From 1be173fb862570d6c3ec9dfda69c4f7f2a14e565 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Thu, 19 Jan 2023 18:08:45 +0100 Subject: [PATCH 01/34] implemented sqlLight and subit locally the campaigns --- android/app/src/main/AndroidManifest.xml | 5 + ic_bg_service_small.png | Bin 0 -> 12937 bytes lib/controllers/login_controller.dart | 113 +++--- .../verifier_campaign_controller.dart | 337 +++++++++++------- lib/main.dart | 8 + lib/models/backgorund_service_model.dart | 68 ++++ lib/models/db_capaign_model.dart | 29 +- lib/models/notification_api.dart | 29 ++ lib/models/verifier_campaign_model.dart | 16 + pubspec.lock | 147 ++++++++ pubspec.yaml | 6 + 11 files changed, 568 insertions(+), 190 deletions(-) create mode 100644 ic_bg_service_small.png create mode 100644 lib/models/backgorund_service_model.dart create mode 100644 lib/models/notification_api.dart diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 7a8d23b..a061140 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -30,8 +30,13 @@ + + + + + diff --git a/ic_bg_service_small.png b/ic_bg_service_small.png new file mode 100644 index 0000000000000000000000000000000000000000..1a406f4a66881078fede563b6f1d1d7d9443afa3 GIT binary patch literal 12937 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 WfBNu^>+8QIfUKmF#2;}Z|NjS;aKI!0 literal 0 HcmV?d00001 diff --git a/lib/controllers/login_controller.dart b/lib/controllers/login_controller.dart index 84a7090..d0cc6f6 100644 --- a/lib/controllers/login_controller.dart +++ b/lib/controllers/login_controller.dart @@ -1,27 +1,35 @@ import 'package:flutter/material.dart'; import 'package:slider_button/slider_button.dart'; +import '../models/backgorund_service_model.dart'; import 'login_metamask_controller.dart'; import '../utils/styles.dart'; import '../models/session_model.dart'; import '../views/home_view.dart'; -class LoginController extends StatelessWidget{ - const LoginController({super.key}); +class LoginController extends StatefulWidget { + const LoginController({Key? key}) : super(key: key); + + @override + State createState() => _LoginControllerState(); +} + +class _LoginControllerState extends State { + bool isRunning = false; + SessionModel sessionData = SessionModel(); + @override Widget build(BuildContext context) { - SessionModel sessionData = SessionModel(); sessionData.checkConnection(); - - return SingleChildScrollView( + return SingleChildScrollView( child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - 'assets/images/main_page_image.png', - fit: BoxFit.fitHeight, - ), - (sessionData.session != null) ? - Container( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/main_page_image.png', + fit: BoxFit.fitHeight, + ), + (sessionData.session != null)? + Container( padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -35,47 +43,52 @@ class LoginController extends StatelessWidget{ style: CustomTextStyle.inconsolata(context), ), const SizedBox(height: 20), - Row( - children: [ - Text( - 'Chain: ', - style: CustomTextStyle.inconsolata(context), - ), - Text( - sessionData.getNetworkName(sessionData.session?.chainId), - style: CustomTextStyle.inconsolata(context), - ), - ]), - const SizedBox(height: 20), - (sessionData - .session - .chainId != 5) ? - Row( - children: const [ - Icon(Icons.warning, color: Colors.redAccent, size: 15), - Text('Network not supported. Switch to '), - Text('Goreli Testnet', - style: TextStyle(fontWeight: FontWeight.bold),) - ]) : + Row(children: [ + Text( + 'Chain: ', + style: CustomTextStyle.inconsolata(context), + ), + Text( + sessionData + .getNetworkName(sessionData.session?.chainId), + style: CustomTextStyle.inconsolata(context), + ), + ]), const SizedBox(height: 20), + (sessionData.session.chainId != 5) + ? Row(children: const [ + Icon(Icons.warning, + color: Colors.redAccent, size: 15), + Text('Network not supported. Switch to '), + Text( + 'Goreli Testnet', + style: TextStyle(fontWeight: FontWeight.bold), + ) + ]) + : const SizedBox(height: 20), Center( - child:SliderButton( - action: () async { - Navigator.pushReplacement(context, MaterialPageRoute( - builder: (context) => const HomeView())); - }, - label: const Text('Slide to login'), - icon: Icon(Icons.arrow_forward_ios_rounded, color: CustomColors.blue900(context)), + child: SliderButton( + action: () async { + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (context) => const HomeView())); + }, + label: const Text('Slide to login'), + icon: Icon(Icons.arrow_forward_ios_rounded, + color: CustomColors.blue900(context)), )) ])) - : ElevatedButton( - style:ButtonStyle(backgroundColor: MaterialStateProperty.all(CustomColors.blue900(context))), - onPressed: () => - Navigator.pushReplacement(context, MaterialPageRoute( + : ElevatedButton( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all( + CustomColors.blue900(context))), + onPressed: () => Navigator.pushReplacement( + context, + MaterialPageRoute( builder: (context) => const LoginMetamaskController())), child: const Text("Connect with Metamask")), - ], - ) - ); + ], + )); } -} \ No newline at end of file +} diff --git a/lib/controllers/verifier_campaign_controller.dart b/lib/controllers/verifier_campaign_controller.dart index a9f38df..e4401f2 100644 --- a/lib/controllers/verifier_campaign_controller.dart +++ b/lib/controllers/verifier_campaign_controller.dart @@ -1,161 +1,240 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:mobile_crowd_sensing/models/verifier_campaign_model.dart'; +import '../models/db_capaign_model.dart'; import '../utils/styles.dart'; import '../models/search_places_model.dart'; import '../models/session_model.dart'; // ignore: must_be_immutable -class VerifierCampaignController extends StatelessWidget { +class VerifierCampaignController extends StatefulWidget { List? contractsAddresses; - VerifierCampaignController(this.contractsAddresses, {super.key}); - SessionModel sessionData = SessionModel(); SearchPlacesModel searchPlacesViewModel = SearchPlacesModel(); + + @override + _VerifierCampaignControllerState createState() => + _VerifierCampaignControllerState(); +} + +class _VerifierCampaignControllerState extends State { + + @override Widget build(BuildContext context) { return FutureBuilder( - future:VerifierCampaignModel.getData(contractsAddresses), + future: VerifierCampaignModel.getData(widget.contractsAddresses), builder: (BuildContext context, AsyncSnapshot snapshot) { switch (snapshot.connectionState) { case ConnectionState.none: + return const Center(child: Text('Sorry something goes wrong...')); + case ConnectionState.waiting: return const Center( - child: Text('Sorry something goes wrong...') + child: CircularProgressIndicator(), ); - case ConnectionState.waiting: - return const Center(child: CircularProgressIndicator(),); default: return _buildPage(context, snapshot); } }); } - // sta qui + String selectedValue = 'photo'; + DbCampaignModel db = DbCampaignModel(); + + _buildPage(BuildContext context, AsyncSnapshot snapshot) { - return (snapshot.data.length>0)? - Container( - padding: const EdgeInsets.fromLTRB(10, 30, 10, 10), - width: double.maxFinite, - child: ListView.builder( - itemCount: snapshot.data.length, - itemBuilder: (context, index) { - List? current = snapshot.data[index]; - String? name,lat,lng,range,type,crowdsourcer,fileCount,contractAddress,readebleLocation; - if (current != null) { - name = current[0]; - lat = current[1].toString(); - lng = current[2].toString(); - range = current[3].toString(); - type = current[4]; - crowdsourcer = current[5].toString(); - fileCount = current[6].toString(); - contractAddress = current[7].toString(); - readebleLocation = current[8]; - } - return GestureDetector( - onTap: () { - Navigator.pushNamed(context, '/verifier_campaign_data', - arguments: { - 'contractAddress': contractAddress, - 'name': name, - 'readebleLocation': readebleLocation, - 'type':type, - 'crowdsourcer': crowdsourcer, - 'range': range, - 'lat': lat, - 'lng': lng, + return (snapshot.data.length > 0) + ? Container( + padding: const EdgeInsets.fromLTRB(10, 30, 10, 10), + width: double.maxFinite, + child: Column(children: [ + DropdownButton( + value: selectedValue, + items: const [ + DropdownMenuItem( + value: 'photo', + child: Text("Photos"), + ), + DropdownMenuItem( + value: 'light', + child: Text("Ambient Light"), + ), + ], + onChanged: (value) { + (context as Element).markNeedsBuild(); + setState(() { + selectedValue = value as String; }); - }, - child: Card( - shadowColor: Colors.blue[600], - color: Colors.white54, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20.0), - ), - child: Padding( - padding: const EdgeInsets.all(20), - child: Stack( - children: [ - Align( - alignment: Alignment.topLeft, - child: Column(children: [ - Row(children: [ - Expanded( - child: Text( - "Name: $name", - style: CustomTextStyle.spaceMono(context), - )), - ]), - Row(children: [ - Text( - "Latitude: ${(int.parse(lat!)/10000000).round()}", - style: CustomTextStyle.spaceMono(context), - ), - ]), - Row(children: [ - Text( - "Longitude: ${(int.parse(lng!)/10000000).round()}", - style: CustomTextStyle.spaceMono(context), - ), - ]), - Column(children: [ - Text( - "Location: $readebleLocation", - style: CustomTextStyle.spaceMono(context)) - ]), - Row(children: [ - Text( - "Range: $range", - style: GoogleFonts.spaceMono( - textStyle: const TextStyle( - color: Colors.black87, - letterSpacing: .5), - fontWeight: FontWeight.normal, - fontSize: 16), - ), - ]), - Row(children: [ - Text( - "Type: $type", - style: CustomTextStyle.spaceMono(context), - ), - ]), - Padding( - padding: const EdgeInsets.all(10), - child: Column( - children: [ - Text( - "crowdsourcer:", - style: CustomTextStyle.spaceMono(context), - ), - FittedBox( - fit: BoxFit.fitWidth, - child: Text( - (crowdsourcer!=null)? crowdsourcer:"null", - style: - CustomTextStyle.spaceMono(context), - )), - ], - ), + }), + Expanded( + child: ListView.builder( + itemCount: snapshot.data.length, + itemBuilder: (context, index) { + List? current = snapshot.data[index]; + print("\n\n DEBUG[current]: \n\n${current.toString()}\n"); + String? name, + lat, + lng, + range, + type, + crowdsourcer, + fileCount, + contractAddress, + readebleLocation, + isSubscribed; + if (current != null) { + name = current[0]; + lat = current[1].toString(); + lng = current[2].toString(); + range = current[3].toString(); + type = current[4]; + crowdsourcer = current[5].toString(); + fileCount = current[6].toString(); + contractAddress = current[7].toString(); + readebleLocation = current[8]; + isSubscribed = current[9]; + } + return GestureDetector( + onTap: () { + Navigator.pushNamed( + context, '/verifier_campaign_data', + arguments: { + 'contractAddress': contractAddress, + 'name': name, + 'readebleLocation': readebleLocation, + 'type': type, + 'crowdsourcer': crowdsourcer, + 'range': range, + 'lat': lat, + 'lng': lng, + }); + }, + child: Card( + shadowColor: Colors.blue[600], + color: Colors.white54, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20.0), + ), + child: Padding( + padding: const EdgeInsets.all(20), + child: Stack( + children: [ + Align( + alignment: Alignment.topRight, + child: ElevatedButton( + style: ButtonStyle( + backgroundColor: (isSubscribed == + 'true') + ? MaterialStateProperty.all( + CustomColors.red600(context)) + : MaterialStateProperty.all( + CustomColors.green600( + context))), + child: (isSubscribed == 'true') + ? const Text('unsubscribe') + : const Text('subscribe'), + onPressed: () async { + if (isSubscribed == 'true') { + await db.deleteCampaign(contractAddress!); + } else { + await db.insertCampaign(Campaign(name, lat, lng, address: contractAddress!)); + } + setState(() {}); + }, + )), + Align( + alignment: Alignment.topLeft, + child: Column(children: [ + Row(children: [ + Expanded( + child: Text( + "Name: $name", + style: CustomTextStyle.spaceMono( + context), + )), + ]), + Row(children: [ + Text( + "Latitude: ${(int.parse(lat!) / 10000000).round()}", + style: CustomTextStyle.spaceMono( + context), + ), + ]), + Row(children: [ + Text( + "Longitude: ${(int.parse(lng!) / 10000000).round()}", + style: CustomTextStyle.spaceMono( + context), + ), + ]), + Column(children: [ + Text("Location: $readebleLocation", + style: CustomTextStyle.spaceMono( + context)) + ]), + Row(children: [ + Text( + "Range: $range", + style: GoogleFonts.spaceMono( + textStyle: const TextStyle( + color: Colors.black87, + letterSpacing: .5), + fontWeight: FontWeight.normal, + fontSize: 16), + ), + ]), + Row(children: [ + Text( + "Type: $type", + style: CustomTextStyle.spaceMono( + context), + ), + ]), + Padding( + padding: const EdgeInsets.all(10), + child: Column( + children: [ + Text( + "crowdsourcer:", + style: CustomTextStyle.spaceMono( + context), + ), + FittedBox( + fit: BoxFit.fitWidth, + child: Text( + (crowdsourcer != null) + ? crowdsourcer + : "null", + style: + CustomTextStyle.spaceMono( + context), + )), + ], + ), + ), + Row(children: [ + Text( + "fileCount: $fileCount", + style: CustomTextStyle.spaceMono( + context), + ), + ]) + ])), + ], ), - Row(children: [ - Text( - "fileCount: $fileCount", - style: CustomTextStyle.spaceMono(context), - ), - ]) - ])), - ], - ), - ), - ), - ); - }), - ): Center(child:Text("No Campaign active at the moment.",style: CustomTextStyle.spaceMono(context),)); + ), + ), + ); + }), + ) + ])) + : Center( + child: Text( + "No Campaign active at the moment.", + style: CustomTextStyle.spaceMono(context), + )); } - - -} \ No newline at end of file +} diff --git a/lib/main.dart b/lib/main.dart index 36f7bed..7759166 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -17,10 +17,17 @@ import 'package:mobile_crowd_sensing/views/search_places_view.dart'; import 'package:mobile_crowd_sensing/views/validate_light_view.dart'; import 'package:mobile_crowd_sensing/views/validate_photo_view.dart'; import 'package:mobile_crowd_sensing/views/wallet_view.dart'; +import 'package:workmanager/workmanager.dart'; +import 'models/backgorund_service_model.dart'; Future main(List args) async { WidgetsFlutterBinding.ensureInitialized(); await FlutterConfig.loadEnvVariables(); + await Workmanager().initialize( + callbackDispatcher, + isInDebugMode: true, + ); + await initializePeriodicTasks(); runApp(const MyApp()); } @@ -29,6 +36,7 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { + return MaterialApp( initialRoute: '/login', routes: { diff --git a/lib/models/backgorund_service_model.dart b/lib/models/backgorund_service_model.dart new file mode 100644 index 0000000..321fafe --- /dev/null +++ b/lib/models/backgorund_service_model.dart @@ -0,0 +1,68 @@ +import 'package:flutter/material.dart'; +import 'package:mobile_crowd_sensing/models/notification_api.dart'; +import 'package:mobile_crowd_sensing/models/session_model.dart'; +import 'package:mobile_crowd_sensing/models/smart_contract_model.dart'; +import 'package:workmanager/workmanager.dart'; + +import 'db_capaign_model.dart'; + +const fetchBackground = "fetchBackground"; + +void callbackDispatcher() { + Workmanager().executeTask((task, inputData) async { + switch (task) { + case fetchBackground: + print("Inizio il task periodico"); + SessionModel sessionData = SessionModel(); + SmartContractModel smartContract = SmartContractModel( + contractAddress: inputData!['address'], + abiName: 'Campaign', + abiFileRoot: 'assets/abi_campaign.json', + provider: sessionData.getProvider()); + List? isClosedRaw = await smartContract.queryCall('isClosed', []); + if (isClosedRaw != null) { + String answer = isClosedRaw[0].toString(); + if (answer == "true") { + NotificationApi.showNotification( + title: "Campaign Closed by corowdsourcer", + body: "this campaign is now colsed:\n ${inputData['title']}", + payload: "Boh"); + } else if (answer == "false") { // to delete + NotificationApi.showNotification( + title: "Campaign still open", + body: "this campaign is:\n ${inputData['title']}", + payload: "Boh"); + } + } else { + return Future.error(StackTrace); + } + break; + } + return Future.value(true); + }); +} + +Future initializePeriodicTasks() async { + DbCampaignModel db = DbCampaignModel(); + List res = await db.campaigns(); + + if (res.isNotEmpty) { + int counter = 0; + for (Campaign c in res) { + await Workmanager().registerPeriodicTask( + "isOpen.${c.address}", + fetchBackground, + //frequency: const Duration(minutes: 15), + initialDelay: const Duration(seconds: 3), + constraints: Constraints(networkType: NetworkType.connected,), + inputData: { + 'address':c.address, + 'title': (c.title != null)? c.title as String : 'NaN', + } + ).then((value) => counter++); + } + + print("sono stati registrati : $counter Tesk periodici"); + } +} + diff --git a/lib/models/db_capaign_model.dart b/lib/models/db_capaign_model.dart index 1ff7380..ed47482 100644 --- a/lib/models/db_capaign_model.dart +++ b/lib/models/db_capaign_model.dart @@ -40,6 +40,8 @@ class DbCampaignModel { cmp.toMap(), conflictAlgorithm: ConflictAlgorithm.replace, ); + print("DEBUG:::::: dentro al db ci sono: \n${(await campaigns()).length} campagne"); + } Future> campaigns() async { @@ -48,10 +50,10 @@ class DbCampaignModel { return List.generate(maps.length, (i) { return Campaign( + maps[i]['title'], + maps[i]['lat'], + maps[i]['lng'], address: maps[i]['address'], - title: maps[i]['title'], - lat: maps[i]['lat'], - lng: maps[i]['lng'], ); }); } @@ -73,18 +75,23 @@ class DbCampaignModel { where: 'address = ?', whereArgs: [address], ); + print("DEBUG:::::: dentro al db ci sono: \n${(await campaigns()).length} campagne"); + } } class Campaign { - final String address, title, lat, lng; - - const Campaign({ - required this.address, - required this.title, - required this.lat, - required this.lng, - }); + final String address; + final String? title, lat, lng; + + const Campaign( + this.title, + this.lat, + this.lng, + { + required this.address, + } + ); Map toMap() { return { diff --git a/lib/models/notification_api.dart b/lib/models/notification_api.dart new file mode 100644 index 0000000..1a7afe0 --- /dev/null +++ b/lib/models/notification_api.dart @@ -0,0 +1,29 @@ + + +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; + +class NotificationApi { + static final _notifications = FlutterLocalNotificationsPlugin(); + + static Future _notificationDetails() async { + return const NotificationDetails( + android: AndroidNotificationDetails( + "channelId", + "channelName", + channelDescription:"channelDescription", + importance: Importance.max + ), + ); + } + + static Future showNotification({ + int id = 0, + String? title, body, payload, + }) async => _notifications.show( + id, + title, + body, + await _notificationDetails(), + payload: payload + ); +} \ No newline at end of file diff --git a/lib/models/verifier_campaign_model.dart b/lib/models/verifier_campaign_model.dart index db2d126..244574c 100644 --- a/lib/models/verifier_campaign_model.dart +++ b/lib/models/verifier_campaign_model.dart @@ -1,3 +1,4 @@ +import 'db_capaign_model.dart'; import 'smart_contract_model.dart'; import 'search_places_model.dart'; import 'session_model.dart'; @@ -9,6 +10,10 @@ class VerifierCampaignModel { List? resInfo = []; List? dataFirstPart = []; + + DbCampaignModel db = DbCampaignModel(); + List res = await db.campaigns(); + if (contractAddress != null) { SmartContractModel smartContractViewModel; for (int i = 0; i < contractAddress.length; i++) { @@ -25,9 +30,20 @@ class VerifierCampaignModel { (double.parse(dataFirstPart[2].toString())) / 10000000)) .toString() .replaceAll(RegExp(r'[^\w\s]+'), '')); + dataFirstPart?.add((await _checkIfIsInCampaignsDb(res,dataFirstPart[7].toString())).toString()); resInfo.add(dataFirstPart); } } return resInfo; } + + static Future _checkIfIsInCampaignsDb(List storedCampaigns,String campaignAddress) async { + Campaign result = storedCampaigns.singleWhere((element) => element.address == campaignAddress, + orElse: () => const Campaign('fake',null, null, address: '')); + if (result.title != "fake") { + return true; + } else { + return false; + } + } } diff --git a/pubspec.lock b/pubspec.lock index ebc7e37..2104c47 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -239,6 +239,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.2.4" + dbus: + dependency: transitive + description: + name: dbus + url: "https://pub.dartlang.org" + source: hosted + version: "0.7.8" + device_info_plus: + dependency: "direct main" + description: + name: device_info_plus + url: "https://pub.dartlang.org" + source: hosted + version: "8.0.0" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "7.0.0" dio: dependency: transitive description: @@ -293,6 +314,34 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_background_service: + dependency: "direct main" + description: + name: flutter_background_service + url: "https://pub.dartlang.org" + source: hosted + version: "2.4.6" + flutter_background_service_android: + dependency: transitive + description: + name: flutter_background_service_android + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.3" + flutter_background_service_ios: + dependency: transitive + description: + name: flutter_background_service_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.4.0" + flutter_background_service_platform_interface: + dependency: transitive + description: + name: flutter_background_service_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" flutter_blurhash: dependency: transitive description: @@ -314,6 +363,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" + flutter_foreground_task: + dependency: "direct main" + description: + name: flutter_foreground_task + url: "https://pub.dartlang.org" + source: hosted + version: "3.10.0" flutter_intl: dependency: "direct main" description: @@ -328,6 +384,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.1" + flutter_local_notifications: + dependency: "direct main" + description: + name: flutter_local_notifications + url: "https://pub.dartlang.org" + source: hosted + version: "13.0.0" + flutter_local_notifications_linux: + dependency: transitive + description: + name: flutter_local_notifications_linux + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + flutter_local_notifications_platform_interface: + dependency: transitive + description: + name: flutter_local_notifications_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.0" flutter_map: dependency: transitive description: @@ -821,6 +898,62 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.1" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.16" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.14" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + shared_preferences_ios: + dependency: transitive + description: + name: shared_preferences_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" shelf: dependency: transitive description: @@ -945,6 +1078,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.4.12" + timezone: + dependency: transitive + description: + name: timezone + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.1" timing: dependency: transitive description: @@ -1106,6 +1246,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" + workmanager: + dependency: "direct main" + description: + name: workmanager + url: "https://pub.dartlang.org" + source: hosted + version: "0.5.1" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 52dae99..8bbcaa8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -59,6 +59,12 @@ dependencies: archive: ^3.3.5 open_street_map_search_and_pick: ^0.0.15 sqflite: ^2.2.3 + flutter_local_notifications: ^13.0.0 + flutter_background_service: ^2.4.6 + device_info_plus: ^8.0.0 + shared_preferences: ^2.0.16 + workmanager: ^0.5.1 + flutter_foreground_task: ^3.10.0 dev_dependencies: flutter_test: From 13a05f7f0622e950f7b24908dcf8eff8c578bd94 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Fri, 20 Jan 2023 17:22:44 +0100 Subject: [PATCH 02/34] la sessione non viene letta nel thread di background --- lib/controllers/login_controller.dart | 15 +- .../verifier_campaign_controller.dart | 4 +- lib/main.dart | 40 +++-- lib/models/backgorund_service_model.dart | 169 ++++++++++++------ lib/models/login_metamask_model.dart | 12 +- lib/models/notification_api.dart | 26 ++- lib/models/session_model.dart | 52 ++++-- pubspec.lock | 14 ++ pubspec.yaml | 2 + 9 files changed, 230 insertions(+), 104 deletions(-) diff --git a/lib/controllers/login_controller.dart b/lib/controllers/login_controller.dart index d0cc6f6..f305c67 100644 --- a/lib/controllers/login_controller.dart +++ b/lib/controllers/login_controller.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:slider_button/slider_button.dart'; -import '../models/backgorund_service_model.dart'; import 'login_metamask_controller.dart'; import '../utils/styles.dart'; import '../models/session_model.dart'; @@ -18,8 +17,13 @@ class _LoginControllerState extends State { SessionModel sessionData = SessionModel(); @override - Widget build(BuildContext context) { + void initState() { + // TODO: implement initState + super.initState(); sessionData.checkConnection(); + } + @override + Widget build(BuildContext context) { return SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -28,7 +32,7 @@ class _LoginControllerState extends State { 'assets/images/main_page_image.png', fit: BoxFit.fitHeight, ), - (sessionData.session != null)? + (sessionData.connector.connected)? Container( padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), child: Column( @@ -50,12 +54,12 @@ class _LoginControllerState extends State { ), Text( sessionData - .getNetworkName(sessionData.session?.chainId), + .getNetworkName(sessionData.connector.session.chainId), style: CustomTextStyle.inconsolata(context), ), ]), const SizedBox(height: 20), - (sessionData.session.chainId != 5) + (sessionData.connector.session.chainId != 5) ? Row(children: const [ Icon(Icons.warning, color: Colors.redAccent, size: 15), @@ -69,6 +73,7 @@ class _LoginControllerState extends State { Center( child: SliderButton( action: () async { + sessionData.killConnection(); Navigator.pushReplacement( context, MaterialPageRoute( diff --git a/lib/controllers/verifier_campaign_controller.dart b/lib/controllers/verifier_campaign_controller.dart index e4401f2..0d4e22e 100644 --- a/lib/controllers/verifier_campaign_controller.dart +++ b/lib/controllers/verifier_campaign_controller.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:mobile_crowd_sensing/models/verifier_campaign_model.dart'; +import '../models/backgorund_service_model.dart'; import '../models/db_capaign_model.dart'; import '../utils/styles.dart'; import '../models/search_places_model.dart'; @@ -74,7 +75,6 @@ class _VerifierCampaignControllerState extends State itemCount: snapshot.data.length, itemBuilder: (context, index) { List? current = snapshot.data[index]; - print("\n\n DEBUG[current]: \n\n${current.toString()}\n"); String? name, lat, lng, @@ -139,8 +139,10 @@ class _VerifierCampaignControllerState extends State onPressed: () async { if (isSubscribed == 'true') { await db.deleteCampaign(contractAddress!); + //await removeTask(contractAddress); } else { await db.insertCampaign(Campaign(name, lat, lng, address: contractAddress!)); + //await addPeriodicTask(name!,contractAddress); } setState(() {}); }, diff --git a/lib/main.dart b/lib/main.dart index 7759166..bb021ab 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_config/flutter_config.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:mobile_crowd_sensing/models/session_model.dart'; import 'package:mobile_crowd_sensing/utils/verifier_campaign_data_factory.dart'; import 'package:mobile_crowd_sensing/views/all_campaign_view.dart'; import 'package:mobile_crowd_sensing/views/close_campaign_view.dart'; @@ -23,11 +25,11 @@ import 'models/backgorund_service_model.dart'; Future main(List args) async { WidgetsFlutterBinding.ensureInitialized(); await FlutterConfig.loadEnvVariables(); - await Workmanager().initialize( - callbackDispatcher, - isInDebugMode: true, - ); - await initializePeriodicTasks(); + // await Workmanager().initialize( + // callbackDispatcher, + // isInDebugMode: true, + // ); + // await initializePeriodicTasks(); runApp(const MyApp()); } @@ -36,7 +38,6 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - return MaterialApp( initialRoute: '/login', routes: { @@ -48,17 +49,22 @@ class MyApp extends StatelessWidget { '/verifier': (context) => const AllCampaignView(cameFrom: 'verifier'), '/map': (context) => const SearchPlacesView(), '/sourcer_campaigns_provider': (context) => const MyCampaignView(), - '/sourcer_close_campaign_provider': (context) => const SourcerPastCampaignsController(), - '/sourcer_close_campaign_service_provider': (context) => const CloseCampaignView(), - '/wallet':(context) => const WalletView(), - '/join_campaign':(context) => JoinCampaignFactory.fromTypeName(context), - '/data_campaign':(context) => WorkerDataCampaignFactory.fromTypeName(context), - "/verifier_campaign_data":(context) => VerifierDataCampaignFactory.fromTypeName(context), - '/camera':(context) => const DataCollectionCameraView(), - '/validate_light_view':(context) => const ValidateLightView(), - '/validate_photo_view':(context) => const ValidatePhotoView(), - '/current_campaign':(context) => const SourcerCampaignView(), + '/sourcer_close_campaign_provider': (context) => + const SourcerPastCampaignsController(), + '/sourcer_close_campaign_service_provider': (context) => + const CloseCampaignView(), + '/wallet': (context) => const WalletView(), + '/join_campaign': (context) => + JoinCampaignFactory.fromTypeName(context), + '/data_campaign': (context) => + WorkerDataCampaignFactory.fromTypeName(context), + "/verifier_campaign_data": (context) => + VerifierDataCampaignFactory.fromTypeName(context), + '/camera': (context) => const DataCollectionCameraView(), + '/validate_light_view': (context) => const ValidateLightView(), + '/validate_photo_view': (context) => const ValidatePhotoView(), + '/current_campaign': (context) => const SourcerCampaignView(), }, ); } -} \ No newline at end of file +} diff --git a/lib/models/backgorund_service_model.dart b/lib/models/backgorund_service_model.dart index 321fafe..07910d8 100644 --- a/lib/models/backgorund_service_model.dart +++ b/lib/models/backgorund_service_model.dart @@ -1,68 +1,125 @@ -import 'package:flutter/material.dart'; import 'package:mobile_crowd_sensing/models/notification_api.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; import 'package:mobile_crowd_sensing/models/smart_contract_model.dart'; -import 'package:workmanager/workmanager.dart'; - import 'db_capaign_model.dart'; -const fetchBackground = "fetchBackground"; - -void callbackDispatcher() { - Workmanager().executeTask((task, inputData) async { - switch (task) { - case fetchBackground: - print("Inizio il task periodico"); - SessionModel sessionData = SessionModel(); - SmartContractModel smartContract = SmartContractModel( - contractAddress: inputData!['address'], - abiName: 'Campaign', - abiFileRoot: 'assets/abi_campaign.json', - provider: sessionData.getProvider()); - List? isClosedRaw = await smartContract.queryCall('isClosed', []); - if (isClosedRaw != null) { - String answer = isClosedRaw[0].toString(); - if (answer == "true") { - NotificationApi.showNotification( - title: "Campaign Closed by corowdsourcer", - body: "this campaign is now colsed:\n ${inputData['title']}", - payload: "Boh"); - } else if (answer == "false") { // to delete - NotificationApi.showNotification( - title: "Campaign still open", - body: "this campaign is:\n ${inputData['title']}", - payload: "Boh"); +import 'dart:async'; +import 'dart:ui'; +import 'package:flutter_background_service/flutter_background_service.dart'; +import 'package:flutter_background_service_android/flutter_background_service_android.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; + +//@pragma('vm:entry-point') +void onStart(ServiceInstance service) async { + // Only available for flutter 3.0.0 and later + DartPluginRegistrant.ensureInitialized(); + + if (service is AndroidServiceInstance) { + service.on('setAsForeground').listen((event) { + service.setAsForegroundService(); + }); + + service.on('setAsBackground').listen((event) { + service.setAsBackgroundService(); + }); + } + + service.on('stopService').listen((event) { + service.stopSelf(); + }); + + DbCampaignModel db = DbCampaignModel(); + List res = await db.campaigns(); + SessionModel session = SessionModel(); + + print("\n DEBUG1_______________________________________\n ${res.toString()}\n"); + print("\n DEBUG2_______________________________________\n ${session.connector.session.toString()}\n"); + + if (res.isNotEmpty) { + int counter = 0; + for (Campaign c in res) { + // bring to foreground + Timer.periodic(const Duration(seconds: 10), (timer) async { + if (service is AndroidServiceInstance) { + if (await service.isForegroundService()) { + //await _process(c.address, c.title!); + } } - } else { - return Future.error(StackTrace); - } - break; + }); + counter++; + } + print("\nsono stati registrati : $counter Tasks periodici\n"); + } else { + print("\nNessun Task da registrare\n"); } - return Future.value(true); - }); + + print('FLUTTER BACKGROUND SERVICE: ${DateTime.now()}'); } -Future initializePeriodicTasks() async { - DbCampaignModel db = DbCampaignModel(); - List res = await db.campaigns(); - - if (res.isNotEmpty) { - int counter = 0; - for (Campaign c in res) { - await Workmanager().registerPeriodicTask( - "isOpen.${c.address}", - fetchBackground, - //frequency: const Duration(minutes: 15), - initialDelay: const Duration(seconds: 3), - constraints: Constraints(networkType: NetworkType.connected,), - inputData: { - 'address':c.address, - 'title': (c.title != null)? c.title as String : 'NaN', - } - ).then((value) => counter++); - } +Future initializeService() async { + final service = FlutterBackgroundService(); + + /// OPTIONAL, using custom notification channel id + AndroidNotificationChannel channel = const AndroidNotificationChannel( + 'my_foreground', // id + 'info', // title + description: + 'This channel is used for important notifications.', // description + importance: Importance.max, + ); + + final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + + await flutterLocalNotificationsPlugin + .resolvePlatformSpecificImplementation< + AndroidFlutterLocalNotificationsPlugin>() + ?.createNotificationChannel(channel); - print("sono stati registrati : $counter Tesk periodici"); - } + await service.configure( + androidConfiguration: AndroidConfiguration( + // this will be executed when app is in foreground or background in separated isolate + onStart: onStart, + + // auto start service + autoStart: true, + isForegroundMode: true, + + // notificationChannelId: 'my_foreground', + // initialNotificationTitle: 'AWESOME SERVICE', + // initialNotificationContent: 'Initializing', + // foregroundServiceNotificationId: 888, + ), + iosConfiguration: IosConfiguration(), + ); + + service.startService(); } + +// Future _process(String address, String title) async { +// SmartContractModel smartContract = SmartContractModel( +// contractAddress: address, +// abiName: 'Campaign', +// abiFileRoot: 'assets/abi_campaign.json', +// provider: ); +// +// List? isClosedRaw = await smartContract.queryCall('isClosed', []); +// if (isClosedRaw != null) { +// String answer = isClosedRaw[0].toString(); +// if (answer == "true") { +// NotificationApi.showNotification( +// title: "Campaign Closed by corowdsourcer", +// body: "this campaign is now colsed:\n $title}", +// payload: "Boh"); +// } else if (answer == "false") { +// // to delete +// NotificationApi.showNotification( +// title: "Campaign still open", +// body: "this campaign is:\n $title", +// payload: "Boh"); +// } +// } else { +// return Future.error(StackTrace); +// } +// } \ No newline at end of file diff --git a/lib/models/login_metamask_model.dart b/lib/models/login_metamask_model.dart index 43ea6ca..2292755 100644 --- a/lib/models/login_metamask_model.dart +++ b/lib/models/login_metamask_model.dart @@ -3,6 +3,8 @@ import 'package:mobile_crowd_sensing/models/session_model.dart'; import 'package:url_launcher/url_launcher_string.dart'; import 'package:walletconnect_dart/walletconnect_dart.dart'; +import 'backgorund_service_model.dart'; + class LoginMetamaskModel { static Future loginUsingMetamask(BuildContext context) async { @@ -17,9 +19,15 @@ class LoginMetamaskModel { }); if(session.accounts.isNotEmpty) { - sessionData.session = session; - print("connesso!"); + sessionData.connector.updateSession(session); + await sessionData.connector.sessionStorage?.store(WalletConnectSession(accounts: session.accounts)); + print('\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++\n' + '+ sessionData indirizzo account: ${sessionData.getAccountAddress()} +\n' + '+ Connector è connesso?: ${sessionData.connector.connected} +\n' + '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n'); + await initializeService(); } + } catch (exp) { print(exp); } diff --git a/lib/models/notification_api.dart b/lib/models/notification_api.dart index 1a7afe0..c1f728c 100644 --- a/lib/models/notification_api.dart +++ b/lib/models/notification_api.dart @@ -1,5 +1,4 @@ - - +import 'package:timezone/timezone.dart' as tz; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; class NotificationApi { @@ -10,8 +9,11 @@ class NotificationApi { android: AndroidNotificationDetails( "channelId", "channelName", - channelDescription:"channelDescription", - importance: Importance.max + channelDescription: "channelDescription", + importance: Importance.max, + priority: Priority.max, + ticker: 'ticker', + icon: 'ic_bg_service_small', ), ); } @@ -26,4 +28,20 @@ class NotificationApi { await _notificationDetails(), payload: payload ); + + static void showScheduledNotification({ + int id = 0, + String? title, body, payload, + required DateTime scheduleDate, + }) async => + _notifications.zonedSchedule( + id, + title, + body, + tz.TZDateTime.from(scheduleDate, tz.local), + await _notificationDetails(), + payload: payload, + uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, + androidAllowWhileIdle: true, + ); } \ No newline at end of file diff --git a/lib/models/session_model.dart b/lib/models/session_model.dart index 62bac3e..aef7d20 100644 --- a/lib/models/session_model.dart +++ b/lib/models/session_model.dart @@ -7,16 +7,19 @@ class SessionModel { static final SessionModel _instance = SessionModel._internal(); - dynamic session, uri, signature; + late dynamic uri, signature; late WalletConnect connector; - late http.Client httpClient; late Web3Client ethClient; + late EthereumWalletConnectProvider provider; - SessionModel._internal() { - httpClient = http.Client(); - ethClient = Web3Client(FlutterConfig.get('ADDRESS_BLOCK_CHAIN'), http.Client()); + factory SessionModel() { + return _instance; + } + Future _initSession() async { + httpClient = http.Client(); + ethClient = Web3Client(FlutterConfig.get('ADDRESS_BLOCK_CHAIN'), httpClient); connector = WalletConnect( bridge: 'https://bridge.walletconnect.org', clientMeta: const PeerMeta( @@ -28,31 +31,42 @@ class SessionModel { ] ) ); + provider = EthereumWalletConnectProvider(connector); + + return provider; } - factory SessionModel() { - return _instance; + SessionModel._internal() { + _initSession(); } EthereumWalletConnectProvider getProvider(){ - return EthereumWalletConnectProvider(connector); + return provider; } dynamic getAccountAddress() { - return session.accounts[0]; + return connector.session.accounts[0]; } Future checkConnection() async { - SessionStorage? sessionStorage = connector.sessionStorage; - if (sessionStorage != null) { - session = sessionStorage.getSession(); - reconnect(); - } else { - await sessionStorage?.store(connector.session); - } - connector.on('connect', (session) => {print('\x1B[31m[checkConnection]\x1B[0m:connect'),reconnect(),this.session = session}); - connector.on('session_update', (payload) =>{print('\x1B[31m[checkConnection]\x1B[0m:session_update'), session = payload}); - connector.on('disconnect', (payload) => {print('\x1B[31m[checkConnection]\x1B[0m:disconnect'),session = null, closeConnection()}); + connector.on('connect', (session) => { + print('\x1B[31m[checkConnection]\x1B[0m:connect'), + reconnect() + }); + connector.on('session_update', (payload) async => { + print('\x1B[31m[checkConnection]\x1B[0m:session_update'), + updateConnection(connector) + }); + connector.on('disconnect', (payload) => { + print('\x1B[31m[checkConnection]\x1B[0m:disconnect'), + closeConnection() + }); + } + + Future updateConnection(WalletConnect c) async { + WalletConnectSession? st = await c.sessionStorage!.getSession(); + SessionStatus current = SessionStatus(chainId: st!.chainId, accounts: st.accounts); + connector.updateSession(current); } void reconnect(){ diff --git a/pubspec.lock b/pubspec.lock index 2104c47..1d14181 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -438,6 +438,13 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_timezone: + dependency: "direct main" + description: + name: flutter_timezone + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" flutter_web_plugins: dependency: transitive description: flutter @@ -667,6 +674,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.4" + observer: + dependency: "direct main" + description: + name: observer + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1" octo_image: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 8bbcaa8..8e510e2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -65,6 +65,8 @@ dependencies: shared_preferences: ^2.0.16 workmanager: ^0.5.1 flutter_foreground_task: ^3.10.0 + flutter_timezone: ^1.0.4 + observer: ^0.0.1 dev_dependencies: flutter_test: From 49ce112d64d42c0f9d6b255d8b817d611c873f08 Mon Sep 17 00:00:00 2001 From: Giacomo Galletti Date: Sat, 21 Jan 2023 12:47:23 +0100 Subject: [PATCH 03/34] working background check campaign open --- lib/controllers/login_controller.dart | 1 - lib/main.dart | 7 +- lib/models/backgorund_service_model.dart | 157 +++++++++++++++-------- lib/models/login_metamask_model.dart | 22 ++-- lib/models/session_model.dart | 2 +- 5 files changed, 114 insertions(+), 75 deletions(-) diff --git a/lib/controllers/login_controller.dart b/lib/controllers/login_controller.dart index f305c67..3b42d94 100644 --- a/lib/controllers/login_controller.dart +++ b/lib/controllers/login_controller.dart @@ -73,7 +73,6 @@ class _LoginControllerState extends State { Center( child: SliderButton( action: () async { - sessionData.killConnection(); Navigator.pushReplacement( context, MaterialPageRoute( diff --git a/lib/main.dart b/lib/main.dart index bb021ab..6aca8bc 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,17 +19,14 @@ import 'package:mobile_crowd_sensing/views/search_places_view.dart'; import 'package:mobile_crowd_sensing/views/validate_light_view.dart'; import 'package:mobile_crowd_sensing/views/validate_photo_view.dart'; import 'package:mobile_crowd_sensing/views/wallet_view.dart'; +import 'package:walletconnect_dart/walletconnect_dart.dart'; import 'package:workmanager/workmanager.dart'; import 'models/backgorund_service_model.dart'; Future main(List args) async { WidgetsFlutterBinding.ensureInitialized(); await FlutterConfig.loadEnvVariables(); - // await Workmanager().initialize( - // callbackDispatcher, - // isInDebugMode: true, - // ); - // await initializePeriodicTasks(); + WalletConnectSession? s = await SessionModel().connector.sessionStorage?.getSession(); runApp(const MyApp()); } diff --git a/lib/models/backgorund_service_model.dart b/lib/models/backgorund_service_model.dart index 07910d8..152b06a 100644 --- a/lib/models/backgorund_service_model.dart +++ b/lib/models/backgorund_service_model.dart @@ -1,8 +1,12 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; import 'package:mobile_crowd_sensing/models/notification_api.dart'; -import 'package:mobile_crowd_sensing/models/session_model.dart'; -import 'package:mobile_crowd_sensing/models/smart_contract_model.dart'; +import 'package:http/http.dart' as http; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:web3dart/contracts.dart'; +import 'package:web3dart/credentials.dart'; +import 'package:web3dart/web3dart.dart'; import 'db_capaign_model.dart'; - import 'dart:async'; import 'dart:ui'; import 'package:flutter_background_service/flutter_background_service.dart'; @@ -11,38 +15,38 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart'; //@pragma('vm:entry-point') void onStart(ServiceInstance service) async { - // Only available for flutter 3.0.0 and later - DartPluginRegistrant.ensureInitialized(); + DbCampaignModel db = DbCampaignModel(); + List res = await db.campaigns(); + SharedPreferences shared = await SharedPreferences.getInstance(); + String? accountAddress = shared.getString('address'); + if(accountAddress == null) { + throw NullThrownError(); + } + if (res.isNotEmpty) { + // Only available for flutter 3.0.0 and later + DartPluginRegistrant.ensureInitialized(); + + if (service is AndroidServiceInstance) { + service.on('setAsForeground').listen((event) { + service.setAsForegroundService(); + }); - if (service is AndroidServiceInstance) { - service.on('setAsForeground').listen((event) { - service.setAsForegroundService(); - }); + service.on('setAsBackground').listen((event) { + service.setAsBackgroundService(); + }); + } - service.on('setAsBackground').listen((event) { - service.setAsBackgroundService(); + service.on('stopService').listen((event) { + service.stopSelf(); }); - } - - service.on('stopService').listen((event) { - service.stopSelf(); - }); - - DbCampaignModel db = DbCampaignModel(); - List res = await db.campaigns(); - SessionModel session = SessionModel(); - print("\n DEBUG1_______________________________________\n ${res.toString()}\n"); - print("\n DEBUG2_______________________________________\n ${session.connector.session.toString()}\n"); - - if (res.isNotEmpty) { int counter = 0; for (Campaign c in res) { - // bring to foreground - Timer.periodic(const Duration(seconds: 10), (timer) async { + Timer.periodic(const Duration(minutes: 30), (timer) async { if (service is AndroidServiceInstance) { if (await service.isForegroundService()) { - //await _process(c.address, c.title!); + print('\x1B[31mEseguo _process per la $counter volta.\x1B[0m'); + await _process(accountAddress,c.address, c.title!); } } }); @@ -85,10 +89,10 @@ Future initializeService() async { autoStart: true, isForegroundMode: true, - // notificationChannelId: 'my_foreground', - // initialNotificationTitle: 'AWESOME SERVICE', - // initialNotificationContent: 'Initializing', - // foregroundServiceNotificationId: 888, + notificationChannelId: 'my_foreground', + initialNotificationTitle: 'AWESOME SERVICE', + initialNotificationContent: 'Initializing', + foregroundServiceNotificationId: 888, ), iosConfiguration: IosConfiguration(), ); @@ -97,29 +101,68 @@ Future initializeService() async { } -// Future _process(String address, String title) async { -// SmartContractModel smartContract = SmartContractModel( -// contractAddress: address, -// abiName: 'Campaign', -// abiFileRoot: 'assets/abi_campaign.json', -// provider: ); -// -// List? isClosedRaw = await smartContract.queryCall('isClosed', []); -// if (isClosedRaw != null) { -// String answer = isClosedRaw[0].toString(); -// if (answer == "true") { -// NotificationApi.showNotification( -// title: "Campaign Closed by corowdsourcer", -// body: "this campaign is now colsed:\n $title}", -// payload: "Boh"); -// } else if (answer == "false") { -// // to delete -// NotificationApi.showNotification( -// title: "Campaign still open", -// body: "this campaign is:\n $title", -// payload: "Boh"); -// } -// } else { -// return Future.error(StackTrace); -// } -// } \ No newline at end of file +Future _process(String accountAdress, String address, String title) async { + SmartContractModel_Bs smartContract = SmartContractModel_Bs( + contractAddress:address, + abiName: 'Campaign', + abiFileRoot: 'assets/abi_campaign.json', + accountAddress: accountAdress); + + List? isClosedRaw = await smartContract.queryCall('isClosed', []); + if (isClosedRaw != null) { + String answer = isClosedRaw[0].toString(); + + if (answer == "true") { + NotificationApi.showNotification( + title: "Campaign Closed by corowdsourcer", + body: "this campaign is now colsed:\n $title}", + payload: "Boh"); + // rimuovi la campagna dal db + } else if (answer == "false") { + print('\x1B[31mThe campaign still open: nothing to notify\x1B[0m'); + } + } else { + return Future.error(StackTrace); + } +} + +class SmartContractModel_Bs { + SmartContractModel_Bs({required this.accountAddress,required this.contractAddress, required this.abiName, required this.abiFileRoot}); + final String accountAddress; + final String contractAddress; + final String abiName; + final String abiFileRoot; + late http.Client httpClient; + late Web3Client ethClient; + + Future loadContract(String contractAddress) async { + String abi = await rootBundle.loadString(abiFileRoot); + final contract = DeployedContract(ContractAbi.fromJson(abi, abiName), + EthereumAddress.fromHex(contractAddress)); + return contract; + } + + Future?> queryCall(String functionName, List args) async { + try { + + httpClient = http.Client(); + ethClient = Web3Client("https://goerli.infura.io/v3/5074605772bb4bc4b6970d2ce999efca", httpClient); + + + final contract = await loadContract(contractAddress); + final ethFunction = contract.function(functionName); + final result = await ethClient.call( + sender: EthereumAddress.fromHex(accountAddress), + contract: contract, + function: ethFunction, + params: args); + List res = result; + return res; + } catch (e) { + if (kDebugMode) { + print('\x1B[31m$e\x1B[0m'); + } + return null; + } + } +} diff --git a/lib/models/login_metamask_model.dart b/lib/models/login_metamask_model.dart index 2292755..0af0312 100644 --- a/lib/models/login_metamask_model.dart +++ b/lib/models/login_metamask_model.dart @@ -1,5 +1,8 @@ +import 'dart:convert'; + import 'package:flutter/cupertino.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher_string.dart'; import 'package:walletconnect_dart/walletconnect_dart.dart'; @@ -17,17 +20,14 @@ class LoginMetamaskModel { sessionData.uri = uri; await launchUrlString(uri, mode: LaunchMode.externalApplication); }); - - if(session.accounts.isNotEmpty) { - sessionData.connector.updateSession(session); - await sessionData.connector.sessionStorage?.store(WalletConnectSession(accounts: session.accounts)); - print('\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++\n' - '+ sessionData indirizzo account: ${sessionData.getAccountAddress()} +\n' - '+ Connector è connesso?: ${sessionData.connector.connected} +\n' - '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n'); - await initializeService(); - } - + SharedPreferences shared = await SharedPreferences.getInstance(); + shared.setString('address', sessionData.getAccountAddress()); + print('\x1B[31m[Filled shared preferences]\x1B[0m'); + print('\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++\n' + '+ sessionData indirizzo account: ${sessionData.getAccountAddress()} +\n' + '+ Connector è connesso?: ${sessionData.connector.connected} +\n' + '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n'); + await initializeService(); } catch (exp) { print(exp); } diff --git a/lib/models/session_model.dart b/lib/models/session_model.dart index aef7d20..2be5c1b 100644 --- a/lib/models/session_model.dart +++ b/lib/models/session_model.dart @@ -1,3 +1,4 @@ +import 'package:shared_preferences/shared_preferences.dart'; import 'package:walletconnect_dart/walletconnect_dart.dart'; import 'package:web3dart/web3dart.dart'; import 'package:flutter_config/flutter_config.dart'; @@ -32,7 +33,6 @@ class SessionModel { ) ); provider = EthereumWalletConnectProvider(connector); - return provider; } From c992bdaaab1f6b3b4d72d217b789fa6ef45d2805 Mon Sep 17 00:00:00 2001 From: Giacomo Galletti Date: Sun, 22 Jan 2023 19:38:17 +0100 Subject: [PATCH 04/34] geofence system refactor of local database added model for iplementing geofence added service to run geofence an elaborate notification --- android/app/src/main/AndroidManifest.xml | 1 + android/gradle.properties | 2 +- lib/controllers/distance_controller.dart | 14 + lib/controllers/geofence_controller.dart | 53 +++ .../verifier_campaign_controller.dart | 311 ++++++++++-------- lib/main.dart | 2 +- lib/models/backgorund_service_model.dart | 168 ---------- lib/models/db_capaign_model.dart | 25 +- lib/models/geofence_model.dart | 95 ++++++ lib/models/login_metamask_model.dart | 8 +- lib/models/notification_api.dart | 47 --- lib/models/verifier_campaign_model.dart | 2 +- lib/services/closed_campaign_service.dart | 198 +++++++++++ lib/services/geofencing_service.dart | 138 ++++++++ lib/services/notification_channels.dart | 21 ++ lib/utils/geofence_status.dart | 7 + pubspec.lock | 56 ++-- pubspec.yaml | 4 +- 18 files changed, 740 insertions(+), 412 deletions(-) create mode 100644 lib/controllers/distance_controller.dart create mode 100644 lib/controllers/geofence_controller.dart delete mode 100644 lib/models/backgorund_service_model.dart create mode 100644 lib/models/geofence_model.dart delete mode 100644 lib/models/notification_api.dart create mode 100644 lib/services/closed_campaign_service.dart create mode 100644 lib/services/geofencing_service.dart create mode 100644 lib/services/notification_channels.dart create mode 100644 lib/utils/geofence_status.dart diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index a061140..98272c8 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -34,6 +34,7 @@ + diff --git a/android/gradle.properties b/android/gradle.properties index 94adc3a..4d3226a 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,3 +1,3 @@ org.gradle.jvmargs=-Xmx1536M android.useAndroidX=true -android.enableJetifier=true +android.enableJetifier=true \ No newline at end of file diff --git a/lib/controllers/distance_controller.dart b/lib/controllers/distance_controller.dart new file mode 100644 index 0000000..82c6c17 --- /dev/null +++ b/lib/controllers/distance_controller.dart @@ -0,0 +1,14 @@ +import 'dart:math'; + +class DistanceController { + + static distanceBetween(lat1, lon1, lat2, lon2) { + var p = 0.017453292519943295; + var c = cos as double Function(num?); + var a = 0.5 - + c((lat2 - lat1) * p) / 2 + + c(lat1 * p) * c(lat2 * p) * (1 - c((lon2 - lon1) * p)) / 2; + return 12742 * asin(sqrt(a)); + } + +} \ No newline at end of file diff --git a/lib/controllers/geofence_controller.dart b/lib/controllers/geofence_controller.dart new file mode 100644 index 0000000..2594d6c --- /dev/null +++ b/lib/controllers/geofence_controller.dart @@ -0,0 +1,53 @@ +import 'dart:async'; +import 'package:flutter/foundation.dart'; +import 'package:mobile_crowd_sensing/models/geofence_model.dart'; +import '../models/db_capaign_model.dart'; +import '../utils/geofence_status.dart'; + +class GeofenceController { + + static List geofenceList = []; + static final DbCampaignModel db = DbCampaignModel(); + static int geofenceActive = 0; + static final GeofenceController _instance = GeofenceController._internal(); + static List?> geofenceStatusStream = []; + + //This singleton class allows to store all + //GeofeceModel in order to manage them and + //streams the result and interact with campaignsDB + + factory GeofenceController() { + return _instance; + } + + GeofenceController._internal(); + + static geofenceInitByDb() async { + List campaigns = await db.campaigns(); + for(Campaign c in campaigns) { + + GeofenceModel g = GeofenceModel( + pointedLatitude: c.lat, + pointedLongitude: c.lng, + radiusMeter: c.radius, + ); + geofenceList.add(g); + g.startGeofenceService(); + geofenceActive++; + } + + if (kDebugMode) { + print("\n Active Geofences: $geofenceActive \n"); + } + } + + static geofenceUpdateByDb() async { + for(GeofenceModel g in geofenceList) { + g.stopGeofenceService(); + geofenceList.remove(g); + } + geofenceActive = 0; + geofenceInitByDb(); + } + +} \ No newline at end of file diff --git a/lib/controllers/verifier_campaign_controller.dart b/lib/controllers/verifier_campaign_controller.dart index 0d4e22e..0dee8cd 100644 --- a/lib/controllers/verifier_campaign_controller.dart +++ b/lib/controllers/verifier_campaign_controller.dart @@ -1,14 +1,11 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:mobile_crowd_sensing/models/verifier_campaign_model.dart'; -import '../models/backgorund_service_model.dart'; import '../models/db_capaign_model.dart'; import '../utils/styles.dart'; import '../models/search_places_model.dart'; import '../models/session_model.dart'; -// ignore: must_be_immutable - class VerifierCampaignController extends StatefulWidget { List? contractsAddresses; VerifierCampaignController(this.contractsAddresses, {super.key}); @@ -42,26 +39,31 @@ class _VerifierCampaignControllerState extends State }); } - String selectedValue = 'photo'; + String selectedValue = 'All Campaigns'; DbCampaignModel db = DbCampaignModel(); - _buildPage(BuildContext context, AsyncSnapshot snapshot) { return (snapshot.data.length > 0) ? Container( padding: const EdgeInsets.fromLTRB(10, 30, 10, 10), width: double.maxFinite, child: Column(children: [ - DropdownButton( + Row( children: [ + Text("filters: ",style: CustomTextStyle.spaceMono(context),), + DropdownButton( value: selectedValue, items: const [ DropdownMenuItem( - value: 'photo', - child: Text("Photos"), + value: 'All Campaigns', + child: Text("All Campaigns"), ), DropdownMenuItem( - value: 'light', - child: Text("Ambient Light"), + value: 'Near Me', + child: Text("Near Me"), + ), + DropdownMenuItem( + value: 'Subscribed', + child: Text("Subscribed"), ), ], onChanged: (value) { @@ -69,7 +71,8 @@ class _VerifierCampaignControllerState extends State setState(() { selectedValue = value as String; }); - }), + }) + ]), Expanded( child: ListView.builder( itemCount: snapshot.data.length, @@ -85,7 +88,7 @@ class _VerifierCampaignControllerState extends State contractAddress, readebleLocation, isSubscribed; - if (current != null) { + if (current != null && _isToShow(current)) { name = current[0]; lat = current[1].toString(); lng = current[2].toString(); @@ -96,140 +99,155 @@ class _VerifierCampaignControllerState extends State contractAddress = current[7].toString(); readebleLocation = current[8]; isSubscribed = current[9]; - } - return GestureDetector( - onTap: () { - Navigator.pushNamed( - context, '/verifier_campaign_data', - arguments: { - 'contractAddress': contractAddress, - 'name': name, - 'readebleLocation': readebleLocation, - 'type': type, - 'crowdsourcer': crowdsourcer, - 'range': range, - 'lat': lat, - 'lng': lng, - }); - }, - child: Card( - shadowColor: Colors.blue[600], - color: Colors.white54, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20.0), - ), - child: Padding( - padding: const EdgeInsets.all(20), - child: Stack( - children: [ - Align( - alignment: Alignment.topRight, - child: ElevatedButton( - style: ButtonStyle( - backgroundColor: (isSubscribed == - 'true') - ? MaterialStateProperty.all( - CustomColors.red600(context)) - : MaterialStateProperty.all( - CustomColors.green600( - context))), - child: (isSubscribed == 'true') - ? const Text('unsubscribe') - : const Text('subscribe'), - onPressed: () async { - if (isSubscribed == 'true') { - await db.deleteCampaign(contractAddress!); - //await removeTask(contractAddress); - } else { - await db.insertCampaign(Campaign(name, lat, lng, address: contractAddress!)); - //await addPeriodicTask(name!,contractAddress); - } - setState(() {}); - }, - )), - Align( - alignment: Alignment.topLeft, - child: Column(children: [ - Row(children: [ - Expanded( - child: Text( - "Name: $name", - style: CustomTextStyle.spaceMono( - context), - )), - ]), - Row(children: [ - Text( - "Latitude: ${(int.parse(lat!) / 10000000).round()}", - style: CustomTextStyle.spaceMono( - context), - ), - ]), - Row(children: [ - Text( - "Longitude: ${(int.parse(lng!) / 10000000).round()}", - style: CustomTextStyle.spaceMono( - context), - ), - ]), - Column(children: [ - Text("Location: $readebleLocation", + return GestureDetector( + onTap: () { + Navigator.pushNamed( + context, '/verifier_campaign_data', + arguments: { + 'contractAddress': contractAddress, + 'name': name, + 'readebleLocation': readebleLocation, + 'type': type, + 'crowdsourcer': crowdsourcer, + 'range': range, + 'lat': lat, + 'lng': lng, + }); + }, + child: Card( + shadowColor: Colors.blue[600], + color: Colors.white54, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20.0), + ), + child: Padding( + padding: const EdgeInsets.all(20), + child: Stack( + children: [ + Align( + alignment: Alignment.topRight, + child: ElevatedButton( + style: ButtonStyle( + backgroundColor: (isSubscribed == + 'true') + ? MaterialStateProperty.all( + CustomColors.red600(context)) + : MaterialStateProperty.all( + CustomColors.green600( + context))), + child: (isSubscribed == 'true') + ? const Text('unsubscribe') + : const Text('subscribe'), + onPressed: () async { + if (isSubscribed == 'true') { + await db.deleteCampaign( + contractAddress!); + //await removeTask(contractAddress); + } else { + await db.insertCampaign( + Campaign( + title: name!, + lat: lat!, + lng: lng!, + radius: range!, + address: contractAddress! + ) + ); + //await addPeriodicTask(name!,contractAddress); + } + setState(() {}); + }, + )), + Align( + alignment: Alignment.topLeft, + child: Column(children: [ + Row(children: [ + Expanded( + child: Text( + "Name: $name", + style: CustomTextStyle + .spaceMono( + context), + )), + ]), + Row(children: [ + Text( + "Latitude: ${(int.parse(lat) / + 10000000).round()}", style: CustomTextStyle.spaceMono( - context)) - ]), - Row(children: [ - Text( - "Range: $range", - style: GoogleFonts.spaceMono( - textStyle: const TextStyle( - color: Colors.black87, - letterSpacing: .5), - fontWeight: FontWeight.normal, - fontSize: 16), - ), - ]), - Row(children: [ - Text( - "Type: $type", - style: CustomTextStyle.spaceMono( - context), - ), - ]), - Padding( - padding: const EdgeInsets.all(10), - child: Column( - children: [ - Text( - "crowdsourcer:", + context), + ), + ]), + Row(children: [ + Text( + "Longitude: ${(int.parse(lng) / + 10000000).round()}", + style: CustomTextStyle.spaceMono( + context), + ), + ]), + Column(children: [ + Text("Location: $readebleLocation", style: CustomTextStyle.spaceMono( - context), - ), - FittedBox( - fit: BoxFit.fitWidth, - child: Text( - (crowdsourcer != null) - ? crowdsourcer - : "null", - style: - CustomTextStyle.spaceMono( - context), - )), - ], - ), - ), - Row(children: [ - Text( - "fileCount: $fileCount", - style: CustomTextStyle.spaceMono( - context), + context)) + ]), + Row(children: [ + Text( + "Range: $range", + style: GoogleFonts.spaceMono( + textStyle: const TextStyle( + color: Colors.black87, + letterSpacing: .5), + fontWeight: FontWeight.normal, + fontSize: 16), + ), + ]), + Row(children: [ + Text( + "Type: $type", + style: CustomTextStyle.spaceMono( + context), + ), + ]), + Padding( + padding: const EdgeInsets.all(10), + child: Column( + children: [ + Text( + "crowdsourcer:", + style: CustomTextStyle + .spaceMono( + context), + ), + FittedBox( + fit: BoxFit.fitWidth, + child: Text( + (crowdsourcer != null) + ? crowdsourcer + : "null", + style: + CustomTextStyle.spaceMono( + context), + )), + ], + ), ), - ]) - ])), - ], + Row(children: [ + Text( + "fileCount: $fileCount", + style: CustomTextStyle.spaceMono( + context), + ), + ]) + ])), + ], + ), ), ), - ), - ); + ); + } else { + return Container(); + } }), ) ])) @@ -239,4 +257,15 @@ class _VerifierCampaignControllerState extends State style: CustomTextStyle.spaceMono(context), )); } + + bool _isToShow(dynamic data){ + switch(selectedValue) { + case "Subscribed": + return (data[9]=="true")? true : false; + case "Near Me": + return data[9]; + default: + return true; + } + } } diff --git a/lib/main.dart b/lib/main.dart index 6aca8bc..6e5f47c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:mobile_crowd_sensing/views/validate_photo_view.dart'; import 'package:mobile_crowd_sensing/views/wallet_view.dart'; import 'package:walletconnect_dart/walletconnect_dart.dart'; import 'package:workmanager/workmanager.dart'; -import 'models/backgorund_service_model.dart'; +import 'services/closed_campaign_service.dart'; Future main(List args) async { WidgetsFlutterBinding.ensureInitialized(); diff --git a/lib/models/backgorund_service_model.dart b/lib/models/backgorund_service_model.dart deleted file mode 100644 index 152b06a..0000000 --- a/lib/models/backgorund_service_model.dart +++ /dev/null @@ -1,168 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; -import 'package:mobile_crowd_sensing/models/notification_api.dart'; -import 'package:http/http.dart' as http; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:web3dart/contracts.dart'; -import 'package:web3dart/credentials.dart'; -import 'package:web3dart/web3dart.dart'; -import 'db_capaign_model.dart'; -import 'dart:async'; -import 'dart:ui'; -import 'package:flutter_background_service/flutter_background_service.dart'; -import 'package:flutter_background_service_android/flutter_background_service_android.dart'; -import 'package:flutter_local_notifications/flutter_local_notifications.dart'; - -//@pragma('vm:entry-point') -void onStart(ServiceInstance service) async { - DbCampaignModel db = DbCampaignModel(); - List res = await db.campaigns(); - SharedPreferences shared = await SharedPreferences.getInstance(); - String? accountAddress = shared.getString('address'); - if(accountAddress == null) { - throw NullThrownError(); - } - if (res.isNotEmpty) { - // Only available for flutter 3.0.0 and later - DartPluginRegistrant.ensureInitialized(); - - if (service is AndroidServiceInstance) { - service.on('setAsForeground').listen((event) { - service.setAsForegroundService(); - }); - - service.on('setAsBackground').listen((event) { - service.setAsBackgroundService(); - }); - } - - service.on('stopService').listen((event) { - service.stopSelf(); - }); - - int counter = 0; - for (Campaign c in res) { - Timer.periodic(const Duration(minutes: 30), (timer) async { - if (service is AndroidServiceInstance) { - if (await service.isForegroundService()) { - print('\x1B[31mEseguo _process per la $counter volta.\x1B[0m'); - await _process(accountAddress,c.address, c.title!); - } - } - }); - counter++; - } - print("\nsono stati registrati : $counter Tasks periodici\n"); - } else { - print("\nNessun Task da registrare\n"); - } - - print('FLUTTER BACKGROUND SERVICE: ${DateTime.now()}'); -} - -Future initializeService() async { - final service = FlutterBackgroundService(); - - /// OPTIONAL, using custom notification channel id - AndroidNotificationChannel channel = const AndroidNotificationChannel( - 'my_foreground', // id - 'info', // title - description: - 'This channel is used for important notifications.', // description - importance: Importance.max, - ); - - final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = - FlutterLocalNotificationsPlugin(); - - await flutterLocalNotificationsPlugin - .resolvePlatformSpecificImplementation< - AndroidFlutterLocalNotificationsPlugin>() - ?.createNotificationChannel(channel); - - await service.configure( - androidConfiguration: AndroidConfiguration( - // this will be executed when app is in foreground or background in separated isolate - onStart: onStart, - - // auto start service - autoStart: true, - isForegroundMode: true, - - notificationChannelId: 'my_foreground', - initialNotificationTitle: 'AWESOME SERVICE', - initialNotificationContent: 'Initializing', - foregroundServiceNotificationId: 888, - ), - iosConfiguration: IosConfiguration(), - ); - - service.startService(); -} - - -Future _process(String accountAdress, String address, String title) async { - SmartContractModel_Bs smartContract = SmartContractModel_Bs( - contractAddress:address, - abiName: 'Campaign', - abiFileRoot: 'assets/abi_campaign.json', - accountAddress: accountAdress); - - List? isClosedRaw = await smartContract.queryCall('isClosed', []); - if (isClosedRaw != null) { - String answer = isClosedRaw[0].toString(); - - if (answer == "true") { - NotificationApi.showNotification( - title: "Campaign Closed by corowdsourcer", - body: "this campaign is now colsed:\n $title}", - payload: "Boh"); - // rimuovi la campagna dal db - } else if (answer == "false") { - print('\x1B[31mThe campaign still open: nothing to notify\x1B[0m'); - } - } else { - return Future.error(StackTrace); - } -} - -class SmartContractModel_Bs { - SmartContractModel_Bs({required this.accountAddress,required this.contractAddress, required this.abiName, required this.abiFileRoot}); - final String accountAddress; - final String contractAddress; - final String abiName; - final String abiFileRoot; - late http.Client httpClient; - late Web3Client ethClient; - - Future loadContract(String contractAddress) async { - String abi = await rootBundle.loadString(abiFileRoot); - final contract = DeployedContract(ContractAbi.fromJson(abi, abiName), - EthereumAddress.fromHex(contractAddress)); - return contract; - } - - Future?> queryCall(String functionName, List args) async { - try { - - httpClient = http.Client(); - ethClient = Web3Client("https://goerli.infura.io/v3/5074605772bb4bc4b6970d2ce999efca", httpClient); - - - final contract = await loadContract(contractAddress); - final ethFunction = contract.function(functionName); - final result = await ethClient.call( - sender: EthereumAddress.fromHex(accountAddress), - contract: contract, - function: ethFunction, - params: args); - List res = result; - return res; - } catch (e) { - if (kDebugMode) { - print('\x1B[31m$e\x1B[0m'); - } - return null; - } - } -} diff --git a/lib/models/db_capaign_model.dart b/lib/models/db_capaign_model.dart index ed47482..0542507 100644 --- a/lib/models/db_capaign_model.dart +++ b/lib/models/db_capaign_model.dart @@ -24,7 +24,8 @@ class DbCampaignModel { 'address TEXT PRIMARY KEY,' ' title TEXT,' ' lat TEXT,' - ' lng TEXT)', + ' lng TEXT,' + ' radius TEXT)', ); }, version: 1, @@ -50,9 +51,10 @@ class DbCampaignModel { return List.generate(maps.length, (i) { return Campaign( - maps[i]['title'], - maps[i]['lat'], - maps[i]['lng'], + title: maps[i]['title'], + lat: maps[i]['lat'], + lng: maps[i]['lng'], + radius: maps[i]['radius'], address: maps[i]['address'], ); }); @@ -81,14 +83,14 @@ class DbCampaignModel { } class Campaign { - final String address; - final String? title, lat, lng; + final String address, title, lat, lng, radius; const Campaign( - this.title, - this.lat, - this.lng, { + required this.title, + required this.lat, + required this.lng, + required this.radius, required this.address, } ); @@ -98,13 +100,14 @@ class Campaign { 'address': address, 'title': title, 'lat': lat, - 'lng': lng + 'lng': lng, + 'radius': radius, }; } @override String toString() { - return 'Campaign{address: $address, name: $title, lat: $lat, lng: $lng}'; + return 'Campaign{address: $address, name: $title, lat: $lat, lng: $lng, radius: $radius}'; } } \ No newline at end of file diff --git a/lib/models/geofence_model.dart b/lib/models/geofence_model.dart new file mode 100644 index 0000000..945aa11 --- /dev/null +++ b/lib/models/geofence_model.dart @@ -0,0 +1,95 @@ +import 'dart:async'; +import 'package:flutter/foundation.dart'; +import 'package:geolocator/geolocator.dart'; +import '../utils/geofence_status.dart'; + +class GeofenceModel { + + late String pointedLatitude, pointedLongitude, radiusMeter; + late int? eventPeriodInSeconds; + + + //documentation: istantiate a Geofance object + // + // if not set eventPeriodInSeconds it will be automatically set to 10 sec + + GeofenceModel( + { + required this.pointedLatitude, + required this.pointedLongitude, + required this.radiusMeter, + this.eventPeriodInSeconds + }); + + StreamSubscription? _positionStream; + + Stream? _geoFencestream; + + final StreamController _controller = StreamController(); + + double _parser(String value) { + if (kDebugMode) { + print("Parse value===>${value.isEmpty}"); + } + double? doubledValue = 0.0; + try { + doubledValue = double.parse(value.isEmpty ? "0" : value); + } catch (e) { + if (kDebugMode) { + print("VALUE IS ===> $value ${value.isEmpty}"); + print("EXCEPTION DOUBLE===> $e"); + } + } + return doubledValue!; + } + + Stream? getGeofenceStream() { + return _geoFencestream; + } + + startGeofenceService() { + //parsing the values to double if in any case they are coming in int etc + double latitude = _parser(pointedLatitude); + double longitude = _parser(pointedLongitude); + double radiusInMeter = _parser(radiusMeter); + //starting the geofence service only if the positionstream is null with us + if (_positionStream == null) { + _geoFencestream = _controller.stream; + _positionStream = Geolocator.getPositionStream( + locationSettings: const LocationSettings(accuracy:LocationAccuracy.high), + ).listen((Position position) { + double distanceInMeters = Geolocator.distanceBetween( + latitude, longitude, position.latitude, position.longitude); + _printOnConsole( + latitude, longitude, position, distanceInMeters, radiusInMeter); + _checkGeofence(distanceInMeters, radiusInMeter); + _positionStream! + .pause(Future.delayed(Duration(seconds: (eventPeriodInSeconds == null)? 10 : eventPeriodInSeconds!))); + }); + _controller.add(GeofenceStatus.init); + } + } + + _checkGeofence(double distanceInMeters, double radiusInMeter) { + if (distanceInMeters <= radiusInMeter) { + _controller.add(GeofenceStatus.enter); + } else { + _controller.add(GeofenceStatus.exit); + } + } + + stopGeofenceService() { + if (_positionStream != null) { + _positionStream!.cancel(); + } + } + + _printOnConsole( + latitude, longitude, Position position, distanceInMeters, radiusInMeter) { + if (kDebugMode) { + print("Started Position $latitude $longitude"); + print("Current Position ${position.toJson()}"); + print("Distance in meters $distanceInMeters and Radius in Meter $radiusInMeter"); + } + } +} diff --git a/lib/models/login_metamask_model.dart b/lib/models/login_metamask_model.dart index 0af0312..a3cbbb2 100644 --- a/lib/models/login_metamask_model.dart +++ b/lib/models/login_metamask_model.dart @@ -1,12 +1,11 @@ -import 'dart:convert'; - import 'package:flutter/cupertino.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; +import 'package:mobile_crowd_sensing/services/geofencing_service.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher_string.dart'; import 'package:walletconnect_dart/walletconnect_dart.dart'; -import 'backgorund_service_model.dart'; +import '../services/closed_campaign_service.dart'; class LoginMetamaskModel { @@ -27,7 +26,8 @@ class LoginMetamaskModel { '+ sessionData indirizzo account: ${sessionData.getAccountAddress()} +\n' '+ Connector è connesso?: ${sessionData.connector.connected} +\n' '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n'); - await initializeService(); + await initializeClosedCampaignService(); + await initializeGeofencingService(); } catch (exp) { print(exp); } diff --git a/lib/models/notification_api.dart b/lib/models/notification_api.dart deleted file mode 100644 index c1f728c..0000000 --- a/lib/models/notification_api.dart +++ /dev/null @@ -1,47 +0,0 @@ -import 'package:timezone/timezone.dart' as tz; -import 'package:flutter_local_notifications/flutter_local_notifications.dart'; - -class NotificationApi { - static final _notifications = FlutterLocalNotificationsPlugin(); - - static Future _notificationDetails() async { - return const NotificationDetails( - android: AndroidNotificationDetails( - "channelId", - "channelName", - channelDescription: "channelDescription", - importance: Importance.max, - priority: Priority.max, - ticker: 'ticker', - icon: 'ic_bg_service_small', - ), - ); - } - - static Future showNotification({ - int id = 0, - String? title, body, payload, - }) async => _notifications.show( - id, - title, - body, - await _notificationDetails(), - payload: payload - ); - - static void showScheduledNotification({ - int id = 0, - String? title, body, payload, - required DateTime scheduleDate, - }) async => - _notifications.zonedSchedule( - id, - title, - body, - tz.TZDateTime.from(scheduleDate, tz.local), - await _notificationDetails(), - payload: payload, - uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, - androidAllowWhileIdle: true, - ); -} \ No newline at end of file diff --git a/lib/models/verifier_campaign_model.dart b/lib/models/verifier_campaign_model.dart index 244574c..47a1897 100644 --- a/lib/models/verifier_campaign_model.dart +++ b/lib/models/verifier_campaign_model.dart @@ -39,7 +39,7 @@ class VerifierCampaignModel { static Future _checkIfIsInCampaignsDb(List storedCampaigns,String campaignAddress) async { Campaign result = storedCampaigns.singleWhere((element) => element.address == campaignAddress, - orElse: () => const Campaign('fake',null, null, address: '')); + orElse: () => const Campaign(title: 'fake', lat: '', lng: '', radius: '', address: '')); if (result.title != "fake") { return true; } else { diff --git a/lib/services/closed_campaign_service.dart b/lib/services/closed_campaign_service.dart new file mode 100644 index 0000000..d757c03 --- /dev/null +++ b/lib/services/closed_campaign_service.dart @@ -0,0 +1,198 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:http/http.dart' as http; +import 'package:mobile_crowd_sensing/services/notification_channels.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:web3dart/contracts.dart'; +import 'package:web3dart/credentials.dart'; +import 'package:web3dart/web3dart.dart'; +import '../models/db_capaign_model.dart'; +import 'dart:async'; +import 'dart:ui'; +import 'package:flutter_background_service/flutter_background_service.dart'; +import 'package:flutter_background_service_android/flutter_background_service_android.dart'; + +//@pragma('vm:entry-point') +void onStart(ServiceInstance service) async { + // Only available for flutter 3.0.0 and later + DartPluginRegistrant.ensureInitialized(); + + if (service is AndroidServiceInstance) { + service.on('setAsForeground').listen((event) { + print('\x1B[31mSet in foreground\x1B[0m'); + service.setAsForegroundService(); + }); + + service.on('setAsBackground').listen((event) { + print('\x1B[31mSet in background\x1B[0m'); + service.setAsBackgroundService(); + }); + } + + service.on('stopService').listen((event) { + print('\x1B[31m stop service\x1B[0m'); + service.stopSelf(); + }); + + DbCampaignModel db = DbCampaignModel(); + List res = await db.campaigns(); + SmartContractModel_Bs smartContract; + if (res.isNotEmpty) { + final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + int counter = 0; + for (Campaign c in res) { + Timer.periodic(const Duration(seconds: 10), (timer) async { + if (kDebugMode) { + print('\x1B[31mEseguo _process per la $counter volta.\x1B[0m'); + } + + SharedPreferences shared = await SharedPreferences.getInstance(); + String? accountAddress = shared.getString('address'); + if (accountAddress == null) { + throw NullThrownError(); + } + String address = c.address; + String title = c.title!; + + smartContract = SmartContractModel_Bs( + contractAddress: address, + abiName: 'Campaign', + abiFileRoot: 'assets/abi_campaign.json', + accountAddress: accountAddress); + + List? isClosedRaw = + await smartContract.queryCall('isClosed', []); + if (isClosedRaw != null) { + String answer = isClosedRaw[0].toString(); + + if (answer == "true") { + if (kDebugMode) { + print('\x1B[31mThe campaign was closed\x1B[0m'); + } + if (service is AndroidServiceInstance) { + if (await service.isForegroundService()) { + + flutterLocalNotificationsPlugin.show( + 888, + 'Campaign Closed', + 'The campaign [$title] \nat address $address \n was closed by crowdsourcer', + const NotificationDetails( + android: AndroidNotificationDetails( + 'important_channel', + 'MY FOREGROUND SERVICE', + icon: 'ic_bg_service_small', + ongoing: true, + ), + ), + ); + } + } + await db.deleteCampaign(address); + } else if (answer == "false") { + print('\x1B[31mThe campaign still open: nothing to notify\x1B[0m'); + } + } else { + return Future.error(StackTrace); + } + }); + counter++; + } + if (kDebugMode) { + print("\nsono stati registrati : $counter Tasks periodici\n"); + } + } else { + if (kDebugMode) { + print('\x1B[31mNessuna camapagna da seguire\x1B[0m'); + } + service.invoke("stopService"); + } +} + +Future initializeClosedCampaignService() async { + DbCampaignModel db = DbCampaignModel(); + List res = await db.campaigns(); + if (res.isNotEmpty) { + print( + '\x1B[31mInizializzazione del servizio [CLOSED CAMPAIGN]\x1B[0m'); + + final service = FlutterBackgroundService(); + + final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + + await flutterLocalNotificationsPlugin + .resolvePlatformSpecificImplementation< + AndroidFlutterLocalNotificationsPlugin>() + ?.createNotificationChannel(NotificationChannel.importantChannel); + + await service.configure( + androidConfiguration: AndroidConfiguration( + // this will be executed when app is in foreground or background in separated isolate + onStart: onStart, + + // auto start service + autoStart: true, + isForegroundMode: true, + + notificationChannelId: 'important_channel', + initialNotificationTitle: 'closing campaign service', + initialNotificationContent: + 'this service notify eventually submitted campaign closed', + foregroundServiceNotificationId: 888, + ), + iosConfiguration: IosConfiguration(), + ); + + service.startService(); + } else { + print('\x1B[31mThe database is empty. no services to initialize\x1B[0m'); + } +} + +class SmartContractModel_Bs { + SmartContractModel_Bs( + {required this.accountAddress, + required this.contractAddress, + required this.abiName, + required this.abiFileRoot}); + final String accountAddress; + final String contractAddress; + final String abiName; + final String abiFileRoot; + late http.Client httpClient; + late Web3Client ethClient; + + Future loadContract(String contractAddress) async { + String abi = await rootBundle.loadString(abiFileRoot); + final contract = DeployedContract(ContractAbi.fromJson(abi, abiName), + EthereumAddress.fromHex(contractAddress)); + return contract; + } + + Future?> queryCall( + String functionName, List args) async { + try { + httpClient = http.Client(); + ethClient = Web3Client( + "https://goerli.infura.io/v3/5074605772bb4bc4b6970d2ce999efca", + httpClient); + + final contract = await loadContract(contractAddress); + final ethFunction = contract.function(functionName); + final result = await ethClient.call( + sender: EthereumAddress.fromHex(accountAddress), + contract: contract, + function: ethFunction, + params: args); + List res = result; + return res; + } catch (e) { + if (kDebugMode) { + print('\x1B[31m$e\x1B[0m'); + } + return null; + } + } +} diff --git a/lib/services/geofencing_service.dart b/lib/services/geofencing_service.dart new file mode 100644 index 0000000..c239ca0 --- /dev/null +++ b/lib/services/geofencing_service.dart @@ -0,0 +1,138 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:geolocator/geolocator.dart'; +import 'package:mobile_crowd_sensing/controllers/geofence_controller.dart'; +import 'package:mobile_crowd_sensing/services/notification_channels.dart'; +import '../models/db_capaign_model.dart'; +import 'dart:async'; +import 'dart:ui'; +import 'package:flutter_background_service/flutter_background_service.dart'; +import 'package:flutter_background_service_android/flutter_background_service_android.dart'; +import '../models/geofence_model.dart'; +import '../utils/geofence_status.dart'; + +//@pragma('vm:entry-point') +void onStart(ServiceInstance service) async { + DbCampaignModel db = DbCampaignModel(); + List res = await db.campaigns(); + if (res.isNotEmpty) { + // Only available for flutter 3.0.0 and later + DartPluginRegistrant.ensureInitialized(); + + if (service is AndroidServiceInstance) { + service.on('setAsForeground').listen((event) { + print('\x1B[31m [GEOFENCE SERVICE]Set in foreground\x1B[0m'); + service.setAsForegroundService(); + }); + + service.on('setAsBackground').listen((event) { + print('\x1B[31m [GEOFENCE SERVICE]Set in background\x1B[0m'); + service.setAsBackgroundService(); + }); + } + + service.on('stopService').listen((event) { + print('\x1B[31m [GEOFENCE SERVICE]stop service\x1B[0m'); + service.stopSelf(); + }); + + final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + + for (GeofenceModel g in GeofenceController.geofenceList) { + g.getGeofenceStream()!.listen((event) { + switch(event) { + case GeofenceStatus.enter: + if (kDebugMode) { + print('\x1B[31m [GEOFENCE SERVICE] Enter Status \x1B[0m'); + } + flutterLocalNotificationsPlugin.show( + 999, + 'Enter in a Campaign area', + 'you are inside a Campaign area', + const NotificationDetails( + android: AndroidNotificationDetails( + 'important_channel', + 'MY FOREGROUND SERVICE', + icon: 'ic_bg_service_small', + ongoing: true, + ), + )); + break; + case GeofenceStatus.exit: + if (kDebugMode) { + print('\x1B[31m [GEOFENCE SERVICE] Exit Status \x1B[0m'); + } + flutterLocalNotificationsPlugin.show( + 999, + 'Exit from Campaign area', + 'you are out from the area', + const NotificationDetails( + android: AndroidNotificationDetails( + 'important_channel', + 'MY FOREGROUND SERVICE', + icon: 'ic_bg_service_small', + ongoing: true, + ), + ), + ); + break; + case GeofenceStatus.init: + if (kDebugMode) { + print('\x1B[31m [GEOFENCE SERVICE] init Status \x1B[0m'); + } + break; + } + }); + } + } else { + if (kDebugMode) { + print('\x1B[31m [GEOFENCE SERVICE] database empty: the service ' + 'was closed after start\x1B[0m'); + } + service.stopSelf(); + } +} + +Future initializeGeofencingService() async { + DbCampaignModel db = DbCampaignModel(); + List res = await db.campaigns(); + if (res.isNotEmpty) { + await Geolocator.requestPermission(); + print('\x1B[31m [GEOFENCE SERVICE]Inizializzazione del servizio: [GEOFENCE]\x1B[0m'); + + GeofenceController.geofenceInitByDb(); + + FlutterBackgroundService service = FlutterBackgroundService(); + + final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + + await flutterLocalNotificationsPlugin + .resolvePlatformSpecificImplementation< + AndroidFlutterLocalNotificationsPlugin>() + ?.createNotificationChannel(NotificationChannel.importantChannel); + + await service.configure( + androidConfiguration: AndroidConfiguration( + // this will be executed when app is in foreground or background in separated isolate + onStart: onStart, + + // auto start service + autoStart: true, + isForegroundMode: true, + + notificationChannelId: 'important_channel', + initialNotificationTitle: 'geofence service', + initialNotificationContent: + 'this service notify eventually submitted campaign area entrance', + foregroundServiceNotificationId: 999, + ), + iosConfiguration: IosConfiguration(), + ); + + service.startService(); + } else { + print('\x1B[31m [GEOFENCE SERVICE]The database is empty. no services to initialize\x1B[0m'); + } +} diff --git a/lib/services/notification_channels.dart b/lib/services/notification_channels.dart new file mode 100644 index 0000000..eedf97f --- /dev/null +++ b/lib/services/notification_channels.dart @@ -0,0 +1,21 @@ +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; + +class NotificationChannel { + static AndroidNotificationChannel importantChannel = + const AndroidNotificationChannel( + 'important_channel', // id + 'IMPORTANT NOTIFICATION CHANNEL', // title + description: + 'This channel is used for important notification.', // description + importance: Importance.max, // importance must be at low or higher level + ); + + static AndroidNotificationChannel lowImportantChannel = + const AndroidNotificationChannel( + 'low_important_channel', // id + 'LOW IMPORTANT NOTIFICATION CHANNEL', // title + description: + 'This channel is used for not important notification.', // description + importance: Importance.low, // importance must be at low or higher level + ); +} diff --git a/lib/utils/geofence_status.dart b/lib/utils/geofence_status.dart new file mode 100644 index 0000000..8e1b618 --- /dev/null +++ b/lib/utils/geofence_status.dart @@ -0,0 +1,7 @@ +/// +/// Geofence events state +/// [init]: this is triggered when geofence service started +/// [enter]: this is triggered when the device current location is in the allocated geofence area +/// [exit]: this is triggered when the device current location is outside of the allocated geofence area +/// +enum GeofenceStatus { init, enter, exit } diff --git a/pubspec.lock b/pubspec.lock index 1d14181..f7dc97a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -28,7 +28,7 @@ packages: name: args url: "https://pub.dartlang.org" source: hosted - version: "2.3.1" + version: "2.3.2" async: dependency: transitive description: @@ -126,35 +126,35 @@ packages: name: camera url: "https://pub.dartlang.org" source: hosted - version: "0.10.2" + version: "0.10.2+1" camera_android: dependency: transitive description: name: camera_android url: "https://pub.dartlang.org" source: hosted - version: "0.10.2+2" + version: "0.10.2+3" camera_avfoundation: dependency: transitive description: name: camera_avfoundation url: "https://pub.dartlang.org" source: hosted - version: "0.9.10+1" + version: "0.9.10+2" camera_platform_interface: dependency: transitive description: name: camera_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.3.3" + version: "2.3.4" camera_web: dependency: transitive description: name: camera_web url: "https://pub.dartlang.org" source: hosted - version: "0.3.1" + version: "0.3.1+1" characters: dependency: transitive description: @@ -438,13 +438,6 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_timezone: - dependency: "direct main" - description: - name: flutter_timezone - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.4" flutter_web_plugins: dependency: transitive description: flutter @@ -582,7 +575,7 @@ packages: name: io url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.0.4" ipfs_client_flutter: dependency: "direct main" description: @@ -603,7 +596,7 @@ packages: name: json_annotation url: "https://pub.dartlang.org" source: hosted - version: "4.7.0" + version: "4.8.0" json_rpc_2: dependency: transitive description: @@ -674,13 +667,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.4" - observer: - dependency: "direct main" - description: - name: observer - url: "https://pub.dartlang.org" - source: hosted - version: "0.0.1" octo_image: dependency: transitive description: @@ -918,21 +904,21 @@ packages: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "2.0.16" + version: "2.0.17" shared_preferences_android: dependency: transitive description: name: shared_preferences_android url: "https://pub.dartlang.org" source: hosted - version: "2.0.14" + version: "2.0.15" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.2" shared_preferences_ios: dependency: transitive description: @@ -946,7 +932,7 @@ packages: name: shared_preferences_linux url: "https://pub.dartlang.org" source: hosted - version: "2.1.2" + version: "2.1.3" shared_preferences_platform_interface: dependency: transitive description: @@ -967,7 +953,7 @@ packages: name: shared_preferences_windows url: "https://pub.dartlang.org" source: hosted - version: "2.1.2" + version: "2.1.3" shelf: dependency: transitive description: @@ -1105,7 +1091,7 @@ packages: name: timing url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.0.1" tuple: dependency: transitive description: @@ -1140,35 +1126,35 @@ packages: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "6.1.7" + version: "6.1.8" url_launcher_android: dependency: transitive description: name: url_launcher_android url: "https://pub.dartlang.org" source: hosted - version: "6.0.22" + version: "6.0.23" url_launcher_ios: dependency: transitive description: name: url_launcher_ios url: "https://pub.dartlang.org" source: hosted - version: "6.0.17" + version: "6.0.18" url_launcher_linux: dependency: transitive description: name: url_launcher_linux url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.2" url_launcher_macos: dependency: transitive description: name: url_launcher_macos url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.2" url_launcher_platform_interface: dependency: transitive description: @@ -1182,14 +1168,14 @@ packages: name: url_launcher_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.13" + version: "2.0.14" url_launcher_windows: dependency: transitive description: name: url_launcher_windows url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.2" uuid: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 8e510e2..6c1efe0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -38,7 +38,7 @@ dependencies: walletconnect_dart: ^0.0.11 google_fonts: ^3.0.1 slider_button: ^2.0.0 - web3dart: ^2.4.1 + web3dart: #latest version geolocator: #latest version geocoding: #latest version flutter_intl: ^0.0.1 @@ -65,8 +65,6 @@ dependencies: shared_preferences: ^2.0.16 workmanager: ^0.5.1 flutter_foreground_task: ^3.10.0 - flutter_timezone: ^1.0.4 - observer: ^0.0.1 dev_dependencies: flutter_test: From d6b77c32186845af2455005bc2cb2b01d393b3dc Mon Sep 17 00:00:00 2001 From: Giacomo Galletti Date: Mon, 23 Jan 2023 20:27:37 +0100 Subject: [PATCH 05/34] fix managing services --- lib/controllers/geofence_controller.dart | 2 +- .../verifier_campaign_controller.dart | 198 ++++++++----- lib/models/db_capaign_model.dart | 7 + lib/models/geofence_model.dart | 2 +- lib/models/login_metamask_model.dart | 32 +- lib/services/closed_campaign_service.dart | 274 ++++++++++-------- lib/{utils => services}/geofence_status.dart | 0 lib/services/geofencing_service.dart | 50 ++-- pubspec.lock | 14 + pubspec.yaml | 1 + 10 files changed, 352 insertions(+), 228 deletions(-) rename lib/{utils => services}/geofence_status.dart (100%) diff --git a/lib/controllers/geofence_controller.dart b/lib/controllers/geofence_controller.dart index 2594d6c..486aef8 100644 --- a/lib/controllers/geofence_controller.dart +++ b/lib/controllers/geofence_controller.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:mobile_crowd_sensing/models/geofence_model.dart'; import '../models/db_capaign_model.dart'; -import '../utils/geofence_status.dart'; +import '../services/geofence_status.dart'; class GeofenceController { diff --git a/lib/controllers/verifier_campaign_controller.dart b/lib/controllers/verifier_campaign_controller.dart index 0dee8cd..bf0f618 100644 --- a/lib/controllers/verifier_campaign_controller.dart +++ b/lib/controllers/verifier_campaign_controller.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:mobile_crowd_sensing/models/verifier_campaign_model.dart'; +import 'package:numberpicker/numberpicker.dart'; import '../models/db_capaign_model.dart'; import '../utils/styles.dart'; import '../models/search_places_model.dart'; @@ -12,15 +13,13 @@ class VerifierCampaignController extends StatefulWidget { SessionModel sessionData = SessionModel(); SearchPlacesModel searchPlacesViewModel = SearchPlacesModel(); - @override _VerifierCampaignControllerState createState() => _VerifierCampaignControllerState(); } -class _VerifierCampaignControllerState extends State { - - +class _VerifierCampaignControllerState + extends State { @override Widget build(BuildContext context) { return FutureBuilder( @@ -30,15 +29,67 @@ class _VerifierCampaignControllerState extends State case ConnectionState.none: return const Center(child: Text('Sorry something goes wrong...')); case ConnectionState.waiting: - return const Center( - child: CircularProgressIndicator(), - ); + return Container( + padding: const EdgeInsets.fromLTRB(10, 30, 10, 10), + width: double.maxFinite, + child: Column(children: [ + Row(children: [ + Text( + "filters: ", + style: CustomTextStyle.spaceMono(context), + ), + DropdownButton( + value: selectedValue, + items: const [ + DropdownMenuItem( + value: 'All Campaigns', + child: Text("All Campaigns"), + ), + DropdownMenuItem( + value: 'Near Me', + child: Text("Near Me"), + ), + DropdownMenuItem( + value: 'Subscribed', + child: Text("Subscribed"), + ), + ], + onChanged: (value) { + (context as Element).markNeedsBuild(); + setState(() { + selectedValue = value as String; + }); + }), + (selectedValue == "Near Me")? + Column(children: [ + NumberPicker( + itemHeight: 18, + value: _currentIntValue, + minValue: 0, + maxValue: 100, + step: 10, + haptics: true, + onChanged: (value) => setState(() => _currentIntValue = value), + ), + ]) + : + Container(), + ]), + Expanded( + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + CircularProgressIndicator(), + ])) + ])); default: return _buildPage(context, snapshot); } }); } - + int _currentIntValue = 10; String selectedValue = 'All Campaigns'; DbCampaignModel db = DbCampaignModel(); @@ -48,30 +99,47 @@ class _VerifierCampaignControllerState extends State padding: const EdgeInsets.fromLTRB(10, 30, 10, 10), width: double.maxFinite, child: Column(children: [ - Row( children: [ - Text("filters: ",style: CustomTextStyle.spaceMono(context),), + Row(children: [ + Text( + "filters: ", + style: CustomTextStyle.spaceMono(context), + ), DropdownButton( - value: selectedValue, - items: const [ - DropdownMenuItem( - value: 'All Campaigns', - child: Text("All Campaigns"), - ), - DropdownMenuItem( - value: 'Near Me', - child: Text("Near Me"), - ), - DropdownMenuItem( - value: 'Subscribed', - child: Text("Subscribed"), - ), - ], - onChanged: (value) { - (context as Element).markNeedsBuild(); - setState(() { - selectedValue = value as String; - }); - }) + value: selectedValue, + items: const [ + DropdownMenuItem( + value: 'All Campaigns', + child: Text("All Campaigns"), + ), + DropdownMenuItem( + value: 'Near Me', + child: Text("Near Me"), + ), + DropdownMenuItem( + value: 'Subscribed', + child: Text("Subscribed"), + ), + ], + onChanged: (value) { + (context as Element).markNeedsBuild(); + setState(() { + selectedValue = value as String; + }); + }), + (selectedValue == "Near Me")? + Column(children: [ + NumberPicker( + itemHeight: 18, + value: _currentIntValue, + minValue: 0, + maxValue: 100, + step: 10, + haptics: true, + onChanged: (value) => setState(() => _currentIntValue = value), + ), + ]) + : + Container(), ]), Expanded( child: ListView.builder( @@ -90,8 +158,10 @@ class _VerifierCampaignControllerState extends State isSubscribed; if (current != null && _isToShow(current)) { name = current[0]; - lat = current[1].toString(); - lng = current[2].toString(); + lat = (int.parse(current[1].toString()) / 10000000) + .toString(); + lng = (int.parse(current[2].toString()) / 10000000) + .toString(); range = current[3].toString(); type = current[4]; crowdsourcer = current[5].toString(); @@ -128,13 +198,14 @@ class _VerifierCampaignControllerState extends State alignment: Alignment.topRight, child: ElevatedButton( style: ButtonStyle( - backgroundColor: (isSubscribed == - 'true') - ? MaterialStateProperty.all( - CustomColors.red600(context)) - : MaterialStateProperty.all( - CustomColors.green600( - context))), + backgroundColor: + (isSubscribed == 'true') + ? MaterialStateProperty.all( + CustomColors.red600( + context)) + : MaterialStateProperty.all( + CustomColors.green600( + context))), child: (isSubscribed == 'true') ? const Text('unsubscribe') : const Text('subscribe'), @@ -144,15 +215,12 @@ class _VerifierCampaignControllerState extends State contractAddress!); //await removeTask(contractAddress); } else { - await db.insertCampaign( - Campaign( - title: name!, - lat: lat!, - lng: lng!, - radius: range!, - address: contractAddress! - ) - ); + await db.insertCampaign(Campaign( + title: name!, + lat: lat!, + lng: lng!, + radius: range!, + address: contractAddress!)); //await addPeriodicTask(name!,contractAddress); } setState(() {}); @@ -164,24 +232,21 @@ class _VerifierCampaignControllerState extends State Row(children: [ Expanded( child: Text( - "Name: $name", - style: CustomTextStyle - .spaceMono( - context), - )), + "Name: $name", + style: CustomTextStyle.spaceMono( + context), + )), ]), Row(children: [ Text( - "Latitude: ${(int.parse(lat) / - 10000000).round()}", + "Latitude: $lat", style: CustomTextStyle.spaceMono( context), ), ]), Row(children: [ Text( - "Longitude: ${(int.parse(lng) / - 10000000).round()}", + "Longitude: $lng", style: CustomTextStyle.spaceMono( context), ), @@ -215,9 +280,9 @@ class _VerifierCampaignControllerState extends State children: [ Text( "crowdsourcer:", - style: CustomTextStyle - .spaceMono( - context), + style: + CustomTextStyle.spaceMono( + context), ), FittedBox( fit: BoxFit.fitWidth, @@ -225,9 +290,8 @@ class _VerifierCampaignControllerState extends State (crowdsourcer != null) ? crowdsourcer : "null", - style: - CustomTextStyle.spaceMono( - context), + style: CustomTextStyle + .spaceMono(context), )), ], ), @@ -258,10 +322,10 @@ class _VerifierCampaignControllerState extends State )); } - bool _isToShow(dynamic data){ - switch(selectedValue) { + bool _isToShow(dynamic data) { + switch (selectedValue) { case "Subscribed": - return (data[9]=="true")? true : false; + return (data[9] == "true") ? true : false; case "Near Me": return data[9]; default: diff --git a/lib/models/db_capaign_model.dart b/lib/models/db_capaign_model.dart index 0542507..522d87f 100644 --- a/lib/models/db_capaign_model.dart +++ b/lib/models/db_capaign_model.dart @@ -2,6 +2,8 @@ import 'dart:async'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; +import '../services/closed_campaign_service.dart'; + class DbCampaignModel { static final DbCampaignModel _instance = DbCampaignModel._internal(); @@ -41,6 +43,11 @@ class DbCampaignModel { cmp.toMap(), conflictAlgorithm: ConflictAlgorithm.replace, ); + + if(ClosedCampaignService().checkIfInitialized()) { + print('\x1B[31m[INITIALIZE AFTER INSERT IN DB]\x1B[0m'); + await ClosedCampaignService().initializeClosedCampaignService(); + } print("DEBUG:::::: dentro al db ci sono: \n${(await campaigns()).length} campagne"); } diff --git a/lib/models/geofence_model.dart b/lib/models/geofence_model.dart index 945aa11..1712565 100644 --- a/lib/models/geofence_model.dart +++ b/lib/models/geofence_model.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:geolocator/geolocator.dart'; -import '../utils/geofence_status.dart'; +import '../services/geofence_status.dart'; class GeofenceModel { diff --git a/lib/models/login_metamask_model.dart b/lib/models/login_metamask_model.dart index a3cbbb2..47ab0bf 100644 --- a/lib/models/login_metamask_model.dart +++ b/lib/models/login_metamask_model.dart @@ -1,10 +1,9 @@ import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; import 'package:mobile_crowd_sensing/services/geofencing_service.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher_string.dart'; -import 'package:walletconnect_dart/walletconnect_dart.dart'; - import '../services/closed_campaign_service.dart'; class LoginMetamaskModel { @@ -14,25 +13,34 @@ class LoginMetamaskModel { sessionData.checkConnection(); if (!sessionData.connector.connected) { try { - SessionStatus session = await sessionData.connector.createSession( + await sessionData.connector.createSession( onDisplayUri: (uri) async { sessionData.uri = uri; await launchUrlString(uri, mode: LaunchMode.externalApplication); }); SharedPreferences shared = await SharedPreferences.getInstance(); shared.setString('address', sessionData.getAccountAddress()); - print('\x1B[31m[Filled shared preferences]\x1B[0m'); - print('\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++\n' - '+ sessionData indirizzo account: ${sessionData.getAccountAddress()} +\n' - '+ Connector è connesso?: ${sessionData.connector.connected} +\n' - '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n'); - await initializeClosedCampaignService(); - await initializeGeofencingService(); + if (kDebugMode) { + print('\x1B[31m[Filled shared preferences]\x1B[0m'); + print('\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++\n' + '+ sessionData indirizzo account: ${sessionData.getAccountAddress()} +\n' + '+ Connector è connesso?: ${sessionData.connector.connected} +\n' + '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n'); + } + if(!ClosedCampaignService().checkIfInitialized()) { + print('\x1B[31m[INITIALIZE AFTER LOGIN]\x1B[0m'); + await ClosedCampaignService().initializeClosedCampaignService(); + } + //await initializeGeofencingService(); } catch (exp) { - print(exp); + if (kDebugMode) { + print(exp); + } } } else { - print("già connesso..."); + if (kDebugMode) { + print("già connesso..."); + } } } } \ No newline at end of file diff --git a/lib/services/closed_campaign_service.dart b/lib/services/closed_campaign_service.dart index d757c03..ff2d0e5 100644 --- a/lib/services/closed_campaign_service.dart +++ b/lib/services/closed_campaign_service.dart @@ -13,146 +13,168 @@ import 'dart:ui'; import 'package:flutter_background_service/flutter_background_service.dart'; import 'package:flutter_background_service_android/flutter_background_service_android.dart'; -//@pragma('vm:entry-point') -void onStart(ServiceInstance service) async { - // Only available for flutter 3.0.0 and later - DartPluginRegistrant.ensureInitialized(); - - if (service is AndroidServiceInstance) { - service.on('setAsForeground').listen((event) { - print('\x1B[31mSet in foreground\x1B[0m'); - service.setAsForegroundService(); - }); +class ClosedCampaignService { - service.on('setAsBackground').listen((event) { - print('\x1B[31mSet in background\x1B[0m'); - service.setAsBackgroundService(); - }); + + static final ClosedCampaignService _instance = ClosedCampaignService._internal(); + + static late bool isInitialized; + + void setIsInizialized(bool status) { + ClosedCampaignService.isInitialized = status; } - service.on('stopService').listen((event) { - print('\x1B[31m stop service\x1B[0m'); - service.stopSelf(); - }); - - DbCampaignModel db = DbCampaignModel(); - List res = await db.campaigns(); - SmartContractModel_Bs smartContract; - if (res.isNotEmpty) { - final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = - FlutterLocalNotificationsPlugin(); - int counter = 0; - for (Campaign c in res) { - Timer.periodic(const Duration(seconds: 10), (timer) async { - if (kDebugMode) { - print('\x1B[31mEseguo _process per la $counter volta.\x1B[0m'); - } + bool checkIfInitialized() { + return ClosedCampaignService.isInitialized; + } - SharedPreferences shared = await SharedPreferences.getInstance(); - String? accountAddress = shared.getString('address'); - if (accountAddress == null) { - throw NullThrownError(); - } - String address = c.address; - String title = c.title!; - - smartContract = SmartContractModel_Bs( - contractAddress: address, - abiName: 'Campaign', - abiFileRoot: 'assets/abi_campaign.json', - accountAddress: accountAddress); - - List? isClosedRaw = - await smartContract.queryCall('isClosed', []); - if (isClosedRaw != null) { - String answer = isClosedRaw[0].toString(); - - if (answer == "true") { - if (kDebugMode) { - print('\x1B[31mThe campaign was closed\x1B[0m'); - } - if (service is AndroidServiceInstance) { - if (await service.isForegroundService()) { - - flutterLocalNotificationsPlugin.show( - 888, - 'Campaign Closed', - 'The campaign [$title] \nat address $address \n was closed by crowdsourcer', - const NotificationDetails( - android: AndroidNotificationDetails( - 'important_channel', - 'MY FOREGROUND SERVICE', - icon: 'ic_bg_service_small', - ongoing: true, + factory ClosedCampaignService() { + return _instance; + } + + ClosedCampaignService._internal() { + ClosedCampaignService.isInitialized = false; + } + + static void onStart(ServiceInstance service) async { + DartPluginRegistrant.ensureInitialized(); + + Timer.periodic(const Duration(seconds: 10), (timer) async { + DbCampaignModel db = DbCampaignModel(); + List res = await db.campaigns(); + SmartContractModelBs smartContract; + if (kDebugMode) { + print( + '\x1B[31m[CLOSED CAMPAIGN SERVICE]check db. IS EMPTY? ${res.isEmpty} \x1B[0m'); + } + if (res.isNotEmpty) { + final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + int counter = 0; + for (Campaign c in res) { + if (kDebugMode) { + print( + '\x1B[31m [CLOSED CAMPAIGN SERVICE]Execution of _process for the $counter time.\x1B[0m'); + } + + SharedPreferences shared = await SharedPreferences.getInstance(); + String? accountAddress = shared.getString('address'); + if (accountAddress == null) { + throw NullThrownError(); + } + String address = c.address; + String title = c.title; + + smartContract = SmartContractModelBs( + contractAddress: address, + abiName: 'Campaign', + abiFileRoot: 'assets/abi_campaign.json', + accountAddress: accountAddress); + + List? isClosedRaw = + await smartContract.queryCall('isClosed', []); + if (isClosedRaw != null) { + String answer = isClosedRaw[0].toString(); + + if (answer == "true") { + // the campaign result closed + if (kDebugMode) { + print('\x1B[31mThe campaign was closed\x1B[0m'); + } + if (service is AndroidServiceInstance) { + if (await service.isForegroundService()) { + flutterLocalNotificationsPlugin.show( + 888, + 'Campaign Closed', + 'The campaign [$title] \nat address $address \n was closed by crowdsourcer', + const NotificationDetails( + android: AndroidNotificationDetails( + 'important_channel', + 'MY FOREGROUND SERVICE', + icon: 'ic_bg_service_small', + ongoing: true, + ), ), - ), - ); + ); + } } + await db.deleteCampaign(address); + } else { + print( + '\x1B[31mThe campaign still open: nothing to notify\x1B[0m'); } - await db.deleteCampaign(address); - } else if (answer == "false") { - print('\x1B[31mThe campaign still open: nothing to notify\x1B[0m'); + } else { + return Future.error(StackTrace); } - } else { - return Future.error(StackTrace); + + counter++; } - }); - counter++; - } - if (kDebugMode) { - print("\nsono stati registrati : $counter Tasks periodici\n"); - } - } else { - if (kDebugMode) { - print('\x1B[31mNessuna camapagna da seguire\x1B[0m'); - } - service.invoke("stopService"); + if (kDebugMode) { + print( + "\n [CLOSED CAMPAIGN SERVICE]registered : $counter periodic Tasks\n"); + } + } else { + if (kDebugMode) { + print( + '\x1B[31m [CLOSED CAMPAIGN SERVICE] No campaigns to follow. stop the service.\x1B[0m'); + } + ClosedCampaignService().setIsInizialized(false); + print('\x1B[31m[DEBUG CANCELLAZIONE SERVIZIO]${ ClosedCampaignService().checkIfInitialized() }\x1B[0m'); + timer.cancel(); + service.stopSelf(); + } + }); } -} -Future initializeClosedCampaignService() async { - DbCampaignModel db = DbCampaignModel(); - List res = await db.campaigns(); - if (res.isNotEmpty) { - print( - '\x1B[31mInizializzazione del servizio [CLOSED CAMPAIGN]\x1B[0m'); - - final service = FlutterBackgroundService(); - - final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = - FlutterLocalNotificationsPlugin(); - - await flutterLocalNotificationsPlugin - .resolvePlatformSpecificImplementation< - AndroidFlutterLocalNotificationsPlugin>() - ?.createNotificationChannel(NotificationChannel.importantChannel); - - await service.configure( - androidConfiguration: AndroidConfiguration( - // this will be executed when app is in foreground or background in separated isolate - onStart: onStart, - - // auto start service - autoStart: true, - isForegroundMode: true, - - notificationChannelId: 'important_channel', - initialNotificationTitle: 'closing campaign service', - initialNotificationContent: - 'this service notify eventually submitted campaign closed', - foregroundServiceNotificationId: 888, - ), - iosConfiguration: IosConfiguration(), - ); - - service.startService(); - } else { - print('\x1B[31mThe database is empty. no services to initialize\x1B[0m'); + Future initializeClosedCampaignService() async { + ClosedCampaignService().setIsInizialized(true); + DbCampaignModel db = DbCampaignModel(); + List res = await db.campaigns(); + if (res.isNotEmpty) { + print( + '\x1B[31m [CLOSED CAMPAIGN SERVICE]Initialize service [CLOSED CAMPAIGN]\x1B[0m'); + + final service = FlutterBackgroundService(); + + final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + + await flutterLocalNotificationsPlugin + .resolvePlatformSpecificImplementation< + AndroidFlutterLocalNotificationsPlugin>() + ?.createNotificationChannel(NotificationChannel.importantChannel); + + await service.configure( + androidConfiguration: AndroidConfiguration( +// this will be executed when app is in foreground or background in separated isolate + onStart: onStart, + +// auto start service + autoStart: true, + isForegroundMode: true, + + notificationChannelId: 'important_channel', + initialNotificationTitle: 'closing campaign service', + initialNotificationContent: + 'this service notify eventually submitted campaign closed', + foregroundServiceNotificationId: 888, + ), + iosConfiguration: IosConfiguration(), + ); + + service.startService(); + } else { + if (kDebugMode) { + print( + '\x1B[31m [CLOSED CAMPAIGN SERVICE]The database is empty. no services to initialize\x1B[0m'); + } + } } } -class SmartContractModel_Bs { - SmartContractModel_Bs( + +class SmartContractModelBs { + SmartContractModelBs( {required this.accountAddress, required this.contractAddress, required this.abiName, diff --git a/lib/utils/geofence_status.dart b/lib/services/geofence_status.dart similarity index 100% rename from lib/utils/geofence_status.dart rename to lib/services/geofence_status.dart diff --git a/lib/services/geofencing_service.dart b/lib/services/geofencing_service.dart index c239ca0..cc41deb 100644 --- a/lib/services/geofencing_service.dart +++ b/lib/services/geofencing_service.dart @@ -7,9 +7,8 @@ import '../models/db_capaign_model.dart'; import 'dart:async'; import 'dart:ui'; import 'package:flutter_background_service/flutter_background_service.dart'; -import 'package:flutter_background_service_android/flutter_background_service_android.dart'; import '../models/geofence_model.dart'; -import '../utils/geofence_status.dart'; +import 'geofence_status.dart'; //@pragma('vm:entry-point') void onStart(ServiceInstance service) async { @@ -19,27 +18,12 @@ void onStart(ServiceInstance service) async { // Only available for flutter 3.0.0 and later DartPluginRegistrant.ensureInitialized(); - if (service is AndroidServiceInstance) { - service.on('setAsForeground').listen((event) { - print('\x1B[31m [GEOFENCE SERVICE]Set in foreground\x1B[0m'); - service.setAsForegroundService(); - }); - - service.on('setAsBackground').listen((event) { - print('\x1B[31m [GEOFENCE SERVICE]Set in background\x1B[0m'); - service.setAsBackgroundService(); - }); - } - - service.on('stopService').listen((event) { - print('\x1B[31m [GEOFENCE SERVICE]stop service\x1B[0m'); - service.stopSelf(); - }); - final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); - + int i =0; for (GeofenceModel g in GeofenceController.geofenceList) { + i++; + print('\x1B[31m [GEOFENCE SERVICE] Read the stream for the : $i time\x1B[0m'); g.getGeofenceStream()!.listen((event) { switch(event) { case GeofenceStatus.enter: @@ -98,7 +82,31 @@ Future initializeGeofencingService() async { DbCampaignModel db = DbCampaignModel(); List res = await db.campaigns(); if (res.isNotEmpty) { - await Geolocator.requestPermission(); + + // check the permission for geolocation + + bool serviceEnabled; + LocationPermission permission; + + serviceEnabled = await Geolocator.isLocationServiceEnabled(); + if (!serviceEnabled) { + await Geolocator.openLocationSettings(); + return Future.error('Location services are disabled.'); + } + + permission = await Geolocator.checkPermission(); + if (permission == LocationPermission.denied) { + permission = await Geolocator.requestPermission(); + if (permission == LocationPermission.denied) { + return Future.error('Location permissions are denied'); + } + } + + if (permission == LocationPermission.deniedForever) { + return Future.error( + 'Location permissions are permanently denied, we cannot request permissions.'); + } + print('\x1B[31m [GEOFENCE SERVICE]Inizializzazione del servizio: [GEOFENCE]\x1B[0m'); GeofenceController.geofenceInitByDb(); diff --git a/pubspec.lock b/pubspec.lock index f7dc97a..a29b541 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -562,6 +562,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.10" + infinite_listview: + dependency: transitive + description: + name: infinite_listview + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" intl: dependency: "direct main" description: @@ -667,6 +674,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.4" + numberpicker: + dependency: "direct main" + description: + name: numberpicker + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" octo_image: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 6c1efe0..02c95ce 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -65,6 +65,7 @@ dependencies: shared_preferences: ^2.0.16 workmanager: ^0.5.1 flutter_foreground_task: ^3.10.0 + numberpicker: ^2.1.1 dev_dependencies: flutter_test: From 9775542fa0954f0b4f55ef7be3a84b33d915ea88 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Tue, 24 Jan 2023 17:36:05 +0100 Subject: [PATCH 06/34] filtro sulla posizione + coin flip animazione --- assets/images/coin.png | Bin 35929 -> 45901 bytes assets/images/coin_back.png | Bin 0 -> 32027 bytes lib/controllers/distance_controller.dart | 2 +- .../sourcer_campaign_controller.dart | 24 +- .../verifier_campaign_controller.dart | 431 +++++++++--------- lib/controllers/wallet_controller.dart | 40 +- pubspec.lock | 9 +- pubspec.yaml | 1 + 8 files changed, 272 insertions(+), 235 deletions(-) create mode 100644 assets/images/coin_back.png diff --git a/assets/images/coin.png b/assets/images/coin.png index 43694c27665d20e746ba8def9248974b58a3c25a..cd3dfc27e43f84c1e5328e3aa019c3379b1f77ab 100644 GIT binary patch literal 45901 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 diff --git a/assets/images/coin_back.png b/assets/images/coin_back.png new file mode 100644 index 0000000000000000000000000000000000000000..9fe53a78e8abcbe3235b5d948193ca0fc4c06277 GIT binary patch literal 32027 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 literal 0 HcmV?d00001 diff --git a/lib/controllers/distance_controller.dart b/lib/controllers/distance_controller.dart index 82c6c17..6eb7a88 100644 --- a/lib/controllers/distance_controller.dart +++ b/lib/controllers/distance_controller.dart @@ -4,7 +4,7 @@ class DistanceController { static distanceBetween(lat1, lon1, lat2, lon2) { var p = 0.017453292519943295; - var c = cos as double Function(num?); + var c = cos; var a = 0.5 - c((lat2 - lat1) * p) / 2 + c(lat1 * p) * c(lat2 * p) * (1 - c((lon2 - lon1) * p)) / 2; diff --git a/lib/controllers/sourcer_campaign_controller.dart b/lib/controllers/sourcer_campaign_controller.dart index 8204749..943e9f1 100644 --- a/lib/controllers/sourcer_campaign_controller.dart +++ b/lib/controllers/sourcer_campaign_controller.dart @@ -29,14 +29,19 @@ class _SourcerCampaignControllerState extends State { readebleLocation =''; _formatData(String contractAddress) async { - if(mounted){ - String counters = await SourcerCampaignModel.getCountersData(contractAddress); - jsonCounters = jsonDecode(counters); - fileCount = jsonCounters['fileCount'].toString(); - fileChecked = jsonCounters['fileChecked'].toString(); - workersCount = jsonCounters['workersCount'].toString(); - setState((){}); - } + await SourcerCampaignModel.getCountersData(contractAddress).then((val) { + if (!mounted) { + return; + } else { + setState(() { + jsonCounters = jsonDecode(val); + fileCount = jsonCounters['fileCount'].toString(); + fileChecked = jsonCounters['fileChecked'].toString(); + workersCount = jsonCounters['workersCount'].toString(); + }); + } + }); + } @override @@ -55,7 +60,8 @@ class _SourcerCampaignControllerState extends State { contractAddress = jsonParameters["contractAddress"]; readebleLocation = jsonParameters["redebleLocation"]; _formatData(contractAddress); - return _buildPage(context); + return _buildPage(context); + } diff --git a/lib/controllers/verifier_campaign_controller.dart b/lib/controllers/verifier_campaign_controller.dart index bf0f618..9988c1e 100644 --- a/lib/controllers/verifier_campaign_controller.dart +++ b/lib/controllers/verifier_campaign_controller.dart @@ -1,30 +1,38 @@ import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; import 'package:mobile_crowd_sensing/models/verifier_campaign_model.dart'; import 'package:numberpicker/numberpicker.dart'; import '../models/db_capaign_model.dart'; import '../utils/styles.dart'; import '../models/search_places_model.dart'; -import '../models/session_model.dart'; +import 'distance_controller.dart'; +// ignore: must_be_immutable class VerifierCampaignController extends StatefulWidget { List? contractsAddresses; VerifierCampaignController(this.contractsAddresses, {super.key}); - SessionModel sessionData = SessionModel(); - SearchPlacesModel searchPlacesViewModel = SearchPlacesModel(); + SearchPlacesModel places = SearchPlacesModel(); @override + // ignore: library_private_types_in_public_api _VerifierCampaignControllerState createState() => _VerifierCampaignControllerState(); } class _VerifierCampaignControllerState extends State { + Future futureGetData() { + return VerifierCampaignModel.getData(widget.contractsAddresses)!; + } + + Future futureGetPosition() async { + await widget.places.updateLocalPosition(); + } + @override Widget build(BuildContext context) { return FutureBuilder( - future: VerifierCampaignModel.getData(widget.contractsAddresses), - builder: (BuildContext context, AsyncSnapshot snapshot) { + future: Future.wait([futureGetData(), futureGetPosition()]), + builder: (BuildContext context, AsyncSnapshot> snapshot) { switch (snapshot.connectionState) { case ConnectionState.none: return const Center(child: Text('Sorry something goes wrong...')); @@ -33,48 +41,7 @@ class _VerifierCampaignControllerState padding: const EdgeInsets.fromLTRB(10, 30, 10, 10), width: double.maxFinite, child: Column(children: [ - Row(children: [ - Text( - "filters: ", - style: CustomTextStyle.spaceMono(context), - ), - DropdownButton( - value: selectedValue, - items: const [ - DropdownMenuItem( - value: 'All Campaigns', - child: Text("All Campaigns"), - ), - DropdownMenuItem( - value: 'Near Me', - child: Text("Near Me"), - ), - DropdownMenuItem( - value: 'Subscribed', - child: Text("Subscribed"), - ), - ], - onChanged: (value) { - (context as Element).markNeedsBuild(); - setState(() { - selectedValue = value as String; - }); - }), - (selectedValue == "Near Me")? - Column(children: [ - NumberPicker( - itemHeight: 18, - value: _currentIntValue, - minValue: 0, - maxValue: 100, - step: 10, - haptics: true, - onChanged: (value) => setState(() => _currentIntValue = value), - ), - ]) - : - Container(), - ]), + _filtersWidget(), Expanded( child: Column( mainAxisSize: MainAxisSize.max, @@ -89,6 +56,7 @@ class _VerifierCampaignControllerState } }); } + int _currentIntValue = 10; String selectedValue = 'All Campaigns'; DbCampaignModel db = DbCampaignModel(); @@ -99,53 +67,12 @@ class _VerifierCampaignControllerState padding: const EdgeInsets.fromLTRB(10, 30, 10, 10), width: double.maxFinite, child: Column(children: [ - Row(children: [ - Text( - "filters: ", - style: CustomTextStyle.spaceMono(context), - ), - DropdownButton( - value: selectedValue, - items: const [ - DropdownMenuItem( - value: 'All Campaigns', - child: Text("All Campaigns"), - ), - DropdownMenuItem( - value: 'Near Me', - child: Text("Near Me"), - ), - DropdownMenuItem( - value: 'Subscribed', - child: Text("Subscribed"), - ), - ], - onChanged: (value) { - (context as Element).markNeedsBuild(); - setState(() { - selectedValue = value as String; - }); - }), - (selectedValue == "Near Me")? - Column(children: [ - NumberPicker( - itemHeight: 18, - value: _currentIntValue, - minValue: 0, - maxValue: 100, - step: 10, - haptics: true, - onChanged: (value) => setState(() => _currentIntValue = value), - ), - ]) - : - Container(), - ]), + _filtersWidget(), Expanded( child: ListView.builder( - itemCount: snapshot.data.length, + itemCount: snapshot.data[0].length, itemBuilder: (context, index) { - List? current = snapshot.data[index]; + List? current = snapshot.data[0][index]; String? name, lat, lng, @@ -184,130 +111,17 @@ class _VerifierCampaignControllerState 'lng': lng, }); }, - child: Card( - shadowColor: Colors.blue[600], - color: Colors.white54, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20.0), - ), - child: Padding( - padding: const EdgeInsets.all(20), - child: Stack( - children: [ - Align( - alignment: Alignment.topRight, - child: ElevatedButton( - style: ButtonStyle( - backgroundColor: - (isSubscribed == 'true') - ? MaterialStateProperty.all( - CustomColors.red600( - context)) - : MaterialStateProperty.all( - CustomColors.green600( - context))), - child: (isSubscribed == 'true') - ? const Text('unsubscribe') - : const Text('subscribe'), - onPressed: () async { - if (isSubscribed == 'true') { - await db.deleteCampaign( - contractAddress!); - //await removeTask(contractAddress); - } else { - await db.insertCampaign(Campaign( - title: name!, - lat: lat!, - lng: lng!, - radius: range!, - address: contractAddress!)); - //await addPeriodicTask(name!,contractAddress); - } - setState(() {}); - }, - )), - Align( - alignment: Alignment.topLeft, - child: Column(children: [ - Row(children: [ - Expanded( - child: Text( - "Name: $name", - style: CustomTextStyle.spaceMono( - context), - )), - ]), - Row(children: [ - Text( - "Latitude: $lat", - style: CustomTextStyle.spaceMono( - context), - ), - ]), - Row(children: [ - Text( - "Longitude: $lng", - style: CustomTextStyle.spaceMono( - context), - ), - ]), - Column(children: [ - Text("Location: $readebleLocation", - style: CustomTextStyle.spaceMono( - context)) - ]), - Row(children: [ - Text( - "Range: $range", - style: GoogleFonts.spaceMono( - textStyle: const TextStyle( - color: Colors.black87, - letterSpacing: .5), - fontWeight: FontWeight.normal, - fontSize: 16), - ), - ]), - Row(children: [ - Text( - "Type: $type", - style: CustomTextStyle.spaceMono( - context), - ), - ]), - Padding( - padding: const EdgeInsets.all(10), - child: Column( - children: [ - Text( - "crowdsourcer:", - style: - CustomTextStyle.spaceMono( - context), - ), - FittedBox( - fit: BoxFit.fitWidth, - child: Text( - (crowdsourcer != null) - ? crowdsourcer - : "null", - style: CustomTextStyle - .spaceMono(context), - )), - ], - ), - ), - Row(children: [ - Text( - "fileCount: $fileCount", - style: CustomTextStyle.spaceMono( - context), - ), - ]) - ])), - ], - ), - ), - ), + child: _cardWidget( + isSubscribed!, + contractAddress, + name!, + lat, + lng, + range, + type!, + fileCount, + crowdsourcer, + readebleLocation!), ); } else { return Container(); @@ -322,12 +136,195 @@ class _VerifierCampaignControllerState )); } + Widget _cardWidget( + String isSubscribed, + String contractAddress, + String name, + String lat, + String lng, + String range, + String type, + String fileCount, + String crowdsourcer, + String readebleLocation) { + return Card( + shadowColor: Colors.blue[600], + color: Colors.white54, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20.0), + ), + child: Padding( + padding: const EdgeInsets.all(20), + child: Stack( + children: [ + // Align( + // alignment: Alignment.topRight, + // child: ), + Align( + alignment: Alignment.topLeft, + child: Column(children: [ + Row(children: [ + Flexible( + flex: 0, + child:Text("Name: ", + style: CustomTextStyle.spaceMonoBold(context))), + Flexible( + flex: 5, + child: Text(name, + style: CustomTextStyle.spaceMono(context))), + Flexible(flex: 1, child:Container()), + Flexible( + flex: 0, + child: ElevatedButton( + style: ButtonStyle( + backgroundColor: (isSubscribed == 'true') + ? MaterialStateProperty.all( + CustomColors.red600(context)) + : MaterialStateProperty.all( + CustomColors.green600(context))), + child: (isSubscribed == 'true') + ? const Text('unsubscribe') + : const Text('subscribe'), + onPressed: () async { + if (isSubscribed == 'true') { + await db.deleteCampaign(contractAddress); + //await removeTask(contractAddress); + } else { + await db.insertCampaign(Campaign( + title: name, + lat: lat, + lng: lng, + radius: range, + address: contractAddress)); + //await addPeriodicTask(name!,contractAddress); + } + setState(() {}); + }, + )), + ]), + Row(children: [ + Text( + "Latitude: $lat", + style: CustomTextStyle.spaceMono(context), + ), + ]), + Row(children: [ + Text( + "Longitude: $lng", + style: CustomTextStyle.spaceMono(context), + ), + ]), + Column(children: [ + Text("Location: $readebleLocation", + style: CustomTextStyle.spaceMono(context)) + ]), + Row(children: [ + Text( + "Range: $range", + style: CustomTextStyle.spaceMono(context), + ), + ]), + Row(children: [ + Text( + "Type: $type", + style: CustomTextStyle.spaceMono(context), + ), + ]), + Padding( + padding: const EdgeInsets.all(10), + child: Column( + children: [ + Text( + "crowdsourcer:", + style: CustomTextStyle.spaceMono(context), + ), + FittedBox( + fit: BoxFit.fitWidth, + child: Text( + crowdsourcer, + style: CustomTextStyle.spaceMono(context), + )), + ], + ), + ), + Row(children: [ + Text( + "fileCount: $fileCount", + style: CustomTextStyle.spaceMono(context), + ), + ]) + ])), + ], + ), + ), + ); + } + + Widget _filtersWidget() { + return Row(children: [ + Text( + "filters: ", + style: CustomTextStyle.spaceMono(context), + ), + DropdownButton( + value: selectedValue, + items: const [ + DropdownMenuItem( + value: 'All Campaigns', + child: Text("All Campaigns"), + ), + DropdownMenuItem( + value: 'Near Me', + child: Text("Near Me"), + ), + DropdownMenuItem( + value: 'Subscribed', + child: Text("Subscribed"), + ), + ], + onChanged: (value) { + (context as Element).markNeedsBuild(); + setState(() { + selectedValue = value as String; + }); + }), + (selectedValue == "Near Me") ? _radiusPicker() : Container(), + ]); + } + + Widget _radiusPicker() { + return Row(children: [ + Text(" radius: ", style: CustomTextStyle.spaceMono(context)), + SizedBox( + width: 50, + child: NumberPicker( + selectedTextStyle: + TextStyle(fontSize: 18, color: CustomColors.blue900(context)), + textStyle: const TextStyle(fontSize: 13), + itemHeight: 18, + value: _currentIntValue, + minValue: 0, + maxValue: 50, + step: 2, + haptics: true, + onChanged: (value) => setState(() => _currentIntValue = value), + )), + Text("Km", style: CustomTextStyle.spaceMono(context)), + ]); + } + bool _isToShow(dynamic data) { switch (selectedValue) { case "Subscribed": return (data[9] == "true") ? true : false; case "Near Me": - return data[9]; + dynamic distance = DistanceController.distanceBetween( + (double.parse(data[1].toString()) / 10000000), + (double.parse(data[2].toString()) / 10000000), + widget.places.lat, + widget.places.lng); + print("BEBUG::::::::::::::::: $distance"); + return (distance <= (_currentIntValue)) ? true : false; default: return true; } diff --git a/lib/controllers/wallet_controller.dart b/lib/controllers/wallet_controller.dart index 6ae4069..3757207 100644 --- a/lib/controllers/wallet_controller.dart +++ b/lib/controllers/wallet_controller.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; import '../models/wallet_model.dart'; import '../utils/styles.dart'; +import 'package:flip_card/flip_card.dart'; class WalletController extends StatefulWidget { const WalletController({Key? key}) : super(key: key); @@ -18,6 +19,8 @@ class _WalletControllerState extends State { dynamic jsonInfo = {}; late Timer timer; String balance = "LOADING...", symbol = "LOADING..."; + late double _height; + late double _width; Future _getBalance() async { String data = await WalletModel.getData(); @@ -44,6 +47,7 @@ class _WalletControllerState extends State { @override Widget build(BuildContext context) { + return WillPopScope( child: Center( child: @@ -79,7 +83,6 @@ Widget _formatBalance(String balance) { if (double.tryParse(balance) != null && balance != "0") { print("DEBUG: $balance"); return Text( - '${balance.substring(0, 2)},${balance.substring(3)}', style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ); @@ -92,6 +95,7 @@ Widget _formatBalance(String balance) { } Widget buildCoinWidget(String balance, String symbol) { + return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -100,12 +104,34 @@ Widget buildCoinWidget(String balance, String symbol) { symbol, style: const TextStyle(fontSize: 25), ), - const SizedBox( - height: 20, - ), - Image.asset('assets/images/coin.png', width: 150, height: 150), - const SizedBox( - height: 20, + SizedBox( + width: 300, + height: 300, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Column( + children: [ + FlipCard( + direction: FlipDirection.VERTICAL, // default + front: Stack( + alignment: Alignment.center, + children: [ + Image.asset('assets/images/coin_back.png', width: 150, height: 150), + ], + ), + back: Stack( + alignment: Alignment.center, + children: [ + Image.asset('assets/images/coin.png', width: 150, height: 150), + ], + ), + ), + ], + ), + ], + ), ), _formatBalance(balance) ], diff --git a/pubspec.lock b/pubspec.lock index a29b541..81bb087 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -309,6 +309,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.1" + flip_card: + dependency: "direct main" + description: + name: flip_card + url: "https://pub.dartlang.org" + source: hosted + version: "0.7.0" flutter: dependency: "direct main" description: flutter @@ -561,7 +568,7 @@ packages: name: image url: "https://pub.dartlang.org" source: hosted - version: "4.0.10" + version: "4.0.12" infinite_listview: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 02c95ce..47acf7a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -66,6 +66,7 @@ dependencies: workmanager: ^0.5.1 flutter_foreground_task: ^3.10.0 numberpicker: ^2.1.1 + flip_card: ^0.7.0 dev_dependencies: flutter_test: From 02582e7bf9032c09b477bc91b81d3fa8742fb83d Mon Sep 17 00:00:00 2001 From: Giacomo Date: Thu, 26 Jan 2023 20:23:44 +0100 Subject: [PATCH 07/34] big refactor + geofence --- android/app/src/main/AndroidManifest.xml | 21 +- .../res/drawable-hdpi/ic_bg_service_small.png | Bin 0 -> 3910 bytes .../res/drawable-mdpi/ic_bg_service_small.png | Bin 0 -> 2392 bytes .../drawable-xhdpi/ic_bg_service_small.png | Bin 0 -> 3591 bytes .../res/mipmap-xxhdpi/ic_bg_service_small.png | Bin 0 -> 6875 bytes .../mipmap-xxxhdpi/ic_bg_service_small.png | Bin 0 -> 9652 bytes contracts/Campaign.sol | 26 +- ...ler.dart => campaign_list_controller.dart} | 22 +- lib/controllers/geofence_controller.dart | 53 ---- lib/controllers/login_controller.dart | 9 +- .../verifier_campaign_data_controller.dart | 268 +++++++++++++++++ ...rifier_campaign_data_light_controller.dart | 265 ----------------- ...rifier_campaign_data_photo_controller.dart | 274 ------------------ .../worker_campaign_controller.dart | 157 ---------- lib/main.dart | 111 ++++++- lib/models/db_capaign_model.dart | 20 +- lib/models/geofence_model.dart | 95 ------ lib/models/login_metamask_model.dart | 30 +- lib/models/search_places_model.dart | 1 + lib/services/closed_campaign_service.dart | 83 +++++- lib/services/geofence_status.dart | 7 - lib/services/geofencing.dart | 105 +++++++ lib/services/geofencing_controller.dart | 65 +++++ lib/services/geofencing_service.dart | 146 ---------- lib/services/notification_channels.dart | 9 + lib/services/services.dart | 203 +++++++++++++ lib/services/services_controller.dart | 23 ++ lib/utils/internet_connection.dart | 19 ++ .../verifier_campaign_data_light_view.dart | 4 +- .../verifier_campaign_data_photo_view.dart | 4 +- lib/views/verifier_campaign_view.dart | 4 +- lib/views/worker_campaign_view.dart | 5 +- pubspec.lock | 59 +++- pubspec.yaml | 3 + 34 files changed, 1000 insertions(+), 1091 deletions(-) create mode 100644 android/app/src/main/res/drawable-hdpi/ic_bg_service_small.png create mode 100644 android/app/src/main/res/drawable-mdpi/ic_bg_service_small.png create mode 100644 android/app/src/main/res/drawable-xhdpi/ic_bg_service_small.png create mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_bg_service_small.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_bg_service_small.png rename lib/controllers/{verifier_campaign_controller.dart => campaign_list_controller.dart} (95%) delete mode 100644 lib/controllers/geofence_controller.dart create mode 100644 lib/controllers/verifier_campaign_data_controller.dart delete mode 100644 lib/controllers/verifier_campaign_data_light_controller.dart delete mode 100644 lib/controllers/verifier_campaign_data_photo_controller.dart delete mode 100644 lib/controllers/worker_campaign_controller.dart delete mode 100644 lib/models/geofence_model.dart delete mode 100644 lib/services/geofence_status.dart create mode 100644 lib/services/geofencing.dart create mode 100644 lib/services/geofencing_controller.dart delete mode 100644 lib/services/geofencing_service.dart create mode 100644 lib/services/services.dart create mode 100644 lib/services/services_controller.dart create mode 100644 lib/utils/internet_connection.dart diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 98272c8..705c593 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -25,12 +25,18 @@ - - - + + + + + + + + + @@ -40,4 +46,7 @@ + + + diff --git a/android/app/src/main/res/drawable-hdpi/ic_bg_service_small.png b/android/app/src/main/res/drawable-hdpi/ic_bg_service_small.png new file mode 100644 index 0000000000000000000000000000000000000000..3001b3e5aad2225082785f16865d696646fa3d6b GIT binary patch literal 3910 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-mdpi/ic_bg_service_small.png b/android/app/src/main/res/drawable-mdpi/ic_bg_service_small.png new file mode 100644 index 0000000000000000000000000000000000000000..208265422bf53e4d76ffdda5358de629658753d3 GIT binary patch literal 2392 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 KQY^n~9`rwajgSuj literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_bg_service_small.png b/android/app/src/main/res/mipmap-xxhdpi/ic_bg_service_small.png new file mode 100644 index 0000000000000000000000000000000000000000..b840e097581d5726efdbc37d051b792ef79de63a GIT binary patch literal 6875 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 vNJ9^qb+hR7>-~K&sU+d= calculateDistance(latFile,lonFile)) { - return true; - } - return false; - } } diff --git a/lib/controllers/verifier_campaign_controller.dart b/lib/controllers/campaign_list_controller.dart similarity index 95% rename from lib/controllers/verifier_campaign_controller.dart rename to lib/controllers/campaign_list_controller.dart index 9988c1e..867f135 100644 --- a/lib/controllers/verifier_campaign_controller.dart +++ b/lib/controllers/campaign_list_controller.dart @@ -1,3 +1,4 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:mobile_crowd_sensing/models/verifier_campaign_model.dart'; import 'package:numberpicker/numberpicker.dart'; @@ -7,19 +8,20 @@ import '../models/search_places_model.dart'; import 'distance_controller.dart'; // ignore: must_be_immutable -class VerifierCampaignController extends StatefulWidget { - List? contractsAddresses; - VerifierCampaignController(this.contractsAddresses, {super.key}); +class CampaignListController extends StatefulWidget { + final List contractsAddresses; + final String goTo; + CampaignListController({super.key,required this.contractsAddresses, required this.goTo}); SearchPlacesModel places = SearchPlacesModel(); @override // ignore: library_private_types_in_public_api - _VerifierCampaignControllerState createState() => - _VerifierCampaignControllerState(); + _CampaignListControllerState createState() => + _CampaignListControllerState(); } -class _VerifierCampaignControllerState - extends State { +class _CampaignListControllerState + extends State { Future futureGetData() { return VerifierCampaignModel.getData(widget.contractsAddresses)!; } @@ -99,7 +101,7 @@ class _VerifierCampaignControllerState return GestureDetector( onTap: () { Navigator.pushNamed( - context, '/verifier_campaign_data', + context, widget.goTo, arguments: { 'contractAddress': contractAddress, 'name': name, @@ -323,7 +325,9 @@ class _VerifierCampaignControllerState (double.parse(data[2].toString()) / 10000000), widget.places.lat, widget.places.lng); - print("BEBUG::::::::::::::::: $distance"); + if (kDebugMode) { + print("BEBUG::::::::::::::::: $distance"); + } return (distance <= (_currentIntValue)) ? true : false; default: return true; diff --git a/lib/controllers/geofence_controller.dart b/lib/controllers/geofence_controller.dart deleted file mode 100644 index 486aef8..0000000 --- a/lib/controllers/geofence_controller.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'dart:async'; -import 'package:flutter/foundation.dart'; -import 'package:mobile_crowd_sensing/models/geofence_model.dart'; -import '../models/db_capaign_model.dart'; -import '../services/geofence_status.dart'; - -class GeofenceController { - - static List geofenceList = []; - static final DbCampaignModel db = DbCampaignModel(); - static int geofenceActive = 0; - static final GeofenceController _instance = GeofenceController._internal(); - static List?> geofenceStatusStream = []; - - //This singleton class allows to store all - //GeofeceModel in order to manage them and - //streams the result and interact with campaignsDB - - factory GeofenceController() { - return _instance; - } - - GeofenceController._internal(); - - static geofenceInitByDb() async { - List campaigns = await db.campaigns(); - for(Campaign c in campaigns) { - - GeofenceModel g = GeofenceModel( - pointedLatitude: c.lat, - pointedLongitude: c.lng, - radiusMeter: c.radius, - ); - geofenceList.add(g); - g.startGeofenceService(); - geofenceActive++; - } - - if (kDebugMode) { - print("\n Active Geofences: $geofenceActive \n"); - } - } - - static geofenceUpdateByDb() async { - for(GeofenceModel g in geofenceList) { - g.stopGeofenceService(); - geofenceList.remove(g); - } - geofenceActive = 0; - geofenceInitByDb(); - } - -} \ No newline at end of file diff --git a/lib/controllers/login_controller.dart b/lib/controllers/login_controller.dart index 3b42d94..be426d3 100644 --- a/lib/controllers/login_controller.dart +++ b/lib/controllers/login_controller.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:slider_button/slider_button.dart'; +import '../utils/internet_connection.dart'; import 'login_metamask_controller.dart'; import '../utils/styles.dart'; import '../models/session_model.dart'; @@ -14,16 +15,18 @@ class LoginController extends StatefulWidget { class _LoginControllerState extends State { bool isRunning = false; - SessionModel sessionData = SessionModel(); + late SessionModel sessionData; + @override void initState() { - // TODO: implement initState + InternetConnection.checkInternetConnectivity(); super.initState(); - sessionData.checkConnection(); } @override Widget build(BuildContext context) { + sessionData = SessionModel(); + sessionData.checkConnection(); return SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/controllers/verifier_campaign_data_controller.dart b/lib/controllers/verifier_campaign_data_controller.dart new file mode 100644 index 0000000..76a0e8d --- /dev/null +++ b/lib/controllers/verifier_campaign_data_controller.dart @@ -0,0 +1,268 @@ +import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:mobile_crowd_sensing/utils/styles.dart'; +import '../models/verifier_campaign_data_model.dart'; + +class VerifierCampaignDataController extends StatefulWidget { + final String goTo; + const VerifierCampaignDataController({Key? key, required this.goTo}) : super(key: key); + + @override + State createState() => + _VerifierCampaignDataPhotoController(); +} + +class _VerifierCampaignDataPhotoController + extends State { + Object? parameters; + dynamic jsonParameters = {}; + dynamic jsonCounters = {}; + List? filesInfo; + + String fileCount = '0'; + String fileChecked = '0'; + String workersCount = '0'; + late String name, + lat, + lng, + range, + type, + crowdsourcer, + contractAddress, + readebleLocation; + + Future _formatData() async { + String counters = await _getContractData(); + filesInfo = await _getDataFile(); + jsonCounters = jsonDecode(counters); + fileCount = jsonCounters['fileCount'].toString(); + fileChecked = jsonCounters['fileChecked'].toString(); + workersCount = jsonCounters['workersCount'].toString(); + } + + Future _getContractData() { + return VerifierCampaignDataModel.getData(contractAddress); + } + + Future _getDataFile() { + return VerifierCampaignDataModel.getDataFileInfo(contractAddress); + } + + @override + Widget build(BuildContext context) { + parameters = ModalRoute.of(context)!.settings.arguments; + jsonParameters = jsonDecode(jsonEncode(parameters)); + contractAddress = jsonParameters["contractAddress"]; + name = jsonParameters['name']; + lat = jsonParameters['lat']; + lng = jsonParameters['lng']; + range = jsonParameters['range']; + type = jsonParameters['type']; + crowdsourcer = jsonParameters['crowdsourcer']; + readebleLocation = jsonParameters['readebleLocation']; + + return Container( + padding: const EdgeInsets.fromLTRB(10, 30, 10, 0), + width: double.maxFinite, + child: Column(children: [ + Column(children: [ + Text("contractAddress:", + style: CustomTextStyle.spaceMonoBold(context)), + FittedBox( + fit: BoxFit.fitWidth, + child: Text(contractAddress, + style: CustomTextStyle.spaceMono(context))), + ]), + Column(children: [ + Text("Crowdsourcer:", style: CustomTextStyle.spaceMonoBold(context)), + FittedBox( + fit: BoxFit.fitWidth, + child: Text(crowdsourcer, + style: CustomTextStyle.spaceMono(context))), + ]), + Column(children: [ + Text("Location:", style: CustomTextStyle.spaceMonoBold(context)), + Text(readebleLocation, style: CustomTextStyle.spaceMono(context)), + ]), + Row(children: [ + Text( + "Range: ", + style: CustomTextStyle.spaceMonoBold(context), + ), + Text( + range, + style: CustomTextStyle.spaceMono(context), + ), + Text( + "Type: ", + style: CustomTextStyle.spaceMonoBold(context), + ), + Text( + type, + style: CustomTextStyle.spaceMono(context), + ), + ]), + FutureBuilder( + future: _formatData(), + builder: (BuildContext context, AsyncSnapshot snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.none: + return const Expanded( + flex: 1, + child:Center( + child: Text('Sorry something goes wrong...'))); + case ConnectionState.waiting: + return const Expanded( + flex: 1, + child: Center( + child: CircularProgressIndicator()), + ); + default: + return _bottomWidget(); + } + }), + ]), + ); + } + + Widget _bottomWidget() { + return Expanded( + flex: 1, + child: Column(children: [ + Text( + "uploaded $fileCount files\nchecked $fileChecked of $fileCount", + style: CustomTextStyle.spaceMonoBold(context), + ), + ListView.builder( + //scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: (filesInfo != null) ? filesInfo!.length : 0, + itemBuilder: (context, index) { + List current = filesInfo![index]; + + String status = current[0].toString(); + String validity = current[1].toString(); + String uploader = current[2].toString(); + String ipfsHash = current[4].toString(); + if (status == 'false') { + return GestureDetector( + onTap: () { + Navigator.pushNamed(context, widget.goTo, + arguments: { + "name": name, + "ipfsHash": ipfsHash, + "uploader": uploader, + "contractAddress": contractAddress + }); + }, + child: Card( + shadowColor: CustomColors.blue600(context), + color: CustomColors.customWhite(context), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20.0), + ), + child: Padding( + padding: const EdgeInsets.all(20), + child: Stack(children: [ + Align( + alignment: Alignment.topLeft, + child: Column( + children: [ + FittedBox( + fit: BoxFit.fitWidth, + child: Column(children: [ + Text( + "Uploader: ", + style: CustomTextStyle.spaceMonoBold( + context), + ), + Text( + uploader, + style: CustomTextStyle.spaceMono( + context), + ) + ])), + FittedBox( + fit: BoxFit.fitWidth, + child: Column(children: [ + Text( + "Ipfs hash: ", + style: CustomTextStyle.spaceMonoBold( + context), + ), + Text( + ipfsHash, + style: CustomTextStyle.spaceMono( + context), + ) + ])), + ], + ), + ), + ])), + ), + ); + } else { + return Card( + shadowColor: (validity == 'true') + ? CustomColors.green600(context) + : CustomColors.red600(context), + color: CustomColors.customWhite(context), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20.0), + ), + child: Padding( + padding: const EdgeInsets.all(20), + child: Align( + alignment: Alignment.topLeft, + child: Column( + children: [ + FittedBox( + fit: BoxFit.fitWidth, + child: Column(children: [ + Text( + "Uploader: ", + style: + CustomTextStyle.spaceMonoBold(context), + ), + Text( + uploader, + style: CustomTextStyle.spaceMono(context), + ) + ])), + FittedBox( + fit: BoxFit.fitWidth, + child: Column(children: [ + Text( + "Ipfs hash: ", + style: + CustomTextStyle.spaceMonoBold(context), + ), + Text( + ipfsHash, + style: CustomTextStyle.spaceMono(context), + ) + ])), + FittedBox( + fit: BoxFit.fitWidth, + child: Row(children: [ + Text( + "validity: ", + style: + CustomTextStyle.spaceMonoBold(context), + ), + Text( + validity, + style: CustomTextStyle.spaceMono(context), + ) + ])), + ], + ), + ), + ), + ); + } + }) + ])); + } +} diff --git a/lib/controllers/verifier_campaign_data_light_controller.dart b/lib/controllers/verifier_campaign_data_light_controller.dart deleted file mode 100644 index b079c91..0000000 --- a/lib/controllers/verifier_campaign_data_light_controller.dart +++ /dev/null @@ -1,265 +0,0 @@ -import 'dart:convert'; -import 'package:flutter/material.dart'; -import 'package:mobile_crowd_sensing/utils/styles.dart'; -import '../models/verifier_campaign_data_model.dart'; - -class VerifierCampaignDataLightController extends StatefulWidget { - const VerifierCampaignDataLightController({Key? key}) : super(key: key); - - @override - State createState() => - _VerifierCampaignDataLightControllerState(); -} - -class _VerifierCampaignDataLightControllerState - extends State { - Object? parameters; - dynamic jsonParameters = {}; - dynamic jsonCounters = {}; - List? filesInfo; - - String fileCount = '0'; - String fileChecked = '0'; - String workersCount = '0'; - late String name, - lat, - lng, - range, - type, - crowdsourcer, - contractAddress, - readebleLocation; - - _formatData(String counters, List? info) { - jsonCounters = jsonDecode(counters); - fileCount = jsonCounters['fileCount'].toString(); - fileChecked = jsonCounters['fileChecked'].toString(); - workersCount = jsonCounters['workersCount'].toString(); - filesInfo = info; - } - - @override - Widget build(BuildContext context) { - parameters = ModalRoute.of(context)!.settings.arguments; - jsonParameters = jsonDecode(jsonEncode(parameters)); - contractAddress = jsonParameters["contractAddress"]; - name = jsonParameters['name']; - lat = jsonParameters['lat']; - lng = jsonParameters['lng']; - range = jsonParameters['range']; - type = jsonParameters['type']; - crowdsourcer = jsonParameters['crowdsourcer']; - readebleLocation = jsonParameters['readebleLocation']; - - VerifierCampaignDataModel.getData(contractAddress).then((counters) => { - VerifierCampaignDataModel.getDataFileInfo(contractAddress) - .then((info) => { - if (mounted) { - setState(() { - _formatData(counters, info); - }) - } - }) - }); - - return (contractAddress != "0x0000000000000000000000000000000000000000") - ? Container( - padding: const EdgeInsets.fromLTRB(10, 30, 10, 0), - width: double.maxFinite, - child: Column(children: [ - Column(children: [ - Column(children: [ - Text("contractAddress:", - style: CustomTextStyle.spaceMonoBold(context)), - FittedBox( - fit: BoxFit.fitWidth, - child: Text(contractAddress, - style: CustomTextStyle.spaceMono(context))), - ]), - Column(children: [ - Text("Crowdsourcer:", - style: CustomTextStyle.spaceMonoBold(context)), - FittedBox( - fit: BoxFit.fitWidth, - child: Text(crowdsourcer, - style: CustomTextStyle.spaceMono(context))), - ]), - Column(children: [ - Text("Location:", - style: CustomTextStyle.spaceMonoBold(context)), - Text(readebleLocation, - style: CustomTextStyle.spaceMono(context)), - ]), - Row(children: [ - Text( - "Range: ", - style: CustomTextStyle.spaceMonoBold(context), - ), - Text( - range, - style: CustomTextStyle.spaceMono(context), - ), - Text( - "Type: ", - style: CustomTextStyle.spaceMonoBold(context), - ), - Text(type, - style: CustomTextStyle.spaceMono(context), - ) - ]), - Padding( - padding: const EdgeInsets.all(40), - child:Text( - "uploaded $fileCount files\nchecked $fileChecked of $fileCount", - style: CustomTextStyle.spaceMonoBold(context), - )), - ]), - Expanded( - flex: 1, - child: ListView.builder( - //scrollDirection: Axis.vertical, - shrinkWrap: true, - itemCount: (filesInfo != null) ? filesInfo!.length : 0, - itemBuilder: (context, index) { - List current = filesInfo![index]; - - String status = current[0].toString(); - String validity = current[1].toString(); - String uploader = current[2].toString(); - String ipfsHash = current[4].toString(); - if (status == 'false') { - return GestureDetector( - onTap: () { - Navigator.pushNamed( - context, '/validate_light_view', - arguments: { - "name": name, - "ipfsHash": ipfsHash, - "uploader": uploader, - "contractAddress": contractAddress - }); - }, - child: Card( - shadowColor: CustomColors.blue600(context), - color: CustomColors.customWhite(context), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20.0), - ), - child: Padding( - padding: const EdgeInsets.all(20), - child: Stack(children: [ - Align( - alignment: Alignment.topLeft, - child: Column( - children: [ - FittedBox( - fit: BoxFit.fitWidth, - child: Column(children: [ - Text( - "Uploader: ", - style: CustomTextStyle - .spaceMonoBold(context), - ), - Text( - uploader, - style: - CustomTextStyle.spaceMono( - context), - ) - ])), - FittedBox( - fit: BoxFit.fitWidth, - child: Column(children: [ - Text( - "Ipfs hash: ", - style: CustomTextStyle - .spaceMonoBold(context), - ), - Text( - ipfsHash, - style: - CustomTextStyle.spaceMono( - context), - ) - ])), - ], - ), - ), - ])), - ), - ); - } else { - return Card( - shadowColor: (validity == 'true') - ? CustomColors.green600(context) - : CustomColors.red600(context), - color: CustomColors.customWhite(context), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20.0), - ), - child: Padding( - padding: const EdgeInsets.all(20), - child: Align( - alignment: Alignment.topLeft, - child: Column( - children: [ - FittedBox( - fit: BoxFit.fitWidth, - child: Column(children: [ - Text( - "Uploader: ", - style: - CustomTextStyle.spaceMonoBold( - context), - ), - Text( - uploader, - style: CustomTextStyle.spaceMono( - context), - ) - ])), - FittedBox( - fit: BoxFit.fitWidth, - child: Column(children: [ - Text( - "Ipfs hash: ", - style: - CustomTextStyle.spaceMonoBold( - context), - ), - Text( - ipfsHash, - style: CustomTextStyle.spaceMono( - context), - ) - ])), - FittedBox( - fit: BoxFit.fitWidth, - child: Row(children: [ - Text( - "validity: ", - style: - CustomTextStyle.spaceMonoBold( - context), - ), - Text( - validity, - style: CustomTextStyle.spaceMono( - context), - ) - ])), - ], - ), - ), - ), - ); - } - })) - ])) - : Center( - child: Text( - 'No active campaign at the moment...', - style: CustomTextStyle.spaceMono(context), - )); - } -} diff --git a/lib/controllers/verifier_campaign_data_photo_controller.dart b/lib/controllers/verifier_campaign_data_photo_controller.dart deleted file mode 100644 index 65f3894..0000000 --- a/lib/controllers/verifier_campaign_data_photo_controller.dart +++ /dev/null @@ -1,274 +0,0 @@ -import 'dart:convert'; -import 'package:flutter/material.dart'; -import 'package:mobile_crowd_sensing/utils/styles.dart'; -import '../models/file_manager_model.dart'; -import '../models/verifier_campaign_data_model.dart'; - -class VerifierCampaignDataPhotoController extends StatefulWidget { - const VerifierCampaignDataPhotoController({Key? key}) : super(key: key); - - @override - State createState() => - _VerifierCampaignDataPhotoControllerState(); -} - -class _VerifierCampaignDataPhotoControllerState - extends State { - Object? parameters; - dynamic jsonParameters = {}; - dynamic jsonCounters = {}; - List? filesInfo; - - String fileCount = '0'; - String fileChecked = '0'; - String workersCount = '0'; - late String name, - lat, - lng, - range, - type, - crowdsourcer, - contractAddress, - readebleLocation; - - @override - initState() { - super.initState(); - FileManagerModel.clearTemporaryDirectory(); - } - - _formatData(String counters, List? info) { - jsonCounters = jsonDecode(counters); - fileCount = jsonCounters['fileCount'].toString(); - fileChecked = jsonCounters['fileChecked'].toString(); - workersCount = jsonCounters['workersCount'].toString(); - filesInfo = info; - } - - @override - Widget build(BuildContext context) { - parameters = ModalRoute.of(context)!.settings.arguments; - jsonParameters = jsonDecode(jsonEncode(parameters)); - contractAddress = jsonParameters["contractAddress"]; - name = jsonParameters['name']; - lat = jsonParameters['lat']; - lng = jsonParameters['lng']; - range = jsonParameters['range']; - type = jsonParameters['type']; - crowdsourcer = jsonParameters['crowdsourcer']; - readebleLocation = jsonParameters['readebleLocation']; - - VerifierCampaignDataModel.getData(contractAddress).then((counters) => { - VerifierCampaignDataModel.getDataFileInfo(contractAddress) - .then((info) => { - if (mounted) - { - setState(() { - _formatData(counters, info); - }) - } - }) - }); - - return (contractAddress != "0x0000000000000000000000000000000000000000") - ? Container( - padding: const EdgeInsets.fromLTRB(10, 30, 10, 0), - width: double.maxFinite, - child: Column(children: [ - Column(children: [ - Column(children: [ - Text("contractAddress:", - style: CustomTextStyle.spaceMonoBold(context)), - FittedBox( - fit: BoxFit.fitWidth, - child: Text(contractAddress, - style: CustomTextStyle.spaceMono(context))), - ]), - Column(children: [ - Text("Crowdsourcer:", - style: CustomTextStyle.spaceMonoBold(context)), - FittedBox( - fit: BoxFit.fitWidth, - child: Text(crowdsourcer, - style: CustomTextStyle.spaceMono(context))), - ]), - Column(children: [ - Text("Location:", - style: CustomTextStyle.spaceMonoBold(context)), - Text(readebleLocation, - style: CustomTextStyle.spaceMono(context)), - ]), - - Row(children: [ - Text( - "Range: ", - style: CustomTextStyle.spaceMonoBold(context), - ), - Text( - range, - style: CustomTextStyle.spaceMono(context), - ), - Text( - "Type: ", - style: CustomTextStyle.spaceMonoBold(context), - ), - Text(type, - style: CustomTextStyle.spaceMono(context), - ) - ]), - Padding( - padding: const EdgeInsets.all(40), - child: Text( - "uploaded $fileCount files\nchecked $fileChecked of $fileCount", - style: CustomTextStyle.spaceMonoBold(context), - )), - ]), - Expanded( - flex: 1, - child: ListView.builder( - //scrollDirection: Axis.vertical, - shrinkWrap: true, - itemCount: (filesInfo != null) ? filesInfo!.length : 0, - itemBuilder: (context, index) { - List current = filesInfo![index]; - - String status = current[0].toString(); - String validity = current[1].toString(); - String uploader = current[2].toString(); - String ipfsHash = current[4].toString(); - if (status == 'false') { - return GestureDetector( - onTap: () { - Navigator.pushNamed( - context, '/validate_photo_view', - arguments: { - "name": name, - "ipfsHash": ipfsHash, - "uploader": uploader, - "contractAddress": contractAddress - }); - }, - child: Card( - shadowColor: CustomColors.blue600(context), - color: CustomColors.customWhite(context), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20.0), - ), - child: Padding( - padding: const EdgeInsets.all(20), - child: Stack(children: [ - Align( - alignment: Alignment.topLeft, - child: Column( - children: [ - FittedBox( - fit: BoxFit.fitWidth, - child: Column(children: [ - Text( - "Uploader: ", - style: CustomTextStyle - .spaceMonoBold(context), - ), - Text( - uploader, - style: - CustomTextStyle.spaceMono( - context), - ) - ])), - FittedBox( - fit: BoxFit.fitWidth, - child: Column(children: [ - Text( - "Ipfs hash: ", - style: CustomTextStyle - .spaceMonoBold(context), - ), - Text( - ipfsHash, - style: - CustomTextStyle.spaceMono( - context), - ) - ])), - ], - ), - ), - ])), - ), - ); - } else { - return Card( - shadowColor: (validity == 'true') - ? CustomColors.green600(context) - : CustomColors.red600(context), - color: CustomColors.customWhite(context), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20.0), - ), - child: Padding( - padding: const EdgeInsets.all(20), - child: Align( - alignment: Alignment.topLeft, - child: Column( - children: [ - FittedBox( - fit: BoxFit.fitWidth, - child: Column(children: [ - Text( - "Uploader: ", - style: - CustomTextStyle.spaceMonoBold( - context), - ), - Text( - uploader, - style: CustomTextStyle.spaceMono( - context), - ) - ])), - FittedBox( - fit: BoxFit.fitWidth, - child: Column(children: [ - Text( - "Ipfs hash: ", - style: - CustomTextStyle.spaceMonoBold( - context), - ), - Text( - ipfsHash, - style: CustomTextStyle.spaceMono( - context), - ) - ])), - FittedBox( - fit: BoxFit.fitWidth, - child: Row(children: [ - Text( - "validity: ", - style: - CustomTextStyle.spaceMonoBold( - context), - ), - Text( - validity, - style: CustomTextStyle.spaceMono( - context), - ) - ])), - ], - ), - ), - ), - ); - } - })) - ])) - : Center( - child: Text( - 'No active campaign at the moment...', - style: CustomTextStyle.spaceMono(context), - )); - } -} diff --git a/lib/controllers/worker_campaign_controller.dart b/lib/controllers/worker_campaign_controller.dart deleted file mode 100644 index b76fbb1..0000000 --- a/lib/controllers/worker_campaign_controller.dart +++ /dev/null @@ -1,157 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; -import '../models/worker_campaign_model.dart'; -import '../utils/styles.dart'; -import '../models/search_places_model.dart'; -import '../models/session_model.dart'; - - -class WorkerCampaignController extends StatelessWidget { - - List? contractsAddresses; - - WorkerCampaignController(this.contractsAddresses, {super.key}); - - SessionModel sessionData = SessionModel(); - SearchPlacesModel searchPlacesViewModel = SearchPlacesModel(); - - @override - Widget build(BuildContext context) { - return FutureBuilder( - future:WorkerCampaignModel.getData(contractsAddresses), - builder: (BuildContext context, AsyncSnapshot snapshot) { - switch (snapshot.connectionState) { - case ConnectionState.none: - return const Center( - child: Text('Sorry something goes wrong...') - ); - case ConnectionState.waiting: - return const Center(child: CircularProgressIndicator(),); - default: - return _buildPage(context, snapshot); - } - }); - } - - // sta qui - _buildPage(BuildContext context, AsyncSnapshot snapshot) { - return (snapshot.data.length>0)? - Container( - padding: const EdgeInsets.fromLTRB(10, 30, 10, 10), - width: double.maxFinite, - child: ListView.builder( - itemCount: snapshot.data.length, - itemBuilder: (context, index) { - List current = snapshot.data[index]; - - String name = current[0]; - String lat = (int.parse(current[1].toString())/10000000).round().toString(); - String lng = (int.parse(current[2].toString())/10000000).round().toString(); - String range = current[3].toString(); - String type = current[4]; - String crowdsourcer = current[5].toString(); - String fileCount = current[6].toString(); - String contractAddress = current[7].toString(); - String readebleLocation = current[8]; - return GestureDetector( - onTap: () { - Navigator.pushNamed(context, '/join_campaign', - arguments: { - 'name': name, - 'lat': lat, - 'lng': lng, - 'range': range, - 'type': type, - 'contractAddress': contractAddress, - }); - }, - child: Card( - shadowColor: Colors.blue[600], - color: Colors.white54, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20.0), - ), - child: Padding( - padding: const EdgeInsets.all(20), - child: Stack( - children: [ - Align( - alignment: Alignment.topLeft, - child: Column(children: [ - Row(children: [ - Expanded( - child: Text( - "Name: $name", - style: CustomTextStyle.spaceMono(context), - )), - ]), - Row(children: [ - Text( - "Latitude: $lat", - style: CustomTextStyle.spaceMono(context), - ), - ]), - Row(children: [ - Text( - "Longitude: $lng", - style: CustomTextStyle.spaceMono(context), - ), - ]), - Column(children: [ - Text( - "Location: $readebleLocation", - style: CustomTextStyle.spaceMono(context)) - ]), - Row(children: [ - Text( - "Range: $range", - style: GoogleFonts.spaceMono( - textStyle: const TextStyle( - color: Colors.black87, - letterSpacing: .5), - fontWeight: FontWeight.normal, - fontSize: 16), - ), - ]), - Row(children: [ - Text( - "Type: $type", - style: CustomTextStyle.spaceMono(context), - ), - ]), - Padding( - padding: const EdgeInsets.all(10), - child: Column( - children: [ - Text( - "crowdsourcer:", - style: CustomTextStyle.spaceMono(context), - ), - FittedBox( - fit: BoxFit.fitWidth, - child: Text( - crowdsourcer, - style: - CustomTextStyle.spaceMono(context), - )), - ], - ), - ), - Row(children: [ - Text( - "fileCount: $fileCount", - style: CustomTextStyle.spaceMono(context), - ), - ]) - ])), - ], - ), - ), - ), - ); - }), - ): Center(child:Text("No Campaign active at the moment.",style: CustomTextStyle.spaceMono(context),)); - } - - -} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 6e5f47c..479416f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,7 +1,11 @@ +import 'dart:io'; + +import 'package:flip_card/flip_card.dart'; import 'package:flutter/material.dart'; import 'package:flutter_config/flutter_config.dart'; -import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; +import 'package:mobile_crowd_sensing/utils/internet_connection.dart'; +import 'package:mobile_crowd_sensing/utils/styles.dart'; import 'package:mobile_crowd_sensing/utils/verifier_campaign_data_factory.dart'; import 'package:mobile_crowd_sensing/views/all_campaign_view.dart'; import 'package:mobile_crowd_sensing/views/close_campaign_view.dart'; @@ -20,19 +24,114 @@ import 'package:mobile_crowd_sensing/views/validate_light_view.dart'; import 'package:mobile_crowd_sensing/views/validate_photo_view.dart'; import 'package:mobile_crowd_sensing/views/wallet_view.dart'; import 'package:walletconnect_dart/walletconnect_dart.dart'; -import 'package:workmanager/workmanager.dart'; -import 'services/closed_campaign_service.dart'; +import 'dart:async'; +import 'package:connectivity/connectivity.dart'; Future main(List args) async { WidgetsFlutterBinding.ensureInitialized(); await FlutterConfig.loadEnvVariables(); - WalletConnectSession? s = await SessionModel().connector.sessionStorage?.getSession(); - runApp(const MyApp()); + ConnectivityResult initialStateInternet = await Connectivity().checkConnectivity(); + if (initialStateInternet == ConnectivityResult.none) { + runApp(const NoConnection()); + } else { + runApp(const MyApp()); + } + // WalletConnectSession? s = + // await SessionModel().connector.sessionStorage?.getSession(); } -class MyApp extends StatelessWidget { +class NoConnection extends StatelessWidget { + const NoConnection({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12.0)), + child: SizedBox( + height: 400.0, + width: 300.0, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(15.0), + child: Text( + "No internet Connection", + style: CustomTextStyle.spaceMonoBold(context) + )), + const Padding(padding: EdgeInsets.only(top: 50.0)), + + Column( + children: [ + FlipCard( + direction: FlipDirection.VERTICAL, // default + front: Stack( + alignment: Alignment.center, + children: [ + Image.asset('assets/images/coin_back.png', width: 150, height: 150), + ], + ), + back: Stack( + alignment: Alignment.center, + children: [ + Image.asset('assets/images/coin.png', width: 150, height: 150), + ], + ), + ), + ], + ), + + TextButton( + style: ButtonStyle(backgroundColor: MaterialStateProperty.all(CustomColors.blue900(context))), + onPressed: () { + exit(0); + }, + child: Text( + 'See you next time!', + style: CustomTextStyle.spaceMonoWhite(context) + )) + ], + ), + ), + ) + ); + } +} + + + +class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key); + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + var subscription; + + @override + dispose() { + super.dispose(); + subscription.cancel(); + } + + @override + void initState() { + super.initState(); + subscription = Connectivity() + .onConnectivityChanged + .listen((ConnectivityResult result) { + setState(() => { + InternetConnection.connectionStatus = result, + }); + InternetConnection.checkInternetConnectivity(); + }); + } + + @override Widget build(BuildContext context) { return MaterialApp( diff --git a/lib/models/db_capaign_model.dart b/lib/models/db_capaign_model.dart index 522d87f..70771a0 100644 --- a/lib/models/db_capaign_model.dart +++ b/lib/models/db_capaign_model.dart @@ -1,4 +1,6 @@ import 'dart:async'; +import 'package:mobile_crowd_sensing/services/geofencing_controller.dart'; +import 'package:mobile_crowd_sensing/services/services_controller.dart'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; @@ -44,12 +46,16 @@ class DbCampaignModel { conflictAlgorithm: ConflictAlgorithm.replace, ); - if(ClosedCampaignService().checkIfInitialized()) { - print('\x1B[31m[INITIALIZE AFTER INSERT IN DB]\x1B[0m'); - await ClosedCampaignService().initializeClosedCampaignService(); + GeofencingController.registerGeofencing(cmp.address, cmp.lat, cmp.lng, cmp.radius); + if(ServicesController.statusGeofencingService) { + print('\x1B[31m [GEOFENCING SERVICE] INITIALIZE AFTER INSERT IN DB\x1B[0m'); + ServicesController.initializeGeofencingService(); + } + if(ServicesController.statusCloseCampaignService) { + print('\x1B[31m [CLOSED CAMPAIGN SERVICE] INITIALIZE AFTER INSERT IN DB\x1B[0m'); + //await ClosedCampaignService().initializeClosedCampaignService(); + ServicesController.initializeCloseCampaignService(); } - print("DEBUG:::::: dentro al db ci sono: \n${(await campaigns()).length} campagne"); - } Future> campaigns() async { @@ -84,7 +90,9 @@ class DbCampaignModel { where: 'address = ?', whereArgs: [address], ); - print("DEBUG:::::: dentro al db ci sono: \n${(await campaigns()).length} campagne"); + //int res = (await campaigns()).length; + GeofencingController.removeGeofenceFromId(address); + //print("DEBUG:::::: dentro al db ci sono: \n${(await campaigns()).length} campagne"); } } diff --git a/lib/models/geofence_model.dart b/lib/models/geofence_model.dart deleted file mode 100644 index 1712565..0000000 --- a/lib/models/geofence_model.dart +++ /dev/null @@ -1,95 +0,0 @@ -import 'dart:async'; -import 'package:flutter/foundation.dart'; -import 'package:geolocator/geolocator.dart'; -import '../services/geofence_status.dart'; - -class GeofenceModel { - - late String pointedLatitude, pointedLongitude, radiusMeter; - late int? eventPeriodInSeconds; - - - //documentation: istantiate a Geofance object - // - // if not set eventPeriodInSeconds it will be automatically set to 10 sec - - GeofenceModel( - { - required this.pointedLatitude, - required this.pointedLongitude, - required this.radiusMeter, - this.eventPeriodInSeconds - }); - - StreamSubscription? _positionStream; - - Stream? _geoFencestream; - - final StreamController _controller = StreamController(); - - double _parser(String value) { - if (kDebugMode) { - print("Parse value===>${value.isEmpty}"); - } - double? doubledValue = 0.0; - try { - doubledValue = double.parse(value.isEmpty ? "0" : value); - } catch (e) { - if (kDebugMode) { - print("VALUE IS ===> $value ${value.isEmpty}"); - print("EXCEPTION DOUBLE===> $e"); - } - } - return doubledValue!; - } - - Stream? getGeofenceStream() { - return _geoFencestream; - } - - startGeofenceService() { - //parsing the values to double if in any case they are coming in int etc - double latitude = _parser(pointedLatitude); - double longitude = _parser(pointedLongitude); - double radiusInMeter = _parser(radiusMeter); - //starting the geofence service only if the positionstream is null with us - if (_positionStream == null) { - _geoFencestream = _controller.stream; - _positionStream = Geolocator.getPositionStream( - locationSettings: const LocationSettings(accuracy:LocationAccuracy.high), - ).listen((Position position) { - double distanceInMeters = Geolocator.distanceBetween( - latitude, longitude, position.latitude, position.longitude); - _printOnConsole( - latitude, longitude, position, distanceInMeters, radiusInMeter); - _checkGeofence(distanceInMeters, radiusInMeter); - _positionStream! - .pause(Future.delayed(Duration(seconds: (eventPeriodInSeconds == null)? 10 : eventPeriodInSeconds!))); - }); - _controller.add(GeofenceStatus.init); - } - } - - _checkGeofence(double distanceInMeters, double radiusInMeter) { - if (distanceInMeters <= radiusInMeter) { - _controller.add(GeofenceStatus.enter); - } else { - _controller.add(GeofenceStatus.exit); - } - } - - stopGeofenceService() { - if (_positionStream != null) { - _positionStream!.cancel(); - } - } - - _printOnConsole( - latitude, longitude, Position position, distanceInMeters, radiusInMeter) { - if (kDebugMode) { - print("Started Position $latitude $longitude"); - print("Current Position ${position.toJson()}"); - print("Distance in meters $distanceInMeters and Radius in Meter $radiusInMeter"); - } - } -} diff --git a/lib/models/login_metamask_model.dart b/lib/models/login_metamask_model.dart index 47ab0bf..137bcd0 100644 --- a/lib/models/login_metamask_model.dart +++ b/lib/models/login_metamask_model.dart @@ -1,7 +1,9 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; +import 'package:mobile_crowd_sensing/models/db_capaign_model.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; -import 'package:mobile_crowd_sensing/services/geofencing_service.dart'; +import 'package:mobile_crowd_sensing/services/geofencing_controller.dart'; +import 'package:mobile_crowd_sensing/services/services_controller.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher_string.dart'; import '../services/closed_campaign_service.dart'; @@ -27,11 +29,29 @@ class LoginMetamaskModel { '+ Connector è connesso?: ${sessionData.connector.connected} +\n' '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n'); } - if(!ClosedCampaignService().checkIfInitialized()) { - print('\x1B[31m[INITIALIZE AFTER LOGIN]\x1B[0m'); - await ClosedCampaignService().initializeClosedCampaignService(); + + if(!ServicesController.statusGeofencingService) { + print('\x1B[31m [GEOFENCE SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); + //await ClosedCampaignService().initializeClosedCampaignService(); + // DEBUG + DbCampaignModel().insertCampaign( + const Campaign( + title: "testing campaign", + lat: "44.3883014", + lng: "11.3467744", + radius: "17", + address: "0x000000000000") + ); + await GeofencingController.initializeFromDB(); + ServicesController.initializeGeofencingService(); + } + + if(!ServicesController.statusCloseCampaignService) { + print('\x1B[31m [CLOSED CAMPAIGN SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); + //await ClosedCampaignService().initializeClosedCampaignService(); + ServicesController.initializeCloseCampaignService(); } - //await initializeGeofencingService(); + } catch (exp) { if (kDebugMode) { print(exp); diff --git a/lib/models/search_places_model.dart b/lib/models/search_places_model.dart index 899b7a7..3984a8e 100644 --- a/lib/models/search_places_model.dart +++ b/lib/models/search_places_model.dart @@ -12,6 +12,7 @@ class SearchPlacesModel { Future updateLocalPosition() async { + await Future.delayed(Duration(seconds: 1)); position = await _getGeoLocationPosition(); lng = position.longitude; lat = position.latitude; diff --git a/lib/services/closed_campaign_service.dart b/lib/services/closed_campaign_service.dart index ff2d0e5..4935da6 100644 --- a/lib/services/closed_campaign_service.dart +++ b/lib/services/closed_campaign_service.dart @@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:http/http.dart' as http; +import 'package:mobile_crowd_sensing/services/geofencing.dart'; import 'package:mobile_crowd_sensing/services/notification_channels.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:web3dart/contracts.dart'; @@ -14,9 +15,8 @@ import 'package:flutter_background_service/flutter_background_service.dart'; import 'package:flutter_background_service_android/flutter_background_service_android.dart'; class ClosedCampaignService { - - - static final ClosedCampaignService _instance = ClosedCampaignService._internal(); + static final ClosedCampaignService _instance = + ClosedCampaignService._internal(); static late bool isInitialized; @@ -38,27 +38,78 @@ class ClosedCampaignService { static void onStart(ServiceInstance service) async { DartPluginRegistrant.ensureInitialized(); + DbCampaignModel db = DbCampaignModel(); + List res = []; + + SharedPreferences shared = await SharedPreferences.getInstance(); + String? accountAddress = shared.getString('address'); + + //List geofencingList = []; + + final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); Timer.periodic(const Duration(seconds: 10), (timer) async { - DbCampaignModel db = DbCampaignModel(); - List res = await db.campaigns(); + res = await db.campaigns(); + //geofencingList.clear(); + SmartContractModelBs smartContract; if (kDebugMode) { print( '\x1B[31m[CLOSED CAMPAIGN SERVICE]check db. IS EMPTY? ${res.isEmpty} \x1B[0m'); } if (res.isNotEmpty) { - final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = - FlutterLocalNotificationsPlugin(); int counter = 0; for (Campaign c in res) { - if (kDebugMode) { - print( - '\x1B[31m [CLOSED CAMPAIGN SERVICE]Execution of _process for the $counter time.\x1B[0m'); + Geofencing g = Geofencing( + id: c.address, + pointedLatitude: c.lat, + pointedLongitude: c.lng, + radiusMeter: c.radius); + + switch (g.getStatus()) { + case GeofenceStatus.init: + print('\x1B[31m [GEOFENCE] status: Init\x1B[0m'); + break; + case GeofenceStatus.enter: + print('\x1B[31m [GEOFENCE] status: Enter\x1B[0m'); + flutterLocalNotificationsPlugin.show( + 888, + 'Entered in Campaign Area', + '[${c.title}] \nat address: ${c.address}', + const NotificationDetails( + android: AndroidNotificationDetails( + 'important_channel', + 'MY FOREGROUND SERVICE', + icon: 'ic_bg_service_small', + ongoing: true, + ), + ), + ); + break; + case GeofenceStatus.exit: + print('\x1B[31m [GEOFENCE] status: Exit\x1B[0m'); + flutterLocalNotificationsPlugin.show( + 888, + 'Exit from Campaign Area', + '[${c.title}] \nat address: ${c.address}', + const NotificationDetails( + android: AndroidNotificationDetails( + 'important_channel', + 'MY FOREGROUND SERVICE', + icon: 'ic_bg_service_small', + ongoing: true, + ), + )); + break; + default: + print( + '\x1B[31m [GEOFENCE] status DEFAULT Exit: ${g.getStatus()}\x1B[0m'); + break; } - SharedPreferences shared = await SharedPreferences.getInstance(); - String? accountAddress = shared.getString('address'); + g.stopGeofenceService(); + if (accountAddress == null) { throw NullThrownError(); } @@ -119,11 +170,14 @@ class ClosedCampaignService { '\x1B[31m [CLOSED CAMPAIGN SERVICE] No campaigns to follow. stop the service.\x1B[0m'); } ClosedCampaignService().setIsInizialized(false); - print('\x1B[31m[DEBUG CANCELLAZIONE SERVIZIO]${ ClosedCampaignService().checkIfInitialized() }\x1B[0m'); + print( + '\x1B[31m[DEBUG CANCELLAZIONE SERVIZIO]${ClosedCampaignService().checkIfInitialized()}\x1B[0m'); timer.cancel(); service.stopSelf(); } }); + + print('\x1B[31m[GEOFENCE SERVICE] try to execute the service\x1B[0m'); } Future initializeClosedCampaignService() async { @@ -147,7 +201,7 @@ class ClosedCampaignService { await service.configure( androidConfiguration: AndroidConfiguration( // this will be executed when app is in foreground or background in separated isolate - onStart: onStart, + onStart: ClosedCampaignService.onStart, // auto start service autoStart: true, @@ -172,7 +226,6 @@ class ClosedCampaignService { } } - class SmartContractModelBs { SmartContractModelBs( {required this.accountAddress, diff --git a/lib/services/geofence_status.dart b/lib/services/geofence_status.dart deleted file mode 100644 index 8e1b618..0000000 --- a/lib/services/geofence_status.dart +++ /dev/null @@ -1,7 +0,0 @@ -/// -/// Geofence events state -/// [init]: this is triggered when geofence service started -/// [enter]: this is triggered when the device current location is in the allocated geofence area -/// [exit]: this is triggered when the device current location is outside of the allocated geofence area -/// -enum GeofenceStatus { init, enter, exit } diff --git a/lib/services/geofencing.dart b/lib/services/geofencing.dart new file mode 100644 index 0000000..627b7a9 --- /dev/null +++ b/lib/services/geofencing.dart @@ -0,0 +1,105 @@ +import 'dart:async'; +import 'package:flutter/foundation.dart'; +import 'package:geolocator/geolocator.dart'; + +enum GeofenceStatus { init, enter, exit } + +class Geofencing { + + late final String id, pointedLatitude, pointedLongitude, radiusMeter; + int? eventPeriodInSeconds; + + GeofenceStatus _previusStatus = GeofenceStatus.init; + GeofenceStatus _status = GeofenceStatus.init; + + bool isStatusChanged = false; + + StreamSubscription? _positionStream; + Stream? _geoFencestream; + final StreamController _controller = StreamController(); + + Geofencing({required this.id,required this.pointedLatitude, required this.pointedLongitude, required this.radiusMeter,this.eventPeriodInSeconds}) { + + double latitude = _parser(pointedLatitude); + double longitude = _parser(pointedLongitude); + double radiusInMeter = _parser(radiusMeter); + + if (_positionStream == null) { + _geoFencestream = _controller.stream; + _positionStream = Geolocator.getPositionStream( + desiredAccuracy: LocationAccuracy.high, + ).listen((Position position) { + double distanceInMeters = Geolocator.distanceBetween( + latitude, longitude, position.latitude, position.longitude); + //_printOnConsole(latitude, longitude, position, distanceInMeters, radiusInMeter); + _checkGeofence(distanceInMeters, radiusInMeter); + _positionStream!.pause(Future.delayed(Duration(seconds: (eventPeriodInSeconds != null)? eventPeriodInSeconds! : 2))); + }); + } + } + + double _parser(String? value) { + double doubledValue = 0.0; + + try { + if(value!.isEmpty) { + throw NullThrownError(); + } + doubledValue = double.parse(value.isEmpty ? "0" : value); + + } catch (e) { + print("VALUE IS ===> $value ${value?.isEmpty}"); + print("EXCEPTION DOUBLE===> $e"); + } + return doubledValue; + } + + _checkGeofence(double distanceInMeters, double radiusInMeter) { + if(_previusStatus == _status) { + isStatusChanged = false; + + if (distanceInMeters <= radiusInMeter) { + _status = GeofenceStatus.enter; + } else { + _status = GeofenceStatus.exit; + } + + } else { + isStatusChanged = true; + + if (distanceInMeters <= radiusInMeter) { + _status = GeofenceStatus.enter; + } else { + _status = GeofenceStatus.exit; + } + + _previusStatus = _status; + } + + if (kDebugMode) { + print("STATUS GEOFENCE: $_status IS CHANGED: $isStatusChanged"); + } + } + + GeofenceStatus getStatus() { + return _status; + } + + stopGeofenceService() { + if (_positionStream != null) { + _positionStream!.cancel(); + } + } + + Stream? getGeofenceStream() { + return _geoFencestream; + } + + // _printOnConsole( + // latitude, longitude, Position position, distanceInMeters, radiusInMeter) { + // print("Started Position $latitude $longitude"); + // print("Current Position ${position.toJson()}"); + // print( + // "Distance in meters $distanceInMeters and Radius in Meter $radiusInMeter"); + // } +} diff --git a/lib/services/geofencing_controller.dart b/lib/services/geofencing_controller.dart new file mode 100644 index 0000000..4512055 --- /dev/null +++ b/lib/services/geofencing_controller.dart @@ -0,0 +1,65 @@ +import 'package:flutter/foundation.dart'; +import 'package:mobile_crowd_sensing/models/db_capaign_model.dart'; + +import 'Geofencing.dart'; + +class GeofencingController { + static final List _activeGeofencing = []; + + static registerGeofencing(String id, String pointedLatitude, + String pointedLongitude, String radiusMeter) { + _activeGeofencing.add(Geofencing( + id: id, + pointedLatitude: pointedLatitude, + pointedLongitude: pointedLongitude, + radiusMeter: radiusMeter)); + if (kDebugMode) { + print('\x1B[31m [GEOFENCING CONTROLLER] add Geofence id: $id. \x1B[0m'); + } + } + + static closeAllGeofencing() { + for (Geofencing g in _activeGeofencing) { + g.stopGeofenceService(); + } + _activeGeofencing.clear(); + + if (kDebugMode) { + print('\x1B[31m [GEOFENCING CONTROLLER] delete all geofencing. \x1B[0m'); + } + } + + static getNumberOfActiveGeofence() { + return _activeGeofencing.length; + } + + static removeGeofenceFromId(String id) { + Geofencing selected = _activeGeofencing.firstWhere((item) => item.id == id); + selected.stopGeofenceService(); + _activeGeofencing.remove(selected); + if (kDebugMode) { + print('\x1B[31m [GEOFENCING CONTROLLER] delete geofence id: $id \n number of active geofence: ${getNumberOfActiveGeofence()} \x1B[0m'); + } + } + + static getListOfActiveGeofences(){ + return _activeGeofencing; + } + + static Future initializeFromDB() async { + DbCampaignModel db = DbCampaignModel(); + List res = await db.campaigns(); + + for(Campaign c in res) { + GeofencingController.registerGeofencing( + c.address, + c.lat, + c.lng, + c.radius); + } + if (kDebugMode) { + print('\x1B[31m [GEOFENCING CONTROLLER] initialized: ${res.length} campaigns \x1B[0m'); + } + } + +} diff --git a/lib/services/geofencing_service.dart b/lib/services/geofencing_service.dart deleted file mode 100644 index cc41deb..0000000 --- a/lib/services/geofencing_service.dart +++ /dev/null @@ -1,146 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter_local_notifications/flutter_local_notifications.dart'; -import 'package:geolocator/geolocator.dart'; -import 'package:mobile_crowd_sensing/controllers/geofence_controller.dart'; -import 'package:mobile_crowd_sensing/services/notification_channels.dart'; -import '../models/db_capaign_model.dart'; -import 'dart:async'; -import 'dart:ui'; -import 'package:flutter_background_service/flutter_background_service.dart'; -import '../models/geofence_model.dart'; -import 'geofence_status.dart'; - -//@pragma('vm:entry-point') -void onStart(ServiceInstance service) async { - DbCampaignModel db = DbCampaignModel(); - List res = await db.campaigns(); - if (res.isNotEmpty) { - // Only available for flutter 3.0.0 and later - DartPluginRegistrant.ensureInitialized(); - - final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = - FlutterLocalNotificationsPlugin(); - int i =0; - for (GeofenceModel g in GeofenceController.geofenceList) { - i++; - print('\x1B[31m [GEOFENCE SERVICE] Read the stream for the : $i time\x1B[0m'); - g.getGeofenceStream()!.listen((event) { - switch(event) { - case GeofenceStatus.enter: - if (kDebugMode) { - print('\x1B[31m [GEOFENCE SERVICE] Enter Status \x1B[0m'); - } - flutterLocalNotificationsPlugin.show( - 999, - 'Enter in a Campaign area', - 'you are inside a Campaign area', - const NotificationDetails( - android: AndroidNotificationDetails( - 'important_channel', - 'MY FOREGROUND SERVICE', - icon: 'ic_bg_service_small', - ongoing: true, - ), - )); - break; - case GeofenceStatus.exit: - if (kDebugMode) { - print('\x1B[31m [GEOFENCE SERVICE] Exit Status \x1B[0m'); - } - flutterLocalNotificationsPlugin.show( - 999, - 'Exit from Campaign area', - 'you are out from the area', - const NotificationDetails( - android: AndroidNotificationDetails( - 'important_channel', - 'MY FOREGROUND SERVICE', - icon: 'ic_bg_service_small', - ongoing: true, - ), - ), - ); - break; - case GeofenceStatus.init: - if (kDebugMode) { - print('\x1B[31m [GEOFENCE SERVICE] init Status \x1B[0m'); - } - break; - } - }); - } - } else { - if (kDebugMode) { - print('\x1B[31m [GEOFENCE SERVICE] database empty: the service ' - 'was closed after start\x1B[0m'); - } - service.stopSelf(); - } -} - -Future initializeGeofencingService() async { - DbCampaignModel db = DbCampaignModel(); - List res = await db.campaigns(); - if (res.isNotEmpty) { - - // check the permission for geolocation - - bool serviceEnabled; - LocationPermission permission; - - serviceEnabled = await Geolocator.isLocationServiceEnabled(); - if (!serviceEnabled) { - await Geolocator.openLocationSettings(); - return Future.error('Location services are disabled.'); - } - - permission = await Geolocator.checkPermission(); - if (permission == LocationPermission.denied) { - permission = await Geolocator.requestPermission(); - if (permission == LocationPermission.denied) { - return Future.error('Location permissions are denied'); - } - } - - if (permission == LocationPermission.deniedForever) { - return Future.error( - 'Location permissions are permanently denied, we cannot request permissions.'); - } - - print('\x1B[31m [GEOFENCE SERVICE]Inizializzazione del servizio: [GEOFENCE]\x1B[0m'); - - GeofenceController.geofenceInitByDb(); - - FlutterBackgroundService service = FlutterBackgroundService(); - - final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = - FlutterLocalNotificationsPlugin(); - - await flutterLocalNotificationsPlugin - .resolvePlatformSpecificImplementation< - AndroidFlutterLocalNotificationsPlugin>() - ?.createNotificationChannel(NotificationChannel.importantChannel); - - await service.configure( - androidConfiguration: AndroidConfiguration( - // this will be executed when app is in foreground or background in separated isolate - onStart: onStart, - - // auto start service - autoStart: true, - isForegroundMode: true, - - notificationChannelId: 'important_channel', - initialNotificationTitle: 'geofence service', - initialNotificationContent: - 'this service notify eventually submitted campaign area entrance', - foregroundServiceNotificationId: 999, - ), - iosConfiguration: IosConfiguration(), - ); - - service.startService(); - } else { - print('\x1B[31m [GEOFENCE SERVICE]The database is empty. no services to initialize\x1B[0m'); - } -} diff --git a/lib/services/notification_channels.dart b/lib/services/notification_channels.dart index eedf97f..86fcbeb 100644 --- a/lib/services/notification_channels.dart +++ b/lib/services/notification_channels.dart @@ -10,6 +10,15 @@ class NotificationChannel { importance: Importance.max, // importance must be at low or higher level ); + static AndroidNotificationChannel importantChannel_2 = + const AndroidNotificationChannel( + 'important_channel_2', // id + 'IMPORTANT NOTIFICATION CHANNEL', // title + description: + 'This channel is used for important notification.', // description + importance: Importance.max, // importance must be at low or higher level + ); + static AndroidNotificationChannel lowImportantChannel = const AndroidNotificationChannel( 'low_important_channel', // id diff --git a/lib/services/services.dart b/lib/services/services.dart new file mode 100644 index 0000000..2bfc6d0 --- /dev/null +++ b/lib/services/services.dart @@ -0,0 +1,203 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:http/http.dart' as http; +import 'package:mobile_crowd_sensing/services/geofencing.dart'; +import 'package:mobile_crowd_sensing/services/geofencing_controller.dart'; +import 'package:mobile_crowd_sensing/services/notification_channels.dart'; +import 'package:mobile_crowd_sensing/services/services_controller.dart'; +import 'package:web3dart/contracts.dart'; +import 'package:web3dart/credentials.dart'; +import 'package:web3dart/web3dart.dart'; +import '../models/db_capaign_model.dart'; +import 'dart:async'; +import 'dart:ui'; + +class Services { + @pragma('vm:entry-point') + static void checkCloseCampaign(Map args) async { + DartPluginRegistrant.ensureInitialized(); + DbCampaignModel db = DbCampaignModel(); + List res = []; + String accountAddress = args['accountAddress']; + + final FlutterLocalNotificationsPlugin notification = + FlutterLocalNotificationsPlugin(); + + await notification + .resolvePlatformSpecificImplementation< + AndroidFlutterLocalNotificationsPlugin>() + ?.createNotificationChannel(NotificationChannel.importantChannel); + + Timer.periodic(const Duration(seconds: 60), (timer) async { + ServicesController.statusCloseCampaignService = true; + res = await db.campaigns(); + if (res.isNotEmpty) { + for (Campaign c in res) { + String address = c.address; + String title = c.title; + + SmartContractModelBs smartContract = SmartContractModelBs( + contractAddress: address, + abiName: 'Campaign', + abiFileRoot: 'assets/abi_campaign.json', + accountAddress: accountAddress); + + List? isClosedRaw = + await smartContract.queryCall('isClosed', []); + + if (isClosedRaw != null) { + String answer = isClosedRaw[0].toString(); + + if (answer == "true") { + // the campaign result closed + if (kDebugMode) { + print('\x1B[31mThe campaign was closed\x1B[0m'); + } + + notification.show( + 888, + 'Campaign Closed', + 'The campaign [$title] \nat address $address \n was closed by crowdsourcer', + const NotificationDetails( + android: AndroidNotificationDetails( + 'important_channel', + 'MY FOREGROUND SERVICE', + icon: 'ic_bg_service_small', + ongoing: false, + ), + ), + ); + + await db.deleteCampaign(address); + } else { + print( + '\x1B[31m [CLOSED CAMPAIGN SERVICE] The campaign still open: nothing to notify. \x1B[0m'); + } + } else { + print( + '\x1B[31m [CLOSED CAMPAIGN SERVICE]an error occurred. \x1B[0m'); + } + } + } else { + ServicesController.statusCloseCampaignService = false; + timer.cancel(); + print( + '\x1B[31m [CLOSED CAMPAIGN SERVICE] No campaigns to follow. stop the service.\x1B[0m'); + } + }); + } + + @pragma('vm:entry-point') + static void checkGeofence(Map args) async { + DartPluginRegistrant.ensureInitialized(); + print('\x1B[31m [GEOFENCING SERVICE] DEBUG:gate1 KKKKK} \x1B[0m'); + + final FlutterLocalNotificationsPlugin notification = + FlutterLocalNotificationsPlugin(); + + await notification + .resolvePlatformSpecificImplementation< + AndroidFlutterLocalNotificationsPlugin>() + ?.createNotificationChannel(NotificationChannel.importantChannel); + print('\x1B[31m [GEOFENCING SERVICE] DEBUG: Geofence registrati ${GeofencingController.getListOfActiveGeofences()} \x1B[0m'); + + Timer.periodic(const Duration(seconds: 5), (timer) async { + ServicesController.statusGeofencingService = true; + if (GeofencingController.getNumberOfActiveGeofence() > 0) { + for (Geofencing g in GeofencingController.getListOfActiveGeofences()) { + print('\x1B[31m [GEOFENCING SERVICE] DEBUG: ${g.isStatusChanged} \x1B[0m'); + if (g.isStatusChanged) { + switch (g.getStatus()) { + case GeofenceStatus.init: + print( + '\x1B[31m [GEOFENCING SERVICE] enter in Init state. \x1B[0m'); + break; + case GeofenceStatus.enter: + notification.show( + 888, + 'Enter in a Campaign Area', + 'inside the area', + const NotificationDetails( + android: AndroidNotificationDetails( + 'important_channel', + 'MY FOREGROUND SERVICE', + icon: 'ic_bg_service_small', + ongoing: false, + ), + ), + ); + break; + case GeofenceStatus.exit: + notification.show( + 888, + 'Exit from Campaign Area', + 'inside the area', + const NotificationDetails( + android: AndroidNotificationDetails( + 'important_channel', + 'MY FOREGROUND SERVICE', + icon: 'ic_bg_service_small', + ongoing: false, + ))); + break; + } + } + } + } else { + ServicesController.statusGeofencingService = false; + timer.cancel(); + print('\x1B[31m [GEOFENCING SERVICE] No campaigns to follow. stop the service.\x1B[0m'); + } + }); + } +} + +class SmartContractModelBs { + SmartContractModelBs( + {required this.accountAddress, + required this.contractAddress, + required this.abiName, + required this.abiFileRoot}); + + final String accountAddress; + final String contractAddress; + final String abiName; + final String abiFileRoot; + late http.Client httpClient; + late Web3Client ethClient; + + Future loadContract(String contractAddress) async { + String abi = await rootBundle.loadString(abiFileRoot); + final contract = DeployedContract(ContractAbi.fromJson(abi, abiName), + EthereumAddress.fromHex(contractAddress)); + return contract; + } + + Future?> queryCall( + String functionName, List args) async { + try { + httpClient = http.Client(); + ethClient = Web3Client( + "https://goerli.infura.io/v3/5074605772bb4bc4b6970d2ce999efca", + httpClient); + + final contract = await loadContract(contractAddress); + final ethFunction = contract.function(functionName); + final result = await ethClient.call( + sender: EthereumAddress.fromHex(accountAddress), + contract: contract, + function: ethFunction, + params: args); + List res = result; + return res; + } catch (e) { + if (kDebugMode) { + print('\x1B[31m$e\x1B[0m'); + } + return null; + } + } +} + + diff --git a/lib/services/services_controller.dart b/lib/services/services_controller.dart new file mode 100644 index 0000000..e01ab88 --- /dev/null +++ b/lib/services/services_controller.dart @@ -0,0 +1,23 @@ +import 'package:flutter_isolate/flutter_isolate.dart'; +import 'package:mobile_crowd_sensing/services/geofencing_controller.dart'; +import 'package:mobile_crowd_sensing/services/services.dart'; + +import '../models/session_model.dart'; + +class ServicesController{ + + static bool statusCloseCampaignService = false; + static bool statusGeofencingService = false; + + static void initializeCloseCampaignService() async { + FlutterIsolate.spawn(Services.checkCloseCampaign, { + 'accountAddress' : SessionModel().getAccountAddress() + }); + statusCloseCampaignService = true; + } + + static void initializeGeofencingService() async { + FlutterIsolate.spawn(Services.checkGeofence, {}); + statusGeofencingService = true; + } +} \ No newline at end of file diff --git a/lib/utils/internet_connection.dart b/lib/utils/internet_connection.dart new file mode 100644 index 0000000..b31ef62 --- /dev/null +++ b/lib/utils/internet_connection.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'dart:async'; +import 'package:connectivity/connectivity.dart'; +import '../main.dart'; + +class InternetConnection { + static var connectionStatus; + + static Future checkInternetConnectivity() async { + connectionStatus = await Connectivity().checkConnectivity(); + if (connectionStatus == ConnectivityResult.none) { + PageRouteBuilder( + pageBuilder: (_, __, ___) => + MaterialApp(home: Builder( + builder: (_) => MyApp())), + transitionDuration: Duration.zero,); + } + } +} \ No newline at end of file diff --git a/lib/views/verifier_campaign_data_light_view.dart b/lib/views/verifier_campaign_data_light_view.dart index 8f4dc44..a3e4029 100644 --- a/lib/views/verifier_campaign_data_light_view.dart +++ b/lib/views/verifier_campaign_data_light_view.dart @@ -1,7 +1,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:mobile_crowd_sensing/utils/verifier_campaign_data_factory.dart'; -import '../controllers/verifier_campaign_data_light_controller.dart'; +import '../controllers/verifier_campaign_data_controller.dart'; class VerifierCampaignDataLightView extends VerifierDataCampaignFactory { const VerifierCampaignDataLightView({Key? key}) : super(key: key); @@ -30,7 +30,7 @@ class _VerifierCampaignDataLightViewState extends State { title: const Text('List Of All Campaigns to Verify'), centerTitle: true, ), - body: VerifierCampaignController(widget.contractsAddresses) + body: CampaignListController(contractsAddresses: widget.contractsAddresses!, goTo: '/verifier_campaign_data',) ); } } diff --git a/lib/views/worker_campaign_view.dart b/lib/views/worker_campaign_view.dart index e8509d2..78f84e1 100644 --- a/lib/views/worker_campaign_view.dart +++ b/lib/views/worker_campaign_view.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; -import '../controllers/worker_campaign_controller.dart'; - +import '../controllers/campaign_list_controller.dart'; class WorkerCampaignView extends StatefulWidget { final List? contractsAddresses; @@ -26,7 +25,7 @@ class _WorkerCampaignViewState extends State { title: const Text('List Of All Campaigns'), centerTitle: true, ), - body: WorkerCampaignController(widget.contractsAddresses) + body: CampaignListController(contractsAddresses: widget.contractsAddresses!, goTo: '/join_campaign',) ); } } diff --git a/pubspec.lock b/pubspec.lock index 81bb087..0599a5f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -190,6 +190,34 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.16.0" + connectivity: + dependency: "direct main" + description: + name: connectivity + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.6" + connectivity_for_web: + dependency: transitive + description: + name: connectivity_for_web + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.0+1" + connectivity_macos: + dependency: transitive + description: + name: connectivity_macos + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.1+2" + connectivity_platform_interface: + dependency: transitive + description: + name: connectivity_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" convert: dependency: transitive description: @@ -267,6 +295,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.6" + easy_geofencing: + dependency: "direct main" + description: + name: easy_geofencing + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0" eip55: dependency: transitive description: @@ -384,6 +419,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.0.1" + flutter_isolate: + dependency: "direct main" + description: + name: flutter_isolate + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" flutter_lints: dependency: "direct dev" description: @@ -477,42 +519,35 @@ packages: name: geolocator url: "https://pub.dartlang.org" source: hosted - version: "9.0.2" + version: "7.7.1" geolocator_android: dependency: transitive description: name: geolocator_android url: "https://pub.dartlang.org" source: hosted - version: "4.1.4" + version: "2.1.0" geolocator_apple: dependency: transitive description: name: geolocator_apple url: "https://pub.dartlang.org" source: hosted - version: "2.2.3" + version: "1.2.2" geolocator_platform_interface: dependency: transitive description: name: geolocator_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "4.0.7" + version: "2.3.6" geolocator_web: dependency: transitive description: name: geolocator_web url: "https://pub.dartlang.org" source: hosted - version: "2.1.6" - geolocator_windows: - dependency: transitive - description: - name: geolocator_windows - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.1" + version: "2.0.6" glob: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 47acf7a..6299204 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -67,6 +67,9 @@ dependencies: flutter_foreground_task: ^3.10.0 numberpicker: ^2.1.1 flip_card: ^0.7.0 + connectivity: ^3.0.6 + flutter_isolate: ^2.0.4 + easy_geofencing: ^0.2.0 dev_dependencies: flutter_test: From c8609979dfe89f9b3a219571272c54a7149a11f9 Mon Sep 17 00:00:00 2001 From: Giacomo Galletti Date: Sun, 29 Jan 2023 12:59:58 +0100 Subject: [PATCH 08/34] payment system --- assets/abi.json | 358 +++++++++++++++++- assets/abi_abstract_factory.json | 150 ++++++-- assets/abi_campaign.json | 86 +---- assets/abi_coin.json | 287 +++++++------- contracts/Campaign.sol | 20 +- contracts/FactoryManager.sol | 74 ++-- contracts/MCScoin.sol | 11 +- contracts/MCSfactory.sol | 64 ++-- lib/controllers/all_campaign_controller.dart | 2 + lib/controllers/campaign_list_controller.dart | 19 +- .../create_campaign_form_controller.dart | 10 +- lib/controllers/wallet_controller.dart | 14 +- lib/models/db_capaign_model.dart | 6 - lib/models/login_metamask_model.dart | 3 +- lib/models/my_campaign_model.dart | 5 +- lib/models/session_model.dart | 1 - lib/models/smart_contract_model.dart | 3 + lib/models/wallet_model.dart | 6 +- lib/services/geofencing_controller.dart | 16 +- lib/services/services.dart | 41 +- lib/utils/nonce_manager.dart | 12 + lib/views/campaign_data_light_view.dart | 6 +- lib/views/photo_join_campaign_view.dart | 25 +- 23 files changed, 795 insertions(+), 424 deletions(-) create mode 100644 lib/utils/nonce_manager.dart diff --git a/assets/abi.json b/assets/abi.json index a8f003e..4236499 100644 --- a/assets/abi.json +++ b/assets/abi.json @@ -1,37 +1,127 @@ [ { "inputs": [ + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + }, { "internalType": "address", - "name": "_addressCoinContract", + "name": "factoryManagerAddress", "type": "address" } ], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "constructor" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" } ], - "name": "activeCampaigns", + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", "outputs": [ { - "internalType": "contract Campaign", + "internalType": "uint256", "name": "", - "type": "address" + "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "closeCampaign", + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", "outputs": [ { "internalType": "bool", @@ -46,37 +136,63 @@ "inputs": [ { "internalType": "address", - "name": "", + "name": "account", "type": "address" - }, + } + ], + "name": "balanceOf", + "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], - "name": "closedCampaigns", - "outputs": [ + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ { - "internalType": "contract Campaign", - "name": "", + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "stateMutability": "view", + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], - "name": "coinAddress", + "name": "closeCampaign", "outputs": [ { - "internalType": "address", + "internalType": "bool", "name": "", - "type": "address" + "type": "bool" } ], - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { @@ -123,6 +239,63 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "destroy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getActiveCampaign", + "outputs": [ + { + "internalType": "contract Campaign", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "getAllCampaigns", @@ -153,11 +326,16 @@ "inputs": [ { "internalType": "address", - "name": "_address", + "name": "spender", "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" } ], - "name": "searchSourcerAddress", + "name": "increaseAllowance", "outputs": [ { "internalType": "bool", @@ -165,7 +343,145 @@ "type": "bool" } ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "name": "setBlockReward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } ] \ No newline at end of file diff --git a/assets/abi_abstract_factory.json b/assets/abi_abstract_factory.json index fec7c83..6525610 100644 --- a/assets/abi_abstract_factory.json +++ b/assets/abi_abstract_factory.json @@ -3,16 +3,16 @@ "inputs": [ { "internalType": "address", - "name": "", + "name": "sourcer", "type": "address" } ], - "name": "activeCampaigns", + "name": "_checkIfSourcerHasActiveCampaign", "outputs": [ { - "internalType": "contract Campaign", + "internalType": "bool", "name": "", - "type": "address" + "type": "bool" } ], "stateMutability": "view", @@ -20,7 +20,7 @@ }, { "inputs": [], - "name": "closeCampaign", + "name": "_closeCampaign", "outputs": [ { "internalType": "bool", @@ -31,30 +31,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "closedCampaigns", - "outputs": [ - { - "internalType": "contract Campaign", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -83,12 +59,17 @@ "type": "string" }, { - "internalType": "uint256", - "name": "_value", - "type": "uint256" + "internalType": "address", + "name": "sourcer", + "type": "address" + }, + { + "internalType": "address", + "name": "factoryAddress", + "type": "address" } ], - "name": "createCampaign", + "name": "_createCampaign", "outputs": [ { "internalType": "address", @@ -96,12 +77,31 @@ "type": "address" } ], - "stateMutability": "payable", + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sourcer", + "type": "address" + } + ], + "name": "_getActiveCampaign", + "outputs": [ + { + "internalType": "contract Campaign", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", "type": "function" }, { "inputs": [], - "name": "getAllCampaigns", + "name": "_getAllCampaigns", "outputs": [ { "internalType": "contract Campaign[]", @@ -113,8 +113,14 @@ "type": "function" }, { - "inputs": [], - "name": "getClosedCampaigns", + "inputs": [ + { + "internalType": "address", + "name": "sourcer", + "type": "address" + } + ], + "name": "_getClosedCampaigns", "outputs": [ { "internalType": "contract Campaign[]", @@ -129,16 +135,78 @@ "inputs": [ { "internalType": "address", - "name": "_address", + "name": "", "type": "address" } ], - "name": "searchSourcerAddress", + "name": "activeCampaigns", "outputs": [ { - "internalType": "bool", + "internalType": "contract Campaign", "name": "", - "type": "bool" + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "addressCrowdSourcerActiveCampaigns", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "addressCrowdSourcerClosedCampaigns", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "closedCampaigns", + "outputs": [ + { + "internalType": "contract Campaign", + "name": "", + "type": "address" } ], "stateMutability": "view", diff --git a/assets/abi_campaign.json b/assets/abi_campaign.json index 579407f..6c7119f 100644 --- a/assets/abi_campaign.json +++ b/assets/abi_campaign.json @@ -35,11 +35,6 @@ "internalType": "address", "name": "_factoryAddress", "type": "address" - }, - { - "internalType": "address", - "name": "_coinContractAddress", - "type": "address" } ], "stateMutability": "payable", @@ -122,30 +117,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "int256", - "name": "latFile", - "type": "int256" - }, - { - "internalType": "int256", - "name": "lonFile", - "type": "int256" - } - ], - "name": "calculateDistance", - "outputs": [ - { - "internalType": "int256", - "name": "dist", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "checkedFiles", @@ -173,19 +144,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [], - "name": "coinAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "fileCount", @@ -233,6 +191,16 @@ "internalType": "string", "name": "hash", "type": "string" + }, + { + "internalType": "int256", + "name": "lat", + "type": "int256" + }, + { + "internalType": "int256", + "name": "lng", + "type": "int256" } ], "stateMutability": "view", @@ -268,6 +236,16 @@ "internalType": "string", "name": "hash", "type": "string" + }, + { + "internalType": "int256", + "name": "lat", + "type": "int256" + }, + { + "internalType": "int256", + "name": "lng", + "type": "int256" } ], "internalType": "struct Campaign.File[]", @@ -360,30 +338,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "int256", - "name": "latFile", - "type": "int256" - }, - { - "internalType": "int256", - "name": "lonFile", - "type": "int256" - } - ], - "name": "isInRange", - "outputs": [ - { - "internalType": "bool", - "name": "answer", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { diff --git a/assets/abi_coin.json b/assets/abi_coin.json index 3fecd00..f559ff6 100644 --- a/assets/abi_coin.json +++ b/assets/abi_coin.json @@ -1,14 +1,28 @@ [ { + "anonymous": false, "inputs": [ { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, "internalType": "uint256", - "name": "reward", + "name": "value", "type": "uint256" } ], - "stateMutability": "nonpayable", - "type": "constructor" + "name": "Approval", + "type": "event" }, { "anonymous": false, @@ -16,13 +30,32 @@ { "indexed": true, "internalType": "address", - "name": "owner", + "name": "previousOwner", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "spender", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", "type": "address" }, { @@ -32,9 +65,33 @@ "type": "uint256" } ], - "name": "Approval", + "name": "Transfer", "type": "event" }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -59,6 +116,25 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -90,6 +166,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -146,23 +235,30 @@ "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "name", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "newOwner", + "name": "", "type": "address" } ], - "name": "OwnershipTransferred", - "type": "event" + "stateMutability": "view", + "type": "function" }, { "inputs": [], @@ -185,61 +281,33 @@ "type": "function" }, { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", + "inputs": [], + "name": "symbol", "outputs": [ { - "internalType": "bool", + "internalType": "string", "name": "", - "type": "bool" + "type": "string" } ], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, + "inputs": [], + "name": "totalSupply", + "outputs": [ { - "indexed": false, "internalType": "uint256", - "name": "value", + "name": "", "type": "uint256" } ], - "name": "Transfer", - "type": "event" + "stateMutability": "view", + "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, { "internalType": "address", "name": "to", @@ -251,7 +319,7 @@ "type": "uint256" } ], - "name": "transferFrom", + "name": "transfer", "outputs": [ { "internalType": "bool", @@ -266,121 +334,42 @@ "inputs": [ { "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", + "name": "from", "type": "address" }, { "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", + "name": "to", "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ + }, { "internalType": "uint256", - "name": "", + "name": "amount", "type": "uint256" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "name", + "name": "transferFrom", "outputs": [ { - "internalType": "string", + "internalType": "bool", "name": "", - "type": "string" + "type": "bool" } ], - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "owner", - "outputs": [ + "inputs": [ { "internalType": "address", - "name": "", + "name": "newOwner", "type": "address" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" } ] \ No newline at end of file diff --git a/contracts/Campaign.sol b/contracts/Campaign.sol index 6c39898..91f27d1 100644 --- a/contracts/Campaign.sol +++ b/contracts/Campaign.sol @@ -18,10 +18,7 @@ contract Campaign is Ownable, Initializable { uint256 public numberOfActiveWorkers = 0; uint256 public numberOfActiveVerifiers = 0; bool public isClosed; - CampaignFactory internal factoryContractAddress; - address public coinAddress; - MCSCoin internal coin; mapping(string => File) public files; // ipfs hash -> file info @@ -59,9 +56,7 @@ contract Campaign is Ownable, Initializable { return(name,lat,lng,range,campaignType,addressCrowdSourcer,fileCount); } - constructor(string memory _name,int256 _lat,int256 _lng,int256 _range,string memory _type,address _addressCrowdSourcer,address _factoryAddress,address _coinContractAddress) onlyOwner payable initializer { - coinAddress =_coinContractAddress; - coin = MCSCoin(coinAddress); + constructor(string memory _name,int256 _lat,int256 _lng,int256 _range,string memory _type,address _addressCrowdSourcer,address _factoryAddress) onlyOwner payable initializer { name = _name; lat = _lat; lng = _lng; @@ -101,19 +96,18 @@ contract Campaign is Ownable, Initializable { } function getCampaignBalance() public view returns(uint256 balance) { - return coin.balanceOf(address(this)); + return factoryContractAddress.balanceOf(address(this)); } // tenuta per debug - function closeCampaign() public { + function closeCampaign() external { require(msg.sender == addressCrowdSourcer,'you are not the owner'); require(msg.sender != address(0), "invalid address provided"); isClosed = factoryContractAddress.closeCampaign(); } - function closeCampaignAndPay() public payable { + function closeCampaignAndPay() external payable { require(msg.sender == addressCrowdSourcer,'you are not the owner'); - require(msg.sender != address(0), "invalid address provided"); isClosed = factoryContractAddress.closeCampaign(); for(uint i; i Campaign) public activeCampaigns; // address sourcer -> campagna - mapping( address => Campaign[]) public closedCampaigns; // address sourcer -> lista di campagne - address[] internal addressKeyLUT; - address[] internal addressClosedKeyLUT; - - function searchSourcerAddress(address _address) public view returns (bool) { - require(msg.sender != address(0), "invalid address provided"); - for (uint256 i = 0; i < addressKeyLUT.length; i++) { - if (addressKeyLUT[i] == _address) { - return true; - } +contract FactoryManager { + + mapping( address => Campaign) public activeCampaigns; + mapping( address => Campaign[]) public closedCampaigns; + + address[] public addressCrowdSourcerActiveCampaigns; + address[] public addressCrowdSourcerClosedCampaigns; + + function _createCampaign(string memory _name,int256 _lat,int256 _lng, int256 _range, string memory _type,address sourcer, address factoryAddress) public returns (address){ + Campaign newCampaign = new Campaign(_name, _lat, _lng,_range,_type,sourcer,factoryAddress); + activeCampaigns[sourcer] = newCampaign; + addressCrowdSourcerActiveCampaigns.push(sourcer); + return (address(newCampaign)); + } + + function _getAllCampaigns() external view returns (Campaign[] memory) { + Campaign[] memory outPut = new Campaign[](addressCrowdSourcerActiveCampaigns.length); + for (uint256 i = 0; i < addressCrowdSourcerActiveCampaigns.length; i++) { + outPut[i] = activeCampaigns[addressCrowdSourcerActiveCampaigns[i]]; } - return false; + return outPut; } - function _burnLUT(uint index) internal { - require(index < addressKeyLUT.length); - addressKeyLUT[index] = addressKeyLUT[addressKeyLUT.length-1]; - addressKeyLUT.pop(); + function _getClosedCampaigns(address sourcer) external view returns (Campaign[] memory) { + require(sourcer != address(0), "invalid address provided"); + return(closedCampaigns[sourcer]); } - function getAllCampaigns() public view returns (Campaign[] memory) { - Campaign[] memory outPut = new Campaign[](addressKeyLUT.length); - for (uint256 i = 0; i < addressKeyLUT.length; i++) { - outPut[i] = activeCampaigns[addressKeyLUT[i]]; + function _closeCampaign() external returns (bool){ + if(address(activeCampaigns[tx.origin])!=address(0)) { + require(tx.origin == activeCampaigns[tx.origin].addressCrowdSourcer(),'you are not the campaign owner'); + closedCampaigns[tx.origin].push(activeCampaigns[tx.origin]); + delete activeCampaigns[tx.origin]; + for (uint i = 0; i < addressCrowdSourcerActiveCampaigns.length; i++){ + if(addressCrowdSourcerActiveCampaigns[i] == tx.origin) { + addressCrowdSourcerClosedCampaigns.push(tx.origin); + addressCrowdSourcerActiveCampaigns[i] = addressCrowdSourcerActiveCampaigns[addressCrowdSourcerActiveCampaigns.length-1]; + addressCrowdSourcerActiveCampaigns.pop(); + break; + } + } + return true; + } else { + return false; } - return outPut; } - function getClosedCampaigns() public view returns (Campaign[] memory) { - require(msg.sender != address(0), "invalid address provided"); - return(closedCampaigns[msg.sender]); + function _checkIfSourcerHasActiveCampaign(address sourcer) external view returns(bool) { + return (address(activeCampaigns[sourcer]) == address(0))? false : true; + } + + function _getActiveCampaign(address sourcer) external view returns(Campaign) { + return activeCampaigns[sourcer]; } - function closeCampaign() external virtual returns (bool); - function createCampaign(string memory _name,int256 _lat,int256 _lng, int256 _range, string memory _type,uint256 _value) public payable virtual returns (address); } \ No newline at end of file diff --git a/contracts/MCScoin.sol b/contracts/MCScoin.sol index 4f2f261..8e26bc5 100644 --- a/contracts/MCScoin.sol +++ b/contracts/MCScoin.sol @@ -4,16 +4,12 @@ pragma solidity ^0.8.17; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; +import "./MCSfactory.sol"; -contract MCSCoin is ERC20, ERC20Burnable, Ownable { +abstract contract MCScoin is ERC20, ERC20Burnable, Ownable { uint256 blockReward; - constructor (uint256 reward) ERC20("Mobile Crowd Sensing Coin", "MCSCoin") { - _mint(msg.sender, 100 * (10 ** uint256(decimals()))); - blockReward = reward * (10 ** uint(decimals())); - } - function setBlockReward(uint256 reward) public onlyOwner() { blockReward = reward * (10 ** decimals()); } @@ -32,5 +28,8 @@ contract MCSCoin is ERC20, ERC20Burnable, Ownable { function destroy() public onlyOwner() { selfdestruct(payable(owner())); } + + + } diff --git a/contracts/MCSfactory.sol b/contracts/MCSfactory.sol index 83e315b..c1b18e9 100644 --- a/contracts/MCSfactory.sol +++ b/contracts/MCSfactory.sol @@ -4,51 +4,41 @@ pragma solidity ^0.8.17; import "./Campaign.sol"; import "./MCScoin.sol"; import "./FactoryManager.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; -import "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; import "hardhat/console.sol"; -contract CampaignFactory is FactoryManager{ +contract CampaignFactory is MCScoin { - address public coinAddress; - MCSCoin internal coin; + FactoryManager factoryManager; - constructor(address _addressCoinContract) payable { - coinAddress=_addressCoinContract; - coin = MCSCoin(coinAddress); + constructor (uint256 reward,address factoryManagerAddress) ERC20("Mobile Crowd Sensing Coin", "MCSCoin") { + _mint(msg.sender, 10000000 * (10 ** uint256(decimals()))); + blockReward = reward * (10 ** uint(decimals())); + factoryManager = FactoryManager(factoryManagerAddress); } - function createCampaign(string memory _name,int256 _lat,int256 _lng, int256 _range, string memory _type,uint256 _value) public override payable returns (address ) { - require(msg.sender != address(0), "invalid address provided"); - require(_value >= 1,"not enough value in message"); - //address sender = payable(msg.sender); - //uint256 balance = coin.balanceOf(sender); - //require(balance >= _value,"not enough found in your balance"); - require(!searchSourcerAddress(msg.sender),"this sourcer already has an active campaign"); - Campaign newCampaign = new Campaign(_name, _lat, _lng,_range,_type,(msg.sender),(address(this)),(address(coin))); - address newCampaignAddress = payable(address(newCampaign)); - //coin.approve(payable(address(this)),_value); - //coin.transferFrom(sender,newCampaignAddress,_value); - activeCampaigns[msg.sender] = newCampaign; - addressKeyLUT.push(msg.sender); - return (newCampaignAddress); + + function createCampaign(string memory _name,int256 _lat,int256 _lng, int256 _range, string memory _type,uint256 _value) public payable returns (address) { + address owner = _msgSender(); + require(!factoryManager._checkIfSourcerHasActiveCampaign(owner),"this sourcer already has an active campaign"); + address to = factoryManager._createCampaign(_name, _lat, _lng,_range,_type,(msg.sender),(address(this))); + _transfer(owner,payable(to), _value); + return to; + } + + function closeCampaign() external returns (bool){ + return factoryManager._closeCampaign(); + } + + function getClosedCampaigns() public view returns (Campaign[] memory) { + return factoryManager._getClosedCampaigns(msg.sender); + } + + function getAllCampaigns() public view returns (Campaign[] memory) { + return factoryManager._getAllCampaigns(); } - function closeCampaign() external override returns (bool){ - if(address(activeCampaigns[tx.origin])!=address(0)) { - require(tx.origin == activeCampaigns[tx.origin].addressCrowdSourcer(),'you are not the campaign owner'); - closedCampaigns[tx.origin].push(activeCampaigns[tx.origin]); - delete activeCampaigns[tx.origin]; - for (uint i = 0; i < addressKeyLUT.length; i++){ - if(addressKeyLUT[i] == tx.origin) { - addressClosedKeyLUT.push(tx.origin); - _burnLUT(i); - } - } - return true; - } else { - return false; - } + function getActiveCampaign() public view returns (Campaign) { + return factoryManager._getActiveCampaign(msg.sender); } } \ No newline at end of file diff --git a/lib/controllers/all_campaign_controller.dart b/lib/controllers/all_campaign_controller.dart index 01299a7..b405a1a 100644 --- a/lib/controllers/all_campaign_controller.dart +++ b/lib/controllers/all_campaign_controller.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:mobile_crowd_sensing/controllers/search_places_controller.dart'; import 'package:mobile_crowd_sensing/utils/spalsh_screens.dart'; import '../models/all_campaign_model.dart'; +import '../models/search_places_model.dart'; import '../views/dialog_view.dart'; import '../views/verifier_campaign_view.dart'; import '../views/worker_campaign_view.dart'; diff --git a/lib/controllers/campaign_list_controller.dart b/lib/controllers/campaign_list_controller.dart index 867f135..3eb19cd 100644 --- a/lib/controllers/campaign_list_controller.dart +++ b/lib/controllers/campaign_list_controller.dart @@ -100,6 +100,9 @@ class _CampaignListControllerState isSubscribed = current[9]; return GestureDetector( onTap: () { + + if(_checkIfDeviceIsInArea(lat!,lng!,range!)) { + Navigator.pushNamed( context, widget.goTo, arguments: { @@ -112,6 +115,13 @@ class _CampaignListControllerState 'lat': lat, 'lng': lng, }); + } else { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text( + 'Out of position', + style: CustomTextStyle.spaceMonoWhite(context), + ))); + } }, child: _cardWidget( isSubscribed!, @@ -159,9 +169,6 @@ class _CampaignListControllerState padding: const EdgeInsets.all(20), child: Stack( children: [ - // Align( - // alignment: Alignment.topRight, - // child: ), Align( alignment: Alignment.topLeft, child: Column(children: [ @@ -333,4 +340,10 @@ class _CampaignListControllerState return true; } } + + bool _checkIfDeviceIsInArea(String lat, String lon, String range) { + widget.places.updateLocalPosition(); + dynamic distance = DistanceController.distanceBetween(widget.places.lat, widget.places.lng, double.parse(lat), double.parse(lon)); + return (distance <= double.parse(range))? true : false; + } } diff --git a/lib/controllers/create_campaign_form_controller.dart b/lib/controllers/create_campaign_form_controller.dart index 9f12332..892d580 100644 --- a/lib/controllers/create_campaign_form_controller.dart +++ b/lib/controllers/create_campaign_form_controller.dart @@ -17,7 +17,7 @@ class _CreateCampaignFormControllerState extends State { final _formKey = GlobalKey(); String selectedValue = 'photo'; - double _howMuch = 5; + double _howMuch = 1000; int _howFar = 100; final titleController = TextEditingController(); String? address; @@ -133,12 +133,12 @@ class _CreateCampaignFormControllerState style: CustomTextStyle.spaceMono(context), ), Slider( - min: 1.0, - max: 10.0, - divisions: 18, + min: 1000, + max: 10000000, + divisions: 100, + label: "${_howMuch.toInt()} wei", activeColor: CustomColors.blue900(context), value: _howMuch, - label: _howMuch.toStringAsFixed(1), onChanged: (newValue) { setState(() { _howMuch = newValue; diff --git a/lib/controllers/wallet_controller.dart b/lib/controllers/wallet_controller.dart index 3757207..a30c68c 100644 --- a/lib/controllers/wallet_controller.dart +++ b/lib/controllers/wallet_controller.dart @@ -18,9 +18,7 @@ class _WalletControllerState extends State { Object? parameters; dynamic jsonInfo = {}; late Timer timer; - String balance = "LOADING...", symbol = "LOADING..."; - late double _height; - late double _width; + String balance = "LOADING...", symbol = "MCScoin"; Future _getBalance() async { String data = await WalletModel.getData(); @@ -80,12 +78,10 @@ class _WalletControllerState extends State { } Widget _formatBalance(String balance) { - if (double.tryParse(balance) != null && balance != "0") { - print("DEBUG: $balance"); - return Text( - '${balance.substring(0, 2)},${balance.substring(3)}', - style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), - ); + double? parsed = double.tryParse(balance); + if (parsed != null && balance != "0") { + parsed = parsed/1000000000000000000; + return Text(parsed.toString(),style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),); } else { return Text( balance, diff --git a/lib/models/db_capaign_model.dart b/lib/models/db_capaign_model.dart index 70771a0..1f81be6 100644 --- a/lib/models/db_capaign_model.dart +++ b/lib/models/db_capaign_model.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'package:mobile_crowd_sensing/services/geofencing_controller.dart'; import 'package:mobile_crowd_sensing/services/services_controller.dart'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; @@ -46,7 +45,6 @@ class DbCampaignModel { conflictAlgorithm: ConflictAlgorithm.replace, ); - GeofencingController.registerGeofencing(cmp.address, cmp.lat, cmp.lng, cmp.radius); if(ServicesController.statusGeofencingService) { print('\x1B[31m [GEOFENCING SERVICE] INITIALIZE AFTER INSERT IN DB\x1B[0m'); ServicesController.initializeGeofencingService(); @@ -90,10 +88,6 @@ class DbCampaignModel { where: 'address = ?', whereArgs: [address], ); - //int res = (await campaigns()).length; - GeofencingController.removeGeofenceFromId(address); - //print("DEBUG:::::: dentro al db ci sono: \n${(await campaigns()).length} campagne"); - } } diff --git a/lib/models/login_metamask_model.dart b/lib/models/login_metamask_model.dart index 137bcd0..58e2fe4 100644 --- a/lib/models/login_metamask_model.dart +++ b/lib/models/login_metamask_model.dart @@ -34,7 +34,7 @@ class LoginMetamaskModel { print('\x1B[31m [GEOFENCE SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); //await ClosedCampaignService().initializeClosedCampaignService(); // DEBUG - DbCampaignModel().insertCampaign( + await DbCampaignModel().insertCampaign( const Campaign( title: "testing campaign", lat: "44.3883014", @@ -42,7 +42,6 @@ class LoginMetamaskModel { radius: "17", address: "0x000000000000") ); - await GeofencingController.initializeFromDB(); ServicesController.initializeGeofencingService(); } diff --git a/lib/models/my_campaign_model.dart b/lib/models/my_campaign_model.dart index 7c45223..84e7700 100644 --- a/lib/models/my_campaign_model.dart +++ b/lib/models/my_campaign_model.dart @@ -2,7 +2,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter_config/flutter_config.dart'; import 'package:mobile_crowd_sensing/models/search_places_model.dart'; import 'package:mobile_crowd_sensing/models/smart_contract_model.dart'; -import 'package:web3dart/credentials.dart'; import 'session_model.dart'; class MyCampaignModel { @@ -10,10 +9,8 @@ class MyCampaignModel { static Future getMyCampaign() async { try { SessionModel sessionData = SessionModel(); - String sourcerAddress = sessionData.getAccountAddress(); SmartContractModel smartContractViewModel = SmartContractModel(contractAddress:FlutterConfig.get('MCSfactory_CONTRACT_ADDRESS'),abiName: 'MCSfactory',abiFileRoot: 'assets/abi.json', provider: sessionData.getProvider()); - EthereumAddress address = EthereumAddress.fromHex(sourcerAddress); - return await smartContractViewModel.queryCall('activeCampaigns',[address]); + return await smartContractViewModel.queryCall('getActiveCampaign',[]); } catch (error) { if (kDebugMode) { print('\x1B[31m$error\x1B[0m'); diff --git a/lib/models/session_model.dart b/lib/models/session_model.dart index 2be5c1b..5036d04 100644 --- a/lib/models/session_model.dart +++ b/lib/models/session_model.dart @@ -1,4 +1,3 @@ -import 'package:shared_preferences/shared_preferences.dart'; import 'package:walletconnect_dart/walletconnect_dart.dart'; import 'package:web3dart/web3dart.dart'; import 'package:flutter_config/flutter_config.dart'; diff --git a/lib/models/smart_contract_model.dart b/lib/models/smart_contract_model.dart index 53d4244..4e52c94 100644 --- a/lib/models/smart_contract_model.dart +++ b/lib/models/smart_contract_model.dart @@ -6,6 +6,8 @@ import 'package:walletconnect_dart/walletconnect_dart.dart'; import 'package:web3dart/src/crypto/secp256k1.dart'; import 'package:web3dart/web3dart.dart'; +import '../utils/nonce_manager.dart'; + class SmartContractModel extends CustomTransactionSender{ SmartContractModel({required this.contractAddress, required this.abiName, required this.abiFileRoot, required this.provider}); final EthereumWalletConnectProvider provider; @@ -30,6 +32,7 @@ class SmartContractModel extends CustomTransactionSender{ contract: contract, function: ethFunction, parameters: args, + nonce: NonceManager.getNonce(), value: (value != null) ? EtherAmount.inWei(value) : null ); launchUrlString(sessionData.uri, mode: LaunchMode.externalApplication); diff --git a/lib/models/wallet_model.dart b/lib/models/wallet_model.dart index 2cbb2f0..380cab0 100644 --- a/lib/models/wallet_model.dart +++ b/lib/models/wallet_model.dart @@ -12,9 +12,9 @@ class WalletModel { SessionModel sessionData = SessionModel(); late SmartContractModel smartContract = SmartContractModel( - contractAddress:FlutterConfig.get('COIN_CONTRACT'), - abiName: 'MCSCoin', - abiFileRoot: 'assets/abi_coin.json', + contractAddress:FlutterConfig.get('MCSfactory_CONTRACT_ADDRESS'), + abiName: 'MCSfactory', + abiFileRoot: 'assets/abi.json', provider: sessionData.getProvider() ); EthereumAddress address = EthereumAddress.fromHex(sessionData.getAccountAddress()); diff --git a/lib/services/geofencing_controller.dart b/lib/services/geofencing_controller.dart index 4512055..ae58fbe 100644 --- a/lib/services/geofencing_controller.dart +++ b/lib/services/geofencing_controller.dart @@ -4,9 +4,9 @@ import 'package:mobile_crowd_sensing/models/db_capaign_model.dart'; import 'Geofencing.dart'; class GeofencingController { - static final List _activeGeofencing = []; + final List _activeGeofencing = []; - static registerGeofencing(String id, String pointedLatitude, + registerGeofencing(String id, String pointedLatitude, String pointedLongitude, String radiusMeter) { _activeGeofencing.add(Geofencing( id: id, @@ -18,7 +18,7 @@ class GeofencingController { } } - static closeAllGeofencing() { + closeAllGeofencing() { for (Geofencing g in _activeGeofencing) { g.stopGeofenceService(); } @@ -29,11 +29,11 @@ class GeofencingController { } } - static getNumberOfActiveGeofence() { + getNumberOfActiveGeofence() { return _activeGeofencing.length; } - static removeGeofenceFromId(String id) { + removeGeofenceFromId(String id) { Geofencing selected = _activeGeofencing.firstWhere((item) => item.id == id); selected.stopGeofenceService(); _activeGeofencing.remove(selected); @@ -42,16 +42,16 @@ class GeofencingController { } } - static getListOfActiveGeofences(){ + getListOfActiveGeofences(){ return _activeGeofencing; } - static Future initializeFromDB() async { + Future initializeFromDB() async { DbCampaignModel db = DbCampaignModel(); List res = await db.campaigns(); for(Campaign c in res) { - GeofencingController.registerGeofencing( + registerGeofencing( c.address, c.lat, c.lng, diff --git a/lib/services/services.dart b/lib/services/services.dart index 2bfc6d0..ae7f4a5 100644 --- a/lib/services/services.dart +++ b/lib/services/services.dart @@ -1,6 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:geolocator/geolocator.dart'; import 'package:http/http.dart' as http; import 'package:mobile_crowd_sensing/services/geofencing.dart'; import 'package:mobile_crowd_sensing/services/geofencing_controller.dart'; @@ -91,7 +92,32 @@ class Services { @pragma('vm:entry-point') static void checkGeofence(Map args) async { DartPluginRegistrant.ensureInitialized(); - print('\x1B[31m [GEOFENCING SERVICE] DEBUG:gate1 KKKKK} \x1B[0m'); + //.... + + bool serviceEnabled; + LocationPermission permission; + + serviceEnabled = await Geolocator.isLocationServiceEnabled(); + if (!serviceEnabled) { + await Geolocator.openLocationSettings(); + return Future.error('Location services are disabled.'); + } + + permission = await Geolocator.checkPermission(); + if (permission == LocationPermission.denied) { + permission = await Geolocator.requestPermission(); + if (permission == LocationPermission.denied) { + return Future.error('Location permissions are denied'); + } + } + + if (permission == LocationPermission.deniedForever) { + return Future.error( + 'Location permissions are permanently denied, we cannot request permissions.'); + } + + + //.... final FlutterLocalNotificationsPlugin notification = FlutterLocalNotificationsPlugin(); @@ -100,12 +126,16 @@ class Services { .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(NotificationChannel.importantChannel); - print('\x1B[31m [GEOFENCING SERVICE] DEBUG: Geofence registrati ${GeofencingController.getListOfActiveGeofences()} \x1B[0m'); + GeofencingController controller = GeofencingController(); Timer.periodic(const Duration(seconds: 5), (timer) async { ServicesController.statusGeofencingService = true; - if (GeofencingController.getNumberOfActiveGeofence() > 0) { - for (Geofencing g in GeofencingController.getListOfActiveGeofences()) { + + controller.initializeFromDB(); + print('\x1B[31m [GEOFENCING SERVICE] DEBUG: numero di geofencing attivi ${controller.getNumberOfActiveGeofence()} \x1B[0m'); + + if (controller.getNumberOfActiveGeofence() > 0) { + for (Geofencing g in controller.getListOfActiveGeofences()) { print('\x1B[31m [GEOFENCING SERVICE] DEBUG: ${g.isStatusChanged} \x1B[0m'); if (g.isStatusChanged) { switch (g.getStatus()) { @@ -139,7 +169,8 @@ class Services { 'MY FOREGROUND SERVICE', icon: 'ic_bg_service_small', ongoing: false, - ))); + )) + ); break; } } diff --git a/lib/utils/nonce_manager.dart b/lib/utils/nonce_manager.dart new file mode 100644 index 0000000..d4576d0 --- /dev/null +++ b/lib/utils/nonce_manager.dart @@ -0,0 +1,12 @@ +class NonceManager { + static int nonce = 1; + + static int getNonce() { + try { + return nonce; + } finally { + print("assigned nonce: $nonce"); + nonce ++; + } + } +} \ No newline at end of file diff --git a/lib/views/campaign_data_light_view.dart b/lib/views/campaign_data_light_view.dart index acd05c9..b58eb2c 100644 --- a/lib/views/campaign_data_light_view.dart +++ b/lib/views/campaign_data_light_view.dart @@ -1,6 +1,5 @@ import 'dart:convert'; import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; import '../models/file_manager_model.dart'; import '../models/ipfs_client_model.dart'; @@ -38,7 +37,6 @@ class LightJoinCampaignViewState extends State { } _downloadFiles(hashToDownload) async { - //print("DEBUG ::::::::::::::::::::::::::::::::::::::: [getFileIPFSHash]: $hashToDownload"); String? res = await IpfsClientModel.downloadItemIPFS(hashToDownload, 'lights'); if (res != null) { @@ -58,9 +56,7 @@ class LightJoinCampaignViewState extends State { List? allfilesPathRes = await smartContract.queryCall('getValidFiles', []); if (allfilesPathRes != null) { - //print("CHECK this: ${allfilesPathRes[0]}"); for (dynamic element in allfilesPathRes[0]) { - //print('element: '+ element); _downloadFiles(element); } } @@ -115,7 +111,7 @@ class LightJoinCampaignViewState extends State { Center( child: Text( 'No files for this Campaign', - style: GoogleFonts.inconsolata(fontSize: 16), + style: CustomTextStyle.inconsolata(context), ), ), ])); diff --git a/lib/views/photo_join_campaign_view.dart b/lib/views/photo_join_campaign_view.dart index 2eec643..b28c8d5 100644 --- a/lib/views/photo_join_campaign_view.dart +++ b/lib/views/photo_join_campaign_view.dart @@ -43,6 +43,7 @@ class PhotoJoinCampaignViewState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ + const SizedBox(height: 20), Image.asset('assets/images/Circle-icons-camera.svg.png', height: 150, fit: BoxFit.fill), Container( @@ -69,17 +70,19 @@ class PhotoJoinCampaignViewState extends State { ), ], ), + Row(children: [ + Text( + 'Latitude: ', + style: CustomTextStyle.spaceMonoBold(context), + ), + Text( + '${campaignSelectedData['lat']}', + style: CustomTextStyle.inconsolata(context), + ), + ]), Row( children: [ - Text( - 'Latitude: ', - style: CustomTextStyle.spaceMonoBold(context), - ), - Text( - '${campaignSelectedData['lat']}', - style: CustomTextStyle.inconsolata(context), - ), - Text(' Longitude: ', + Text('Longitude: ', style: CustomTextStyle.spaceMonoBold(context)), Text( '${campaignSelectedData['lng']}', @@ -227,8 +230,8 @@ class PhotoJoinCampaignViewState extends State { style: CustomTextStyle .spaceMonoWhite(context), ))); - Navigator.pushReplacementNamed( - context, '/worker'); + Navigator.of(context).pushNamedAndRemoveUntil( + '/home', (Route route) => false); }); } else { setState(() { From f5a4d1964bad593e5facf6bab657fcbb01492f28 Mon Sep 17 00:00:00 2001 From: Giacomo Galletti Date: Mon, 30 Jan 2023 10:38:51 +0100 Subject: [PATCH 09/34] fix vaidate photo --- .../close_campaign_controller.dart | 3 +- .../validate_photo_controller.dart | 279 ++++++++++-------- lib/controllers/wallet_controller.dart | 3 + lib/models/close_campaign_model.dart | 8 +- lib/models/login_metamask_model.dart | 16 +- lib/models/session_model.dart | 10 +- lib/models/smart_contract_model.dart | 1 - lib/views/validate_photo_view.dart | 3 +- report-galletti-giacomo-bozza.pdf | Bin 624455 -> 0 bytes 9 files changed, 182 insertions(+), 141 deletions(-) delete mode 100644 report-galletti-giacomo-bozza.pdf diff --git a/lib/controllers/close_campaign_controller.dart b/lib/controllers/close_campaign_controller.dart index f29ad8c..114ef88 100644 --- a/lib/controllers/close_campaign_controller.dart +++ b/lib/controllers/close_campaign_controller.dart @@ -15,7 +15,8 @@ class CloseCampaignController extends StatelessWidget { static routing(BuildContext context,List? result) { if (result != null) { - Navigator.pushReplacementNamed(context, '/sourcer'); + Navigator.of(context).pushNamedAndRemoveUntil( + '/home', (Route route) => false); } else { Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => const DialogView(message: "An error occurred. Campaign still open"))); } diff --git a/lib/controllers/validate_photo_controller.dart b/lib/controllers/validate_photo_controller.dart index cc8241a..6b3151a 100644 --- a/lib/controllers/validate_photo_controller.dart +++ b/lib/controllers/validate_photo_controller.dart @@ -4,7 +4,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import '../../utils/join_campaign_factory.dart'; import '../../utils/styles.dart'; -import '../models/file_manager_model.dart'; import '../models/validate_model.dart'; class ValidatePhotoController extends JoinCampaignFactory { @@ -23,8 +22,8 @@ class ValidatePhotoState extends State { bool downloadGate = true; late List pictures = []; - _prepareData() async { - if(mounted) { + Future? _prepareData() async { + if (mounted) { pictures.clear(); Stream? res = await ValidateModel.downloadPhotosFiles( campaignSelectedData['ipfsHash']); @@ -37,7 +36,6 @@ class ValidatePhotoState extends State { print("PREPARING DATA: ${pictures.length}"); } } - setState(() {}); } } @@ -49,127 +47,160 @@ class ValidatePhotoState extends State { parameters = ModalRoute.of(context)!.settings.arguments; campaignSelectedData = jsonDecode(jsonEncode(parameters)); - if (campaignSelectedData['ipfsHash'] != null && downloadGate) { - _prepareData(); - } + + return FutureBuilder( + future: _prepareData(), + builder: (BuildContext context, AsyncSnapshot snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.none: + return const Center(child: Text('Sorry something goes wrong...')); + case ConnectionState.waiting: + return Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + Center( + child: CircularProgressIndicator(), + ) + ]); + default: + return _buildPage(); + } + }); + } + + Widget _buildPage() { return (pictures.isNotEmpty) - ? ListView(shrinkWrap: false, children: [ - Column( - children: [ - Text( - 'ipfs hash: ', - style: CustomTextStyle.spaceMonoBold(context), - ), - Text( - '${campaignSelectedData['ipfsHash']}', - style: CustomTextStyle.inconsolata(context), - ), - ], - ), - Padding( - padding: EdgeInsets.only( - top: DeviceDimension.deviceHeight(context) * 0.15, - left: DeviceDimension.deviceWidth(context) * 0.09, - ), - child: Wrap( - alignment: WrapAlignment.spaceAround, // set your alignment - children: [ - Row(children: [ - Text('Number of photos: ', - style: CustomTextStyle.merriweatherBold(context)), - Text('${pictures.length}', - style: CustomTextStyle.inconsolata(context)) - ]), - Center( - child: SizedBox( - height: 200, // card height - child: PageView.builder( - itemCount: pictures.length, - controller: PageController(viewportFraction: 0.7), - onPageChanged: (int index) => - setState(() => index = index), - itemBuilder: (_, i) { - return Transform.scale( - scale: 1, - child: Card( - elevation: 6, - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(20)), - child: Image.file(pictures[i], - fit: BoxFit.cover)), - ); - }), + ? Padding( + padding: const EdgeInsets.all(10), + child: ListView(shrinkWrap: false, children: [ + Column( + children: [ + const SizedBox( + height: 20, + ), + Text( + 'ipfs hash: ', + style: CustomTextStyle.spaceMonoBold(context), + ), + FittedBox( + fit: BoxFit.fitWidth, + child: Text( + '${campaignSelectedData['ipfsHash']}', + style: CustomTextStyle.inconsolata(context), + ), + ) + ], + ), + Padding( + padding: EdgeInsets.only( + top: DeviceDimension.deviceHeight(context) * 0.15, + left: DeviceDimension.deviceWidth(context) * 0.09, + ), + child: Wrap( + alignment: + WrapAlignment.spaceAround, // set your alignment + children: [ + Row(children: [ + Text('Number of photos: ', + style: CustomTextStyle.merriweatherBold(context)), + Text('${pictures.length}', + style: CustomTextStyle.inconsolata(context)) + ]), + Center( + child: SizedBox( + height: 200, // card height + child: PageView.builder( + itemCount: pictures.length, + controller: + PageController(viewportFraction: 0.7), + onPageChanged: (int index) => + setState(() => index = index), + itemBuilder: (_, i) { + return Transform.scale( + scale: 1, + child: Card( + elevation: 6, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(20)), + child: Image.file(pictures[i], + fit: BoxFit.cover)), + ); + }), + ), ), - ), - FloatingActionButton( - heroTag: "verified", - onPressed: () async { - bool res = await ValidateModel.approveOrNot( - campaignSelectedData['contractAddress'], - campaignSelectedData['ipfsHash'], - true); - if (res) { - setState(() { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar( - content: Text( - 'Data verified', - style: - CustomTextStyle.spaceMonoWhite(context), - ))); - Navigator.of(context) - .pushNamedAndRemoveUntil('/home', (Route route) => false); - }); - } else { - setState(() { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar( - content: Text( - 'An Error occurred', - style: - CustomTextStyle.spaceMonoWhite(context), - ))); - }); - } - }, - backgroundColor: CustomColors.green600(context), - child: const Icon(Icons.check)), - FloatingActionButton( - heroTag: "notVerified", - onPressed: () async { - bool res = await ValidateModel.approveOrNot( - campaignSelectedData['contractAddress'], - campaignSelectedData['ipfsHash'], - false); - if (res) { - setState(() { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar( - content: Text( - 'Data verified', - style: - CustomTextStyle.spaceMonoWhite(context), - ))); - Navigator.of(context) - .pushNamedAndRemoveUntil('/home', (Route route) => false); - }); - } else { - setState(() { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar( - content: Text( - 'An Error occurred', - style: - CustomTextStyle.spaceMonoWhite(context), - ))); - }); - } - }, - backgroundColor: CustomColors.red600(context), - child: const Icon(Icons.close)), - ])) - ]) - : Center(child: Text('Data not available on ipfs.',style: CustomTextStyle.spaceMono(context))); + FloatingActionButton( + heroTag: "verified", + onPressed: () async { + bool res = await ValidateModel.approveOrNot( + campaignSelectedData['contractAddress'], + campaignSelectedData['ipfsHash'], + true); + if (res) { + setState(() { + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + 'Data verified', + style: + CustomTextStyle.spaceMonoWhite(context), + ))); + Navigator.of(context).pushNamedAndRemoveUntil( + '/home', (Route route) => false); + }); + } else { + setState(() { + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + 'An Error occurred', + style: + CustomTextStyle.spaceMonoWhite(context), + ))); + }); + } + }, + backgroundColor: CustomColors.green600(context), + child: const Icon(Icons.check)), + FloatingActionButton( + heroTag: "notVerified", + onPressed: () async { + bool res = await ValidateModel.approveOrNot( + campaignSelectedData['contractAddress'], + campaignSelectedData['ipfsHash'], + false); + if (res) { + setState(() { + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + 'Data verified', + style: + CustomTextStyle.spaceMonoWhite(context), + ))); + Navigator.of(context).pushNamedAndRemoveUntil( + '/home', (Route route) => false); + }); + } else { + setState(() { + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + 'An Error occurred', + style: + CustomTextStyle.spaceMonoWhite(context), + ))); + }); + } + }, + backgroundColor: CustomColors.red600(context), + child: const Icon(Icons.close)), + ])) + ])) + : Center( + child: Text('Data not available on ipfs.', + style: CustomTextStyle.spaceMono(context))); } } diff --git a/lib/controllers/wallet_controller.dart b/lib/controllers/wallet_controller.dart index a30c68c..b70a972 100644 --- a/lib/controllers/wallet_controller.dart +++ b/lib/controllers/wallet_controller.dart @@ -78,9 +78,12 @@ class _WalletControllerState extends State { } Widget _formatBalance(String balance) { + print("DEBUG:::: wallet balance: $balance"); double? parsed = double.tryParse(balance); + SessionModel session = SessionModel(); if (parsed != null && balance != "0") { parsed = parsed/1000000000000000000; + print("DEBUG:::: wallet balance: ${parsed.toStringAsFixed(20)}"); return Text(parsed.toString(),style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),); } else { return Text( diff --git a/lib/models/close_campaign_model.dart b/lib/models/close_campaign_model.dart index 0e2a623..72c905d 100644 --- a/lib/models/close_campaign_model.dart +++ b/lib/models/close_campaign_model.dart @@ -1,5 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_config/flutter_config.dart'; import 'package:mobile_crowd_sensing/controllers/close_campaign_controller.dart'; import 'smart_contract_model.dart'; import 'session_model.dart'; @@ -10,7 +11,12 @@ class CloseCampaignModel { static Future closeMyCampaign(BuildContext context,String address) async { try { SessionModel sessionData = SessionModel(); - SmartContractModel smartContractViewModel = SmartContractModel(contractAddress: address,abiName: 'Campaing',abiFileRoot: 'assets/abi_campaign.json', provider: sessionData.getProvider()); + SmartContractModel smartContractViewModel = SmartContractModel( + contractAddress: FlutterConfig.get('MCSfactory_CONTRACT_ADDRESS'), + abiName: 'MCSfactory', + abiFileRoot: 'assets/abi.json', + provider: sessionData.getProvider() + ); await smartContractViewModel.queryTransaction('closeCampaign',[],null).then((value) => { CloseCampaignController.routing(context,value) }); diff --git a/lib/models/login_metamask_model.dart b/lib/models/login_metamask_model.dart index 58e2fe4..27e1a7e 100644 --- a/lib/models/login_metamask_model.dart +++ b/lib/models/login_metamask_model.dart @@ -34,14 +34,14 @@ class LoginMetamaskModel { print('\x1B[31m [GEOFENCE SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); //await ClosedCampaignService().initializeClosedCampaignService(); // DEBUG - await DbCampaignModel().insertCampaign( - const Campaign( - title: "testing campaign", - lat: "44.3883014", - lng: "11.3467744", - radius: "17", - address: "0x000000000000") - ); + // await DbCampaignModel().insertCampaign( + // const Campaign( + // title: "testing campaign", + // lat: "44.3883014", + // lng: "11.3467744", + // radius: "17", + // address: "0x000000000000") + // ); ServicesController.initializeGeofencingService(); } diff --git a/lib/models/session_model.dart b/lib/models/session_model.dart index 5036d04..3d5927e 100644 --- a/lib/models/session_model.dart +++ b/lib/models/session_model.dart @@ -54,7 +54,7 @@ class SessionModel { }); connector.on('session_update', (payload) async => { print('\x1B[31m[checkConnection]\x1B[0m:session_update'), - updateConnection(connector) + print("\n DEBUG DEL PAYLOAD: ${payload.toString()}"), }); connector.on('disconnect', (payload) => { print('\x1B[31m[checkConnection]\x1B[0m:disconnect'), @@ -63,11 +63,11 @@ class SessionModel { } Future updateConnection(WalletConnect c) async { - WalletConnectSession? st = await c.sessionStorage!.getSession(); - SessionStatus current = SessionStatus(chainId: st!.chainId, accounts: st.accounts); - connector.updateSession(current); + // WalletConnectSession? st = await c.sessionStorage!.getSession(); + // SessionStatus current = SessionStatus(chainId: st!.chainId, accounts: st.accounts); + // connector.updateSession(current); } - + void reconnect(){ print('\x1B[31m[Connection reconnected]\x1B[0m:connect'); connector.reconnect(); diff --git a/lib/models/smart_contract_model.dart b/lib/models/smart_contract_model.dart index 4e52c94..399de52 100644 --- a/lib/models/smart_contract_model.dart +++ b/lib/models/smart_contract_model.dart @@ -32,7 +32,6 @@ class SmartContractModel extends CustomTransactionSender{ contract: contract, function: ethFunction, parameters: args, - nonce: NonceManager.getNonce(), value: (value != null) ? EtherAmount.inWei(value) : null ); launchUrlString(sessionData.uri, mode: LaunchMode.externalApplication); diff --git a/lib/views/validate_photo_view.dart b/lib/views/validate_photo_view.dart index 9a74eb0..997f04f 100644 --- a/lib/views/validate_photo_view.dart +++ b/lib/views/validate_photo_view.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'package:flutter/material.dart'; +import 'package:mobile_crowd_sensing/utils/styles.dart'; import 'package:mobile_crowd_sensing/utils/verifier_campaign_data_factory.dart'; import '../controllers/validate_photo_controller.dart'; @@ -26,7 +27,7 @@ class _VerifierCampaignDataLightViewState extends State { return Scaffold( appBar: AppBar( - backgroundColor: Colors.red[900], + backgroundColor: CustomColors.blue900(context), title: Text(jsonParameters["name"]), centerTitle: true, ), diff --git a/report-galletti-giacomo-bozza.pdf b/report-galletti-giacomo-bozza.pdf deleted file mode 100644 index dd89b13ac05eb7f0383e7b74d1bde7c4e62744c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 624455 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

wvLZ5t?qK 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 QuyCN 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 From 8efc116c530e0efbef1521cc15441f711c2f003f Mon Sep 17 00:00:00 2001 From: Giacomo Date: Mon, 30 Jan 2023 19:18:33 +0100 Subject: [PATCH 10/34] bug fix chiusura campagne --- contracts/MCSfactory.sol | 2 +- .../campaign_data_light_controller.dart | 84 ++++++++++++++++++ .../close_campaign_controller.dart | 32 ++++--- .../create_campaign_form_controller.dart | 2 +- .../sourcer_campaign_controller.dart | 5 +- .../sourcer_closed_campaign_controller.dart | 4 +- .../sourcer_past_campaigns_controller.dart | 63 ++++++------- .../verifier_campaign_data_controller.dart | 3 +- lib/main.dart | 2 - lib/models/campaign_data_light_model.dart | 39 ++++++++ lib/models/close_campaign_model.dart | 44 +++++----- lib/models/my_campaign_model.dart | 3 +- lib/models/session_model.dart | 3 +- lib/models/sourcer_past_campaigns_model.dart | 33 +++---- lib/views/campaign_data_light_view.dart | 88 +------------------ lib/views/close_campaign_view.dart | 6 +- 16 files changed, 222 insertions(+), 191 deletions(-) create mode 100644 lib/controllers/campaign_data_light_controller.dart create mode 100644 lib/models/campaign_data_light_model.dart diff --git a/contracts/MCSfactory.sol b/contracts/MCSfactory.sol index c1b18e9..6d7d7bd 100644 --- a/contracts/MCSfactory.sol +++ b/contracts/MCSfactory.sol @@ -11,7 +11,7 @@ contract CampaignFactory is MCScoin { FactoryManager factoryManager; constructor (uint256 reward,address factoryManagerAddress) ERC20("Mobile Crowd Sensing Coin", "MCSCoin") { - _mint(msg.sender, 10000000 * (10 ** uint256(decimals()))); + _mint(msg.sender, 100 * (10 ** uint256(decimals()))); blockReward = reward * (10 ** uint(decimals())); factoryManager = FactoryManager(factoryManagerAddress); } diff --git a/lib/controllers/campaign_data_light_controller.dart b/lib/controllers/campaign_data_light_controller.dart new file mode 100644 index 0000000..cbc1c89 --- /dev/null +++ b/lib/controllers/campaign_data_light_controller.dart @@ -0,0 +1,84 @@ +import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:syncfusion_flutter_charts/charts.dart'; +import '../models/campaign_data_light_model.dart'; +import '../models/session_model.dart'; +import '../utils/styles.dart'; + +class CampaignDataLightController extends StatefulWidget { + const CampaignDataLightController({Key? key}) : super(key: key); + + @override + State createState() => _CampaignDataLightControllerState(); +} + +class _CampaignDataLightControllerState extends State { + dynamic campaignSelectedData = {}; + Object? parameters; + SessionModel sessionData = SessionModel(); + + @override + Widget build(BuildContext context) { + parameters = ModalRoute.of(context)!.settings.arguments; + campaignSelectedData = jsonDecode(jsonEncode(parameters)); + return Container( + padding: const EdgeInsets.fromLTRB(10, 30, 10, 0), + width: double.maxFinite, + child: Column(children: [ + Text( + 'Account', + style: CustomTextStyle.merriweatherBold(context), + ), + Text( + '${sessionData.getAccountAddress()}', + style: CustomTextStyle.inconsolata(context), + ), + FutureBuilder( + future: CampaignDataLightModel.preparePage(campaignSelectedData['contractAddress']), + builder: (BuildContext context, + AsyncSnapshot> snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.none: + return const Center( + child: Text('Sorry something goes wrong...')); + case ConnectionState.waiting: + return const Expanded( + flex: 1, + child: Center( + child: CircularProgressIndicator()), + ); + default: + return (snapshot.data!.isNotEmpty) + ? _closedCampaignLightWidget(context, snapshot) + : Expanded(child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Center( + child: Text( + "No data for this campaign.", + style: CustomTextStyle.spaceMono( + context))) + ])); + } + }) + ])); + } + + Widget _closedCampaignLightWidget( + BuildContext context, AsyncSnapshot> snapshot) { + return Center( + child: SfCartesianChart( + primaryXAxis: CategoryAxis(), + series: >[ + LineSeries( + dataSource: snapshot.data!, + xValueMapper: (LightData data, _) => + DateFormat('dd/MM/yyyy, HH:mm').format(data.timeStamp), + yValueMapper: (LightData data, _) => data.value) + ] + ) + ); + } +} diff --git a/lib/controllers/close_campaign_controller.dart b/lib/controllers/close_campaign_controller.dart index 114ef88..5395e19 100644 --- a/lib/controllers/close_campaign_controller.dart +++ b/lib/controllers/close_campaign_controller.dart @@ -3,23 +3,35 @@ import 'package:mobile_crowd_sensing/utils/spalsh_screens.dart'; import '../views/dialog_view.dart'; import '../models/close_campaign_model.dart'; -class CloseCampaignController extends StatelessWidget { - final String address; - const CloseCampaignController({super.key, required this.address}); +class CloseCampaignController extends StatefulWidget { + const CloseCampaignController({super.key}); + @override + State createState() => + _CloseCampaignControllerState(); +} + +class _CloseCampaignControllerState extends State { @override Widget build(BuildContext context) { - CloseCampaignModel.closeMyCampaign(context,address); + _getData(context); return CustomSplashScreen.fadingCubeBlueBg(context); } - static routing(BuildContext context,List? result) { - if (result != null) { - Navigator.of(context).pushNamedAndRemoveUntil( - '/home', (Route route) => false); + Future _getData(BuildContext context) async { + String result = await CloseCampaignModel.closeMyCampaign(context); + + if (result.contains("Campaign Closed")) { + if (!mounted) return; + Navigator.of(context) + .pushNamedAndRemoveUntil('/home', (Route route) => false); } else { - Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => const DialogView(message: "An error occurred. Campaign still open"))); + if (!mounted) return; + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (context) => DialogView( + message: "Error on result:\n${result.toString()}"))); } } - } diff --git a/lib/controllers/create_campaign_form_controller.dart b/lib/controllers/create_campaign_form_controller.dart index 892d580..0806ba8 100644 --- a/lib/controllers/create_campaign_form_controller.dart +++ b/lib/controllers/create_campaign_form_controller.dart @@ -175,7 +175,7 @@ class _CreateCampaignFormControllerState ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text( 'Processing Data', - style: CustomTextStyle.spaceMono(context), + style: CustomTextStyle.spaceMonoWhite(context), ))); String res = await CreateCampaignModel.createCampaign( context, diff --git a/lib/controllers/sourcer_campaign_controller.dart b/lib/controllers/sourcer_campaign_controller.dart index 943e9f1..a5cc350 100644 --- a/lib/controllers/sourcer_campaign_controller.dart +++ b/lib/controllers/sourcer_campaign_controller.dart @@ -98,7 +98,7 @@ class _SourcerCampaignControllerState extends State { (lat.isEmpty) ? GlobalText.loadingText(context) : Text( - "Latitude: ${(int.parse(lat) / 10000000).round()}", + "Latitude: ${(int.parse(lat) / 10000000)}", style: CustomTextStyle.spaceMono(context), ), ]), @@ -106,7 +106,7 @@ class _SourcerCampaignControllerState extends State { (lng.isEmpty) ? GlobalText.loadingText(context) : Text( - "Longitude: ${(int.parse(lng) / 10000000).round()}", + "Longitude: ${(int.parse(lng) / 10000000)}", style: CustomTextStyle.spaceMono(context)), ]), @@ -145,6 +145,7 @@ class _SourcerCampaignControllerState extends State { "Sourcing Status:\nuploaded $fileCount files\nchecked $fileChecked of $fileCount\nwhit the contribution of $workersCount workers", style: CustomTextStyle.spaceMono(context), )), + const SizedBox(height: 20,), FloatingActionButton( backgroundColor: CustomColors.red600(context), child: Icon(Icons.close,color: CustomColors.customWhite(context),), diff --git a/lib/controllers/sourcer_closed_campaign_controller.dart b/lib/controllers/sourcer_closed_campaign_controller.dart index 41c9615..0ce8a9a 100644 --- a/lib/controllers/sourcer_closed_campaign_controller.dart +++ b/lib/controllers/sourcer_closed_campaign_controller.dart @@ -96,12 +96,12 @@ class _SourcerClosedCampaignControllerState extends State[ - (longitude.length != widget.contractAddress!.length) ? GlobalText.loadingText(context) : Text("Longitude: ${(int.parse(longitude[index].toString())/10000000).round()}", + (longitude.length != widget.contractAddress!.length) ? GlobalText.loadingText(context) : Text("Longitude: ${(int.parse(longitude[index].toString())/10000000)}", style: CustomTextStyle.spaceMono(context), ), ]), diff --git a/lib/controllers/sourcer_past_campaigns_controller.dart b/lib/controllers/sourcer_past_campaigns_controller.dart index 80f2af2..2d430b8 100644 --- a/lib/controllers/sourcer_past_campaigns_controller.dart +++ b/lib/controllers/sourcer_past_campaigns_controller.dart @@ -5,15 +5,15 @@ import '../views/dialog_view.dart'; import '../views/sourcer_closed_campaign_view.dart'; class SourcerPastCampaignsController extends StatefulWidget { - const SourcerPastCampaignsController({super.key}); @override // ignore: library_private_types_in_public_api - _SourcerPastCampaignsControllerState createState() => _SourcerPastCampaignsControllerState(); + _SourcerPastCampaignsControllerState createState() => + _SourcerPastCampaignsControllerState(); } -class _SourcerPastCampaignsControllerState extends State { - +class _SourcerPastCampaignsControllerState + extends State { @override void initState() { super.initState(); @@ -26,36 +26,29 @@ class _SourcerPastCampaignsControllerState extends State { - _goTo(value) - }); - } - - _goTo(result){ - if (result.isNotEmpty && result != null) { - setState(() { - Navigator.pushReplacement(context,MaterialPageRoute(builder: (context) => SourcerClosedCampaignView(contractAddress: result,))); - }); - } else { - setState(() { - Navigator.pushReplacement( - context, - MaterialPageRoute(builder: (BuildContext context) => const DialogView(message: 'No Campaigns Available'))); - }); - } + await SourcerPastCampaignsModel.getMyClosedCampaign(context) + .then((result) => { + if (result != null) + { + setState(() { + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (context) => SourcerClosedCampaignView( + contractAddress: result, + ))); + }) + } + else + { + setState(() { + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (BuildContext context) => const DialogView( + message: 'No Campaigns Available'))); + }) + } + }); } } - - - - - - - - - - - - - - diff --git a/lib/controllers/verifier_campaign_data_controller.dart b/lib/controllers/verifier_campaign_data_controller.dart index 76a0e8d..eebacfe 100644 --- a/lib/controllers/verifier_campaign_data_controller.dart +++ b/lib/controllers/verifier_campaign_data_controller.dart @@ -64,7 +64,8 @@ class _VerifierCampaignDataPhotoController return Container( padding: const EdgeInsets.fromLTRB(10, 30, 10, 0), width: double.maxFinite, - child: Column(children: [ + child: + Column(children: [ Column(children: [ Text("contractAddress:", style: CustomTextStyle.spaceMonoBold(context)), diff --git a/lib/main.dart b/lib/main.dart index 479416f..1759fff 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,7 +3,6 @@ import 'dart:io'; import 'package:flip_card/flip_card.dart'; import 'package:flutter/material.dart'; import 'package:flutter_config/flutter_config.dart'; -import 'package:mobile_crowd_sensing/models/session_model.dart'; import 'package:mobile_crowd_sensing/utils/internet_connection.dart'; import 'package:mobile_crowd_sensing/utils/styles.dart'; import 'package:mobile_crowd_sensing/utils/verifier_campaign_data_factory.dart'; @@ -23,7 +22,6 @@ import 'package:mobile_crowd_sensing/views/search_places_view.dart'; import 'package:mobile_crowd_sensing/views/validate_light_view.dart'; import 'package:mobile_crowd_sensing/views/validate_photo_view.dart'; import 'package:mobile_crowd_sensing/views/wallet_view.dart'; -import 'package:walletconnect_dart/walletconnect_dart.dart'; import 'dart:async'; import 'package:connectivity/connectivity.dart'; diff --git a/lib/models/campaign_data_light_model.dart b/lib/models/campaign_data_light_model.dart new file mode 100644 index 0000000..1dc8e09 --- /dev/null +++ b/lib/models/campaign_data_light_model.dart @@ -0,0 +1,39 @@ +import 'package:mobile_crowd_sensing/models/session_model.dart'; +import 'package:mobile_crowd_sensing/models/smart_contract_model.dart'; + +import 'ipfs_client_model.dart'; + +class CampaignDataLightModel { + + static Future> preparePage(String campaignAddress) async { + List contents = []; + late SmartContractModel smartContract = SmartContractModel( + contractAddress: campaignAddress, + abiName: 'Campaign', + abiFileRoot: 'assets/abi_campaign.json', + provider: SessionModel().getProvider()); + + List? allfilesPathRes = + await smartContract.queryCall('getValidFiles', []); + if (allfilesPathRes != null) { + for (dynamic element in allfilesPathRes[0]) { + String? res = await IpfsClientModel.downloadItemIPFS(element, 'lights'); + if (res != null) { + List value = res.split('/'); + contents.add(LightData( + DateTime.fromMillisecondsSinceEpoch(int.parse(value[0])), + double.parse(value[1]))); + } + } + } + + return contents; + } + +} + +class LightData { + LightData(this.timeStamp, this.value); + final DateTime timeStamp; + final double value; +} \ No newline at end of file diff --git a/lib/models/close_campaign_model.dart b/lib/models/close_campaign_model.dart index 72c905d..14cb6ce 100644 --- a/lib/models/close_campaign_model.dart +++ b/lib/models/close_campaign_model.dart @@ -7,30 +7,26 @@ import 'session_model.dart'; import '../views/dialog_view.dart'; class CloseCampaignModel { + static Future closeMyCampaign( + BuildContext context) async { + SessionModel sessionData = SessionModel(); + SmartContractModel smartContractViewModel = SmartContractModel( + contractAddress: FlutterConfig.get('MCSfactory_CONTRACT_ADDRESS'), + abiName: 'MCSfactory', + abiFileRoot: 'assets/abi.json', + provider: sessionData.getProvider()); + dynamic res = await smartContractViewModel.queryTransaction( + 'closeCampaign', [], null); - static Future closeMyCampaign(BuildContext context,String address) async { - try { - SessionModel sessionData = SessionModel(); - SmartContractModel smartContractViewModel = SmartContractModel( - contractAddress: FlutterConfig.get('MCSfactory_CONTRACT_ADDRESS'), - abiName: 'MCSfactory', - abiFileRoot: 'assets/abi.json', - provider: sessionData.getProvider() - ); - await smartContractViewModel.queryTransaction('closeCampaign',[],null).then((value) => { - CloseCampaignController.routing(context,value) - }); - } catch (error) { - if (kDebugMode) { - print('\x1B[31m$error\x1B[0m'); - } - Future.delayed(Duration.zero, () { - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (BuildContext context) => - DialogView(message: error.toString()))); - }); + if (res.toString() != "null" && + res.toString() != "0x0000000000000000000000000000000000000000" && + !res.startsWith('JSON-RPC error')) { + return 'Campaign Closed'; + }else if (res.startsWith('JSON-RPC error -32000:')){ + return res.split('JSON-RPC error -32000:').last.toString(); + } + else { + return 'An error Occurred.'; } } -} \ No newline at end of file +} diff --git a/lib/models/my_campaign_model.dart b/lib/models/my_campaign_model.dart index 84e7700..fa90462 100644 --- a/lib/models/my_campaign_model.dart +++ b/lib/models/my_campaign_model.dart @@ -10,7 +10,8 @@ class MyCampaignModel { try { SessionModel sessionData = SessionModel(); SmartContractModel smartContractViewModel = SmartContractModel(contractAddress:FlutterConfig.get('MCSfactory_CONTRACT_ADDRESS'),abiName: 'MCSfactory',abiFileRoot: 'assets/abi.json', provider: sessionData.getProvider()); - return await smartContractViewModel.queryCall('getActiveCampaign',[]); + List? res = await smartContractViewModel.queryCall('getActiveCampaign',[]); + return res; } catch (error) { if (kDebugMode) { print('\x1B[31m$error\x1B[0m'); diff --git a/lib/models/session_model.dart b/lib/models/session_model.dart index 3d5927e..79fcd8d 100644 --- a/lib/models/session_model.dart +++ b/lib/models/session_model.dart @@ -52,8 +52,9 @@ class SessionModel { print('\x1B[31m[checkConnection]\x1B[0m:connect'), reconnect() }); - connector.on('session_update', (payload) async => { + connector.on('session_update', (WCSessionUpdateResponse payload) async => { print('\x1B[31m[checkConnection]\x1B[0m:session_update'), + connector.updateSession(SessionStatus(chainId: payload.chainId, accounts: payload.accounts)), print("\n DEBUG DEL PAYLOAD: ${payload.toString()}"), }); connector.on('disconnect', (payload) => { diff --git a/lib/models/sourcer_past_campaigns_model.dart b/lib/models/sourcer_past_campaigns_model.dart index e7644f8..d6ed960 100644 --- a/lib/models/sourcer_past_campaigns_model.dart +++ b/lib/models/sourcer_past_campaigns_model.dart @@ -7,26 +7,20 @@ import 'session_model.dart'; import '../views/dialog_view.dart'; class SourcerPastCampaignsModel { - - static Future?> getMyClosedCampaign(BuildContext context) async { + static Future getMyClosedCampaign(BuildContext context) async { try { SessionModel sessionData = SessionModel(); - SmartContractModel smartContractViewModel = SmartContractModel(contractAddress:FlutterConfig.get('MCSfactory_CONTRACT_ADDRESS'),abiName: 'MCSfactory',abiFileRoot: 'assets/abi.json', provider: sessionData.getProvider()); - EthereumAddress address = EthereumAddress.fromHex(sessionData.getAccountAddress()); - List? result = []; - int index = 0; - List? query = []; - - do { - query = await smartContractViewModel.queryCall('closedCampaigns', [address, BigInt.from(index)]); - - if (query.toString() != "null") { - result.add(query![0].toString()); - } - index++; - } while (query.toString() != "null"); - - return result; + SmartContractModel smartContractViewModel = SmartContractModel( + contractAddress: FlutterConfig.get('MCSfactory_CONTRACT_ADDRESS'), + abiName: 'MCSfactory', + abiFileRoot: 'assets/abi.json', + provider: sessionData.getProvider()); + List? query = + await smartContractViewModel.queryCall('getClosedCampaigns', []); + if (query.toString() != "null") { + return query![0]; + } + return null; } catch (error) { if (kDebugMode) { print('\x1B[31m$error\x1B[0m'); @@ -39,5 +33,4 @@ class SourcerPastCampaignsModel { } return null; } - -} \ No newline at end of file +} diff --git a/lib/views/campaign_data_light_view.dart b/lib/views/campaign_data_light_view.dart index b58eb2c..1806488 100644 --- a/lib/views/campaign_data_light_view.dart +++ b/lib/views/campaign_data_light_view.dart @@ -1,12 +1,8 @@ import 'dart:convert'; import 'package:flutter/material.dart'; -import 'package:mobile_crowd_sensing/models/session_model.dart'; +import '../controllers/campaign_data_light_controller.dart'; import '../models/file_manager_model.dart'; -import '../models/ipfs_client_model.dart'; -import '../models/smart_contract_model.dart'; import '../utils/worker_campaign_data_factory.dart'; -import 'package:syncfusion_flutter_charts/charts.dart'; -import 'package:intl/intl.dart'; import '../utils/styles.dart'; class CampaignDataLightView extends WorkerDataCampaignFactory { @@ -21,52 +17,16 @@ class CampaignDataLightView extends WorkerDataCampaignFactory { class LightJoinCampaignViewState extends State { dynamic campaignSelectedData = {}; Object? parameters; - SessionModel sessionData = SessionModel(); - late SmartContractModel smartContract = SmartContractModel( - contractAddress: campaignSelectedData['contractAddress'], - abiName: 'Campaign', - abiFileRoot: 'assets/abi_campaign.json', - provider: sessionData.getProvider()); - late List hashes = []; - List contents = []; - @override initState() { super.initState(); FileManagerModel.clearTemporaryDirectory(); } - _downloadFiles(hashToDownload) async { - String? res = - await IpfsClientModel.downloadItemIPFS(hashToDownload, 'lights'); - if (res != null) { - List value = res.split('/'); - if (mounted) { - setState(() { - contents.add(LightData( - DateTime.fromMillisecondsSinceEpoch(int.parse(value[0])), - double.parse(value[1]))); - hashes.add(hashToDownload); - }); - } - } - } - - _preparePage() async { - List? allfilesPathRes = - await smartContract.queryCall('getValidFiles', []); - if (allfilesPathRes != null) { - for (dynamic element in allfilesPathRes[0]) { - _downloadFiles(element); - } - } - } - @override Widget build(BuildContext context) { parameters = ModalRoute.of(context)!.settings.arguments; campaignSelectedData = jsonDecode(jsonEncode(parameters)); - _preparePage(); return Scaffold( resizeToAvoidBottomInset: false, @@ -75,51 +35,7 @@ class LightJoinCampaignViewState extends State { centerTitle: true, title: Text(campaignSelectedData['name']), ), - body: (contents.isNotEmpty) - ? SingleChildScrollView( - child: Container( - padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Account', - style: CustomTextStyle.merriweatherBold(context), - ), - Text( - '${sessionData.getAccountAddress()}', - style: CustomTextStyle.inconsolata(context), - ), - Container( - padding: - const EdgeInsets.fromLTRB(10, 30, 10, 10), - width: double.maxFinite, - child: Center( - child: SfCartesianChart( - primaryXAxis: CategoryAxis(), - series: >[ - LineSeries( - dataSource: contents, - xValueMapper: (LightData sales, _) => - DateFormat('dd/MM/yyyy, HH:mm') - .format(sales.timeStamp), - yValueMapper: (LightData sales, _) => - sales.value) - ]))) - ]))) - : Column(mainAxisAlignment: MainAxisAlignment.center, children: [ - Center( - child: Text( - 'No files for this Campaign', - style: CustomTextStyle.inconsolata(context), - ), - ), - ])); + body: const CampaignDataLightController()); } } -class LightData { - LightData(this.timeStamp, this.value); - final DateTime timeStamp; - final double value; -} diff --git a/lib/views/close_campaign_view.dart b/lib/views/close_campaign_view.dart index d32fd39..4e9c504 100644 --- a/lib/views/close_campaign_view.dart +++ b/lib/views/close_campaign_view.dart @@ -11,14 +11,10 @@ class CloseCampaignView extends StatefulWidget { } class _CloseCampaignViewState extends State { - Object? parameters; - dynamic jsonParameters = {}; @override Widget build(BuildContext context) { - parameters = ModalRoute.of(context)!.settings.arguments; - jsonParameters = jsonDecode(jsonEncode(parameters)); - return CloseCampaignController(address: jsonParameters['address'],); + return const CloseCampaignController(); } From 3e5e02db6e4da76f63cef42e38470b8493a2decb Mon Sep 17 00:00:00 2001 From: Giacomo Date: Tue, 31 Jan 2023 13:04:37 +0100 Subject: [PATCH 11/34] fix photo sourcer visualization at close campaign --- assets/abi_campaign.json | 7 -- contracts/Campaign.sol | 9 +- contracts/FactoryManager.sol | 24 ++--- contracts/MCSfactory.sol | 2 +- .../campaign_data_photo_controller.dart | 94 +++++++++++++++++++ lib/controllers/campaign_list_controller.dart | 13 ++- .../close_campaign_controller.dart | 5 +- lib/models/close_campaign_model.dart | 11 +-- lib/views/campaign_data_photo_view.dart | 54 +---------- lib/views/close_campaign_view.dart | 6 +- 10 files changed, 131 insertions(+), 94 deletions(-) create mode 100644 lib/controllers/campaign_data_photo_controller.dart diff --git a/assets/abi_campaign.json b/assets/abi_campaign.json index 6c7119f..8ddf780 100644 --- a/assets/abi_campaign.json +++ b/assets/abi_campaign.json @@ -130,13 +130,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "closeCampaign", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "closeCampaignAndPay", diff --git a/contracts/Campaign.sol b/contracts/Campaign.sol index 91f27d1..396311d 100644 --- a/contracts/Campaign.sol +++ b/contracts/Campaign.sol @@ -99,14 +99,7 @@ contract Campaign is Ownable, Initializable { return factoryContractAddress.balanceOf(address(this)); } - // tenuta per debug - function closeCampaign() external { - require(msg.sender == addressCrowdSourcer,'you are not the owner'); - require(msg.sender != address(0), "invalid address provided"); - isClosed = factoryContractAddress.closeCampaign(); - } - - function closeCampaignAndPay() external payable { + function closeCampaignAndPay() public payable { require(msg.sender == addressCrowdSourcer,'you are not the owner'); isClosed = factoryContractAddress.closeCampaign(); diff --git a/contracts/FactoryManager.sol b/contracts/FactoryManager.sol index 6d78b41..9bc1dfc 100644 --- a/contracts/FactoryManager.sol +++ b/contracts/FactoryManager.sol @@ -35,22 +35,18 @@ contract FactoryManager { } function _closeCampaign() external returns (bool){ - if(address(activeCampaigns[tx.origin])!=address(0)) { - require(tx.origin == activeCampaigns[tx.origin].addressCrowdSourcer(),'you are not the campaign owner'); - closedCampaigns[tx.origin].push(activeCampaigns[tx.origin]); - delete activeCampaigns[tx.origin]; - for (uint i = 0; i < addressCrowdSourcerActiveCampaigns.length; i++){ - if(addressCrowdSourcerActiveCampaigns[i] == tx.origin) { - addressCrowdSourcerClosedCampaigns.push(tx.origin); - addressCrowdSourcerActiveCampaigns[i] = addressCrowdSourcerActiveCampaigns[addressCrowdSourcerActiveCampaigns.length-1]; - addressCrowdSourcerActiveCampaigns.pop(); - break; - } + require(tx.origin == activeCampaigns[tx.origin].addressCrowdSourcer(),'you are not the campaign owner'); + closedCampaigns[tx.origin].push(activeCampaigns[tx.origin]); + delete activeCampaigns[tx.origin]; + for (uint i = 0; i < addressCrowdSourcerActiveCampaigns.length; i++){ + if(addressCrowdSourcerActiveCampaigns[i] == tx.origin) { + addressCrowdSourcerClosedCampaigns.push(tx.origin); + addressCrowdSourcerActiveCampaigns[i] = addressCrowdSourcerActiveCampaigns[addressCrowdSourcerActiveCampaigns.length-1]; + addressCrowdSourcerActiveCampaigns.pop(); + return true; } - return true; - } else { - return false; } + return false; } function _checkIfSourcerHasActiveCampaign(address sourcer) external view returns(bool) { diff --git a/contracts/MCSfactory.sol b/contracts/MCSfactory.sol index 6d7d7bd..13bb3f0 100644 --- a/contracts/MCSfactory.sol +++ b/contracts/MCSfactory.sol @@ -25,7 +25,7 @@ contract CampaignFactory is MCScoin { return to; } - function closeCampaign() external returns (bool){ + function closeCampaign() public returns (bool){ return factoryManager._closeCampaign(); } diff --git a/lib/controllers/campaign_data_photo_controller.dart b/lib/controllers/campaign_data_photo_controller.dart new file mode 100644 index 0000000..b218f0c --- /dev/null +++ b/lib/controllers/campaign_data_photo_controller.dart @@ -0,0 +1,94 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:mobile_crowd_sensing/models/file_manager_model.dart'; +import '../models/validate_model.dart'; +import '../models/verifier_campaign_data_model.dart'; +import '../utils/styles.dart'; + +class CampaignDataPhotoController extends StatefulWidget { + const CampaignDataPhotoController({Key? key}) : super(key: key); + + @override + State createState() => + _CampaignDataPhotoControllerState(); +} + +class _CampaignDataPhotoControllerState + extends State { + Object? parameters; + dynamic jsonParameters = {}; + + Future> _getData(String contractAddress) async { + late List pictures = []; + await FileManagerModel.clearTemporaryDirectory(); + List? res = + await VerifierCampaignDataModel.getDataFileInfo(contractAddress); + if (res != null) { + for (dynamic i in res) { + Stream? res = await ValidateModel.downloadPhotosFiles(i[4].toString()); + if (res != null) { + res.forEach((element) { + pictures.add(File(element.path)); + }); + } + } + } + return pictures; + } + + @override + Widget build(BuildContext context) { + parameters = ModalRoute.of(context)!.settings.arguments; + jsonParameters = jsonDecode(jsonEncode(parameters)); + String contractAddress = jsonParameters["contractAddress"]; + + return FutureBuilder( + future: _getData(contractAddress), + builder: (BuildContext context, AsyncSnapshot> snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.none: + return const Center(child: Text('Sorry something goes wrong...')); + case ConnectionState.waiting: + return Container( + padding: const EdgeInsets.fromLTRB(10, 30, 10, 10), + width: double.maxFinite, + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + CircularProgressIndicator(), + ])); + default: + return _galleryWidget(context, snapshot); + } + }); + } + + Widget _galleryWidget( + BuildContext context, AsyncSnapshot> snapshot) { + + return (snapshot.data!.isEmpty + ? Center( + child: Text('No images for this campaign.', + style: CustomTextStyle.spaceMono(context))) + : ListView.builder( + scrollDirection: Axis.vertical, + itemCount: snapshot.data!.length, + itemBuilder: (context, i) => Padding( + padding: const EdgeInsets.all(20), + child: SizedBox( + width: DeviceDimension.deviceWidth(context) * 0.9, + child: + Card( + elevation: 6, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20)), + child: Image.file(snapshot.data![i], + fit: BoxFit.cover)) + ) + )) + ); + } +} diff --git a/lib/controllers/campaign_list_controller.dart b/lib/controllers/campaign_list_controller.dart index 3eb19cd..2e6af80 100644 --- a/lib/controllers/campaign_list_controller.dart +++ b/lib/controllers/campaign_list_controller.dart @@ -63,8 +63,8 @@ class _CampaignListControllerState String selectedValue = 'All Campaigns'; DbCampaignModel db = DbCampaignModel(); - _buildPage(BuildContext context, AsyncSnapshot snapshot) { - return (snapshot.data.length > 0) + Widget _buildPage(BuildContext context, AsyncSnapshot snapshot) { + return (snapshot.data[0].length > 0) ? Container( padding: const EdgeInsets.fromLTRB(10, 30, 10, 10), width: double.maxFinite, @@ -141,11 +141,16 @@ class _CampaignListControllerState }), ) ])) - : Center( + : Container( + padding: const EdgeInsets.fromLTRB(10, 30, 10, 10), + width: double.maxFinite, + child: Column(children: [ + Expanded( + child:Center( child: Text( "No Campaign active at the moment.", style: CustomTextStyle.spaceMono(context), - )); + )))])); } Widget _cardWidget( diff --git a/lib/controllers/close_campaign_controller.dart b/lib/controllers/close_campaign_controller.dart index 5395e19..e40f1f5 100644 --- a/lib/controllers/close_campaign_controller.dart +++ b/lib/controllers/close_campaign_controller.dart @@ -4,7 +4,8 @@ import '../views/dialog_view.dart'; import '../models/close_campaign_model.dart'; class CloseCampaignController extends StatefulWidget { - const CloseCampaignController({super.key}); + final String address; + const CloseCampaignController({super.key,required this.address}); @override State createState() => @@ -19,7 +20,7 @@ class _CloseCampaignControllerState extends State { } Future _getData(BuildContext context) async { - String result = await CloseCampaignModel.closeMyCampaign(context); + String result = await CloseCampaignModel.closeMyCampaign(widget.address); if (result.contains("Campaign Closed")) { if (!mounted) return; diff --git a/lib/models/close_campaign_model.dart b/lib/models/close_campaign_model.dart index 14cb6ce..951f31c 100644 --- a/lib/models/close_campaign_model.dart +++ b/lib/models/close_campaign_model.dart @@ -7,16 +7,15 @@ import 'session_model.dart'; import '../views/dialog_view.dart'; class CloseCampaignModel { - static Future closeMyCampaign( - BuildContext context) async { + static Future closeMyCampaign(String address) async { SessionModel sessionData = SessionModel(); SmartContractModel smartContractViewModel = SmartContractModel( - contractAddress: FlutterConfig.get('MCSfactory_CONTRACT_ADDRESS'), - abiName: 'MCSfactory', - abiFileRoot: 'assets/abi.json', + contractAddress: address, + abiName: 'Campaign', + abiFileRoot: 'assets/abi_campaign.json', provider: sessionData.getProvider()); dynamic res = await smartContractViewModel.queryTransaction( - 'closeCampaign', [], null); + 'closeCampaignAndPay', [], null); if (res.toString() != "null" && res.toString() != "0x0000000000000000000000000000000000000000" && diff --git a/lib/views/campaign_data_photo_view.dart b/lib/views/campaign_data_photo_view.dart index aef824d..42dd9be 100644 --- a/lib/views/campaign_data_photo_view.dart +++ b/lib/views/campaign_data_photo_view.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:mobile_crowd_sensing/controllers/campaign_data_photo_controller.dart'; import 'package:mobile_crowd_sensing/utils/styles.dart'; import '../../utils/worker_campaign_data_factory.dart'; import '../models/validate_model.dart'; @@ -18,47 +19,14 @@ class CampaignDataPhotoView extends WorkerDataCampaignFactory { class LightJoinCampaignViewState extends State { Object? parameters; dynamic jsonParameters = {}; - late String contractAddress; - List hashes = []; - bool downloadGate = true; - - _prepareData(String hash) async { - Stream? res = - await ValidateModel.downloadPhotosFiles(hash); - if (res != null) { - res.forEach((element) { - pictures.add(File(element.path)); - }); - if (kDebugMode) { - print("PREPARING DATA: ${pictures.length}"); - } - setState(() {}); - } - } - - late List pictures = []; @override Widget build(BuildContext context) { parameters = ModalRoute.of(context)!.settings.arguments; jsonParameters = jsonDecode(jsonEncode(parameters)); - contractAddress = jsonParameters["contractAddress"]; print("campaign_data_photo_view"); - if (downloadGate) { - VerifierCampaignDataModel.getDataFileInfo(contractAddress) - .then((info) => { - if (mounted && info != null) - { - setState(() { - for (dynamic i in info) { - _prepareData(i[3].toString()); - } - downloadGate = !downloadGate; - }) - } - }); - } + return Scaffold( appBar: AppBar( @@ -66,22 +34,6 @@ class LightJoinCampaignViewState extends State { title: Text(jsonParameters["name"]), centerTitle: true, ), - body: SizedBox ( - height: DeviceDimension.deviceHeight(context) * 0.6, - child: ListView.builder( - scrollDirection: Axis.vertical, - itemCount: pictures.length, - itemBuilder: (ctx, i) => (pictures.isEmpty - ? const Text('Add some images') - : Padding( - padding: const EdgeInsets.all(20), - child: SizedBox( - width: DeviceDimension.deviceWidth(context) * 0.9, - child: Card( - elevation: 6, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20)), - child: Image.file(pictures[i], - fit: BoxFit.cover)))))))); + body: const CampaignDataPhotoController()); } } diff --git a/lib/views/close_campaign_view.dart b/lib/views/close_campaign_view.dart index 4e9c504..d32fd39 100644 --- a/lib/views/close_campaign_view.dart +++ b/lib/views/close_campaign_view.dart @@ -11,10 +11,14 @@ class CloseCampaignView extends StatefulWidget { } class _CloseCampaignViewState extends State { + Object? parameters; + dynamic jsonParameters = {}; @override Widget build(BuildContext context) { - return const CloseCampaignController(); + parameters = ModalRoute.of(context)!.settings.arguments; + jsonParameters = jsonDecode(jsonEncode(parameters)); + return CloseCampaignController(address: jsonParameters['address'],); } From 6267c8ba8bc68a53173fce678a49f13031b7d241 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Thu, 2 Feb 2023 18:11:21 +0100 Subject: [PATCH 12/34] claim campaign reward fixed contracts + widgets and bug fix of session update --- assets/abi.json | 110 +++ assets/abi_campaign.json | 7 + contracts/Campaign.sol | 35 +- contracts/MCSfactory.sol | 30 + lib/controllers/campaign_list_controller.dart | 25 +- .../claim_campaign_controller.dart | 187 +++++ .../validate_light_controller.dart | 13 +- .../verifier_campaign_data_controller.dart | 24 +- lib/controllers/wallet_controller.dart | 110 +-- lib/models/session_model.dart | 6 - lib/models/smart_contract_model.dart | 16 +- lib/services/closed_campaign_service.dart | 2 +- lib/services/geofencing.dart | 2 +- lib/views/wallet_view.dart | 10 +- pubspec.lock | 651 ++++++++++++------ 15 files changed, 901 insertions(+), 327 deletions(-) create mode 100644 lib/controllers/claim_campaign_controller.dart diff --git a/assets/abi.json b/assets/abi.json index 4236499..28b5832 100644 --- a/assets/abi.json +++ b/assets/abi.json @@ -182,6 +182,40 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "campaignsToClaim", + "outputs": [ + { + "internalType": "address", + "name": "campaignAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "role", + "type": "string" + }, + { + "internalType": "uint256", + "name": "toClaim", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "closeCampaign", @@ -309,6 +343,36 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "getCampaignsToClaim", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "campaignAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "role", + "type": "string" + }, + { + "internalType": "uint256", + "name": "toClaim", + "type": "uint256" + } + ], + "internalType": "struct CampaignFactory.CampaignToClaim[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "getClosedCampaigns", @@ -372,6 +436,52 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "campaignAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "role", + "type": "string" + }, + { + "internalType": "uint256", + "name": "toClaim", + "type": "uint256" + } + ], + "name": "putCampaignToClaim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "campaignAddress", + "type": "address" + } + ], + "name": "removeCampaignToClaim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "renounceOwnership", diff --git a/assets/abi_campaign.json b/assets/abi_campaign.json index 8ddf780..3430caf 100644 --- a/assets/abi_campaign.json +++ b/assets/abi_campaign.json @@ -438,5 +438,12 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, + { + "inputs": [], + "name": "withdrawCredits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } ] \ No newline at end of file diff --git a/contracts/Campaign.sol b/contracts/Campaign.sol index 396311d..628f3a9 100644 --- a/contracts/Campaign.sol +++ b/contracts/Campaign.sol @@ -34,6 +34,21 @@ contract Campaign is Ownable, Initializable { int256 lng; } + mapping(address => uint) credits; + + function allowForPull(address receiver, uint amount) private { + credits[receiver] += amount; + } + + function withdrawCredits() public { + uint amount = credits[msg.sender]; + require(amount != 0); + require(factoryContractAddress.balanceOf(address(this)) >= amount); + credits[msg.sender] = 0; + factoryContractAddress.transfer(msg.sender,amount); + factoryContractAddress.removeCampaignToClaim(msg.sender,address(this)); + } + function getAllFilesInfo() public view returns(File[] memory){ File[] memory out = new File[](allfilesPath.length); for(uint i = 0; i CampaignToClaim[]) public campaignsToClaim; // address worker/verifier -> campaigns + + struct CampaignToClaim { + address campaignAddress; + string role; + uint256 toClaim; + } + + function getCampaignsToClaim() public view returns (CampaignToClaim[] memory) { + CampaignToClaim[] memory outPut = new CampaignToClaim[](campaignsToClaim[msg.sender].length); + for (uint256 i = 0; i < campaignsToClaim[msg.sender].length; i++) { + outPut[i] = campaignsToClaim[msg.sender][i]; + } + return outPut; + } + + + function putCampaignToClaim(address sender, address campaignAddress, string memory role, uint256 toClaim) external { + campaignsToClaim[sender].push(CampaignToClaim(campaignAddress,role,toClaim)); + } + + function removeCampaignToClaim(address sender, address campaignAddress) external { + for (uint i = 0; i createState() => _ClaimCampaignControllerState(); +} + +class _ClaimCampaignControllerState extends State { + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _getClaimData(), + builder: (BuildContext context, + AsyncSnapshot> snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.none: + return const Center( + child: Text('Sorry something goes wrong...')); + case ConnectionState.waiting: + return Container( + padding: const EdgeInsets.fromLTRB(10, 30, 10, 10), + width: double.maxFinite, + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + CircularProgressIndicator(), + ])); + default: + return _claimCardWidget(context, snapshot); + } + }); + } + + Future> _getClaimData() async { + SmartContractModel smartContractViewModel = SmartContractModel( + contractAddress: FlutterConfig.get('MCSfactory_CONTRACT_ADDRESS'), + abiName: 'MCSfactory', + abiFileRoot: 'assets/abi.json', + provider: SessionModel().getProvider()); + List? res = + await smartContractViewModel.queryCall('getCampaignsToClaim', []); + print("DEBUG::::::: res : ${res.toString()}"); + if (res != null) { + print("DEBUGG---- " + res[0].toString()); + return res[0]; + } + return []; + } + + Widget _claimCardWidget( + BuildContext context, AsyncSnapshot> snapshot) { + return Expanded(child: + ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: (snapshot.data != null) ? snapshot.data!.length : 0, + itemBuilder: (context, index) { + List current = snapshot.data![index]; + + String address = current[0].toString(); + String role = current[1].toString(); + String reward = current[2].toString(); + return GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: const Text('Want to Claim?'), + content: Text('you will recive:\n$reward MCSCoin'), + actions: [ + TextButton( + child: const Text('No'), + onPressed: () { + Navigator.of(ctx).pop(false); + }), + TextButton( + child: const Text('Yes'), + onPressed: () async { + SmartContractModel smartContractViewModel = SmartContractModel( + contractAddress: address, + abiName: 'Campaign', + abiFileRoot: 'assets/abi_campaign.json', + provider: SessionModel().getProvider()); + dynamic res = await smartContractViewModel.queryTransaction("withdrawCredits", [], null); + print("DEBUG::::::: res : ${res.toString()}"); + if (res.toString() != "null" && + res.toString() != "0x0000000000000000000000000000000000000000" && + !res.startsWith('JSON-RPC error')) { + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + 'Claimed!', + style: CustomTextStyle + .spaceMonoWhite(context), + ))); + }else if (res.startsWith('JSON-RPC error -32000:')){ + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + res.split('JSON-RPC error -32000:').last.toString(), + style: CustomTextStyle + .spaceMonoWhite(context), + ))); + } + else { + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + "An error occurred", + style: CustomTextStyle + .spaceMonoWhite(context), + ))); + } + setState(() { + Navigator.of(ctx).pop(false); + }); + }), + ], + ), + ); + }, + child: Card( + shadowColor: CustomColors.blue600(context), + color: CustomColors.customWhite(context), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20.0), + ), + child: Padding( + padding: const EdgeInsets.all(20), + child: Stack(children: [ + Align( + alignment: Alignment.topLeft, + child: Column( + children: [ + FittedBox( + fit: BoxFit.fitWidth, + child: Column(children: [ + Text( + "Campaign Address: ", + style: CustomTextStyle.spaceMonoBold(context), + ), + Text( + address, + style: CustomTextStyle.spaceMono(context), + ) + ])), + FittedBox( + fit: BoxFit.fitWidth, + child: Row(children: [ + Text( + "Role: ", + style: CustomTextStyle.spaceMonoBold(context), + ), + Text( + role, + style: CustomTextStyle.spaceMono(context), + ) + ])), + FittedBox( + fit: BoxFit.fitWidth, + child: Row(children: [ + Text( + "Reward: ", + style: CustomTextStyle.spaceMonoBold(context), + ), + Text( + reward, + style: CustomTextStyle.spaceMono(context), + ) + ])), + ], + ), + ) + ])), + ), + ); + })); + } +} diff --git a/lib/controllers/validate_light_controller.dart b/lib/controllers/validate_light_controller.dart index c61b48f..dfbbd0c 100644 --- a/lib/controllers/validate_light_controller.dart +++ b/lib/controllers/validate_light_controller.dart @@ -43,7 +43,8 @@ class ValidateLightControllerState extends State { if (hash != null && !downloadGate) { _prepareData(); } - return ListView( + return + ListView( shrinkWrap: false, children: [ Column( @@ -128,7 +129,7 @@ class ValidateLightControllerState extends State { context)) ]), Row(children: [ - Text('Average Relevation: ', + Text('Average Data Collected: ', style: CustomTextStyle.merriweatherBold( context)), Text('$relevation ', @@ -148,6 +149,7 @@ class ValidateLightControllerState extends State { onPressed: () async { bool res = await ValidateModel.approveOrNot(campaignSelectedData['contractAddress'], hash, true); if(res) { + if(!mounted) {return;} ScaffoldMessenger.of(context) .showSnackBar(SnackBar( content: Text( @@ -157,6 +159,7 @@ class ValidateLightControllerState extends State { Navigator.of(context) .pushNamedAndRemoveUntil('/home', (Route route) => false); } else { + if(!mounted) {return;} ScaffoldMessenger.of(context) .showSnackBar(SnackBar( content: Text( @@ -173,6 +176,7 @@ class ValidateLightControllerState extends State { onPressed: () async { bool res = await ValidateModel.approveOrNot(campaignSelectedData['contractAddress'], hash, false); if(res) { + if(!mounted) {return;} ScaffoldMessenger.of(context) .showSnackBar(SnackBar( content: Text( @@ -182,6 +186,7 @@ class ValidateLightControllerState extends State { Navigator.of(context) .pushNamedAndRemoveUntil('/home', (Route route) => false); } else { + if(!mounted) {return;} ScaffoldMessenger.of(context) .showSnackBar(SnackBar( content: Text( @@ -196,8 +201,8 @@ class ValidateLightControllerState extends State { ])); } }) - : const Text( - "check data for get a relevation and compare the result") + : const Center( child:Text( + "check data for get a relevation and compare the result")) ]); } } diff --git a/lib/controllers/verifier_campaign_data_controller.dart b/lib/controllers/verifier_campaign_data_controller.dart index eebacfe..2b23e9a 100644 --- a/lib/controllers/verifier_campaign_data_controller.dart +++ b/lib/controllers/verifier_campaign_data_controller.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'package:flutter/material.dart'; +import 'package:mobile_crowd_sensing/models/session_model.dart'; import 'package:mobile_crowd_sensing/utils/styles.dart'; import '../models/verifier_campaign_data_model.dart'; @@ -148,13 +149,22 @@ class _VerifierCampaignDataPhotoController if (status == 'false') { return GestureDetector( onTap: () { - Navigator.pushNamed(context, widget.goTo, - arguments: { - "name": name, - "ipfsHash": ipfsHash, - "uploader": uploader, - "contractAddress": contractAddress - }); + if(SessionModel().getAccountAddress().toLowerCase() != uploader.toLowerCase()) { + Navigator.pushNamed(context, widget.goTo, + arguments: { + "name": name, + "ipfsHash": ipfsHash, + "uploader": uploader, + "contractAddress": contractAddress + }); + } else { + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + "You can't verify your own Uploads", + style: CustomTextStyle.spaceMonoWhite(context), + ))); + } }, child: Card( shadowColor: CustomColors.blue600(context), diff --git a/lib/controllers/wallet_controller.dart b/lib/controllers/wallet_controller.dart index b70a972..fce0f6c 100644 --- a/lib/controllers/wallet_controller.dart +++ b/lib/controllers/wallet_controller.dart @@ -1,7 +1,9 @@ import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; +import 'package:flutter_config/flutter_config.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; +import '../models/smart_contract_model.dart'; import '../models/wallet_model.dart'; import '../utils/styles.dart'; import 'package:flip_card/flip_card.dart'; @@ -45,28 +47,29 @@ class _WalletControllerState extends State { @override Widget build(BuildContext context) { - return WillPopScope( child: Center( child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [ - Padding( - padding: const EdgeInsets.all(20), - child: Column( + Column( children: [ Text( "You are logged with the Account:", style: CustomTextStyle.spaceMonoBold(context), ), - FittedBox( + Container( + padding: const EdgeInsets.fromLTRB(10, 5, 10, 30), + width: double.maxFinite, + child:FittedBox( fit: BoxFit.fitWidth, child: Text( session.getAccountAddress(), style: CustomTextStyle.spaceMono(context), - )), + ))), ], - )), - buildCoinWidget(balance, symbol) + ), + _buildCoinWidget(balance, symbol), + ])), onWillPop: () async { timer.cancel(); @@ -75,65 +78,66 @@ class _WalletControllerState extends State { return true; }); } -} -Widget _formatBalance(String balance) { - print("DEBUG:::: wallet balance: $balance"); - double? parsed = double.tryParse(balance); - SessionModel session = SessionModel(); - if (parsed != null && balance != "0") { - parsed = parsed/1000000000000000000; - print("DEBUG:::: wallet balance: ${parsed.toStringAsFixed(20)}"); - return Text(parsed.toString(),style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),); - } else { - return Text( - balance, - style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), - ); + Widget _formatBalance(String balance) { + double? parsed = double.tryParse(balance); + if (parsed != null && balance != "0") { + parsed = parsed / 1000000000000000000; + return Text( + parsed.toString(), + style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ); + } else { + return Text( + balance, + style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ); + } } -} -Widget buildCoinWidget(String balance, String symbol) { - - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - symbol, - style: const TextStyle(fontSize: 25), - ), - SizedBox( - width: 300, - height: 300, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Column( - children: [ - FlipCard( + Widget _buildCoinWidget(String balance, String symbol) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + symbol, + style: const TextStyle(fontSize: 25), + ), + SizedBox( + width: 300, + height: 200, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Column( + children: [ + FlipCard( direction: FlipDirection.VERTICAL, // default front: Stack( alignment: Alignment.center, children: [ - Image.asset('assets/images/coin_back.png', width: 150, height: 150), + Image.asset('assets/images/coin_back.png', + width: 150, height: 150), ], ), back: Stack( alignment: Alignment.center, children: [ - Image.asset('assets/images/coin.png', width: 150, height: 150), + Image.asset('assets/images/coin.png', + width: 150, height: 150), ], ), ), - ], - ), - ], + ], + ), + ], + ), ), - ), - _formatBalance(balance) - ], - ), - ); + _formatBalance(balance) + ], + ), + ); + } } diff --git a/lib/models/session_model.dart b/lib/models/session_model.dart index 79fcd8d..a2e3aaa 100644 --- a/lib/models/session_model.dart +++ b/lib/models/session_model.dart @@ -63,12 +63,6 @@ class SessionModel { }); } - Future updateConnection(WalletConnect c) async { - // WalletConnectSession? st = await c.sessionStorage!.getSession(); - // SessionStatus current = SessionStatus(chainId: st!.chainId, accounts: st.accounts); - // connector.updateSession(current); - } - void reconnect(){ print('\x1B[31m[Connection reconnected]\x1B[0m:connect'); connector.reconnect(); diff --git a/lib/models/smart_contract_model.dart b/lib/models/smart_contract_model.dart index 399de52..f6ab85f 100644 --- a/lib/models/smart_contract_model.dart +++ b/lib/models/smart_contract_model.dart @@ -15,7 +15,6 @@ class SmartContractModel extends CustomTransactionSender{ final String contractAddress; final String abiName; final String abiFileRoot; - SessionModel sessionData = SessionModel(); Future loadContract(String contractAddress) async { String abi = await rootBundle.loadString(abiFileRoot); @@ -26,15 +25,20 @@ class SmartContractModel extends CustomTransactionSender{ Future queryTransaction(String functionName, List args, BigInt? value) async { try { + //SessionModel().checkConnection(); + int nonce = await SessionModel().ethClient.getTransactionCount(EthereumAddress.fromHex(SessionModel().getAccountAddress())); final contract = await loadContract(contractAddress); final ethFunction = contract.function(functionName); - final transaction = Transaction.callContract( + Transaction transaction = Transaction.callContract( contract: contract, function: ethFunction, parameters: args, + nonce: nonce, value: (value != null) ? EtherAmount.inWei(value) : null ); - launchUrlString(sessionData.uri, mode: LaunchMode.externalApplication); + print('\x1B[31m nonce: $nonce gasPrice: ${transaction.gasPrice} maxGas: ${transaction.maxGas} \x1B[0m'); + + launchUrlString(SessionModel().uri, mode: LaunchMode.externalApplication); final txBytes = await sendTransaction(transaction); return txBytes; } catch (e) { @@ -49,7 +53,7 @@ class SmartContractModel extends CustomTransactionSender{ Future sendTransaction(Transaction transaction) async { try { final hash = await provider.sendTransaction( - from: sessionData.getAccountAddress(), + from: SessionModel().getAccountAddress(), to: transaction.to?.hex, data: transaction.data, gas: transaction.maxGas, @@ -70,8 +74,8 @@ class SmartContractModel extends CustomTransactionSender{ try { final contract = await loadContract(contractAddress); final ethFunction = contract.function(functionName); - final result = await sessionData.ethClient.call( - sender: EthereumAddress.fromHex(sessionData.getAccountAddress()), + final result = await SessionModel().ethClient.call( + sender: EthereumAddress.fromHex(SessionModel().getAccountAddress()), contract: contract, function: ethFunction, params: args); diff --git a/lib/services/closed_campaign_service.dart b/lib/services/closed_campaign_service.dart index 4935da6..0a88053 100644 --- a/lib/services/closed_campaign_service.dart +++ b/lib/services/closed_campaign_service.dart @@ -111,7 +111,7 @@ class ClosedCampaignService { g.stopGeofenceService(); if (accountAddress == null) { - throw NullThrownError(); + throw Error(); } String address = c.address; String title = c.title; diff --git a/lib/services/geofencing.dart b/lib/services/geofencing.dart index 627b7a9..987204f 100644 --- a/lib/services/geofencing.dart +++ b/lib/services/geofencing.dart @@ -43,7 +43,7 @@ class Geofencing { try { if(value!.isEmpty) { - throw NullThrownError(); + throw Error(); } doubledValue = double.parse(value.isEmpty ? "0" : value); diff --git a/lib/views/wallet_view.dart b/lib/views/wallet_view.dart index ba7d773..6344e79 100644 --- a/lib/views/wallet_view.dart +++ b/lib/views/wallet_view.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:mobile_crowd_sensing/utils/styles.dart'; +import '../controllers/claim_campaign_controller.dart'; import '../controllers/wallet_controller.dart'; class WalletView extends StatelessWidget { @@ -14,11 +15,10 @@ class WalletView extends StatelessWidget { centerTitle: true, backgroundColor: CustomColors.blue900(context), ), - body: Column( - children: const [ - WalletController() - ] - ) + body: Column( children: const [ + WalletController(), + ClaimCampaignController() + ]) ); } } diff --git a/pubspec.lock b/pubspec.lock index 0599a5f..69dc779 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,350 +5,408 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - url: "https://pub.dartlang.org" + sha256: "0c80aeab9bc807ab10022cd3b2f4cf2ecdf231949dc1ddd9442406a003f19201" + url: "https://pub.dev" source: hosted - version: "50.0.0" + version: "52.0.0" analyzer: dependency: transitive description: name: analyzer - url: "https://pub.dartlang.org" + sha256: cd8ee83568a77f3ae6b913a36093a1c9b1264e7cb7f834d9ddd2311dade9c1f4 + url: "https://pub.dev" source: hosted - version: "5.2.0" + version: "5.4.0" archive: dependency: "direct main" description: name: archive - url: "https://pub.dartlang.org" + sha256: d6347d54a2d8028e0437e3c099f66fdb8ae02c4720c1e7534c9f24c10351f85d + url: "https://pub.dev" source: hosted - version: "3.3.5" + version: "3.3.6" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: "139d809800a412ebb26a3892da228b2d0ba36f0ef5d9a82166e5e52ec8d61611" + url: "https://pub.dev" source: hosted version: "2.3.2" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + url: "https://pub.dev" source: hosted - version: "2.9.0" + version: "2.10.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" build: dependency: transitive description: name: build - url: "https://pub.dartlang.org" + sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" + url: "https://pub.dev" source: hosted version: "2.3.1" build_config: dependency: transitive description: name: build_config - url: "https://pub.dartlang.org" + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" source: hosted version: "1.1.1" build_daemon: dependency: transitive description: name: build_daemon - url: "https://pub.dartlang.org" + sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" + url: "https://pub.dev" source: hosted version: "3.1.0" build_resolvers: dependency: transitive description: name: build_resolvers - url: "https://pub.dartlang.org" + sha256: "7c35a3a7868626257d8aee47b51c26b9dba11eaddf3431117ed2744951416aab" + url: "https://pub.dev" source: hosted version: "2.1.0" build_runner: dependency: "direct main" description: name: build_runner - url: "https://pub.dartlang.org" + sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + url: "https://pub.dev" source: hosted version: "2.3.3" build_runner_core: dependency: transitive description: name: build_runner_core - url: "https://pub.dartlang.org" + sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" + url: "https://pub.dev" source: hosted version: "7.2.7" built_collection: dependency: transitive description: name: built_collection - url: "https://pub.dartlang.org" + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" source: hosted version: "5.1.1" built_value: dependency: transitive description: name: built_value - url: "https://pub.dartlang.org" + sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725" + url: "https://pub.dev" source: hosted version: "8.4.3" cached_network_image: dependency: transitive description: name: cached_network_image - url: "https://pub.dartlang.org" + sha256: fd3d0dc1d451f9a252b32d95d3f0c3c487bc41a75eba2e6097cb0b9c71491b15 + url: "https://pub.dev" source: hosted version: "3.2.3" cached_network_image_platform_interface: dependency: transitive description: name: cached_network_image_platform_interface - url: "https://pub.dartlang.org" + sha256: bb2b8403b4ccdc60ef5f25c70dead1f3d32d24b9d6117cfc087f496b178594a7 + url: "https://pub.dev" source: hosted version: "2.0.0" cached_network_image_web: dependency: transitive description: name: cached_network_image_web - url: "https://pub.dartlang.org" + sha256: b8eb814ebfcb4dea049680f8c1ffb2df399e4d03bf7a352c775e26fa06e02fa0 + url: "https://pub.dev" source: hosted version: "1.0.2" camera: dependency: "direct main" description: name: camera - url: "https://pub.dartlang.org" + sha256: e7ac55af24a890d20276821eb3c95857074d03b7de6f9892b99a205ee30bd179 + url: "https://pub.dev" source: hosted - version: "0.10.2+1" + version: "0.10.3" camera_android: dependency: transitive description: name: camera_android - url: "https://pub.dartlang.org" + sha256: "4cef01e8e78fe27c809a429bf74352ab94ab76b0c980e3ec708f1414614e3d9f" + url: "https://pub.dev" source: hosted - version: "0.10.2+3" + version: "0.10.3" camera_avfoundation: dependency: transitive description: name: camera_avfoundation - url: "https://pub.dartlang.org" + sha256: "6a68c20593d4cd58974d555f74a48b244f9db28cc9156de57781122d11b8754b" + url: "https://pub.dev" source: hosted - version: "0.9.10+2" + version: "0.9.11" camera_platform_interface: dependency: transitive description: name: camera_platform_interface - url: "https://pub.dartlang.org" + sha256: "0eedd642d905ca24f1c483fe9ea0d0e7287b86a402845c28d24df28cc7b0ee6e" + url: "https://pub.dev" source: hosted version: "2.3.4" camera_web: dependency: transitive description: name: camera_web - url: "https://pub.dartlang.org" + sha256: "496de93c5d462738ce991dbfe91fb19026f115ed36406700a20a380fb0018299" + url: "https://pub.dev" source: hosted version: "0.3.1+1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + url: "https://pub.dev" source: hosted version: "1.2.1" checked_yaml: dependency: transitive description: name: checked_yaml - url: "https://pub.dartlang.org" + sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" + url: "https://pub.dev" source: hosted version: "2.0.2" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted version: "1.1.1" code_builder: dependency: transitive description: name: code_builder - url: "https://pub.dartlang.org" + sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" + url: "https://pub.dev" source: hosted version: "4.4.0" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" connectivity: dependency: "direct main" description: name: connectivity - url: "https://pub.dartlang.org" + sha256: a8e91263cf3e25fb5cc95e19dfde4999e32a648ac3b9e8a558a28165731678f8 + url: "https://pub.dev" source: hosted version: "3.0.6" connectivity_for_web: dependency: transitive description: name: connectivity_for_web - url: "https://pub.dartlang.org" + sha256: "01a390c1d5adc2ed1fa1f52d120c07fe9fd01166a93f965a832fd6cfc0ea6482" + url: "https://pub.dev" source: hosted version: "0.4.0+1" connectivity_macos: dependency: transitive description: name: connectivity_macos - url: "https://pub.dartlang.org" + sha256: "51ae08d5162eca9669b9d8951ed83ce19c5355a81149f94e4dee2740beb93628" + url: "https://pub.dev" source: hosted version: "0.2.1+2" connectivity_platform_interface: dependency: transitive description: name: connectivity_platform_interface - url: "https://pub.dartlang.org" + sha256: "2d82e942df9d49f29a24bb07fb5ce085d4a53e47818c62364d2b6deb9e0d7a8e" + url: "https://pub.dev" source: hosted version: "2.0.1" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" source: hosted version: "3.1.1" cross_file: dependency: transitive description: name: cross_file - url: "https://pub.dartlang.org" + sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9" + url: "https://pub.dev" source: hosted - version: "0.3.3+2" + version: "0.3.3+4" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" source: hosted version: "3.0.2" cryptography: dependency: transitive description: name: cryptography - url: "https://pub.dartlang.org" + sha256: e0e37f79665cd5c86e8897f9abe1accfe813c0cc5299dab22256e22fddc1fef8 + url: "https://pub.dev" source: hosted version: "2.0.5" csslib: dependency: transitive description: name: csslib - url: "https://pub.dartlang.org" + sha256: b36c7f7e24c0bdf1bf9a3da461c837d1de64b9f8beb190c9011d8c72a3dfd745 + url: "https://pub.dev" source: hosted version: "0.17.2" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - url: "https://pub.dartlang.org" + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" source: hosted version: "1.0.5" dart_style: dependency: transitive description: name: dart_style - url: "https://pub.dartlang.org" + sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" + url: "https://pub.dev" source: hosted version: "2.2.4" dbus: dependency: transitive description: name: dbus - url: "https://pub.dartlang.org" + sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263" + url: "https://pub.dev" source: hosted version: "0.7.8" device_info_plus: dependency: "direct main" description: name: device_info_plus - url: "https://pub.dartlang.org" + sha256: "7ff671ed0a6356fa8f2e1ae7d3558d3fb7b6a41e24455e4f8df75b811fb8e4ab" + url: "https://pub.dev" source: hosted version: "8.0.0" device_info_plus_platform_interface: dependency: transitive description: name: device_info_plus_platform_interface - url: "https://pub.dartlang.org" + sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 + url: "https://pub.dev" source: hosted version: "7.0.0" dio: dependency: transitive description: name: dio - url: "https://pub.dartlang.org" + sha256: "7d328c4d898a61efc3cd93655a0955858e29a0aa647f0f9e02d59b3bb275e2e8" + url: "https://pub.dev" source: hosted version: "4.0.6" easy_geofencing: dependency: "direct main" description: name: easy_geofencing - url: "https://pub.dartlang.org" + sha256: "27f3e06988fd6653ec8a7e65a08d006d8106a2b0301a890a87cd9a2132fdc00e" + url: "https://pub.dev" source: hosted version: "0.2.0" + eip1559: + dependency: transitive + description: + name: eip1559 + sha256: de454d6321bd753eb79116e9ec4f8df20895c2e97f9a3839a032f3a728985516 + url: "https://pub.dev" + source: hosted + version: "0.6.1" eip55: dependency: transitive description: name: eip55 - url: "https://pub.dartlang.org" + sha256: "213a9b86add87a5216328e8494b0ab836e401210c4d55eb5e521bd39e39169e1" + url: "https://pub.dev" source: hosted version: "1.0.2" environment_sensors: dependency: "direct main" description: name: environment_sensors - url: "https://pub.dartlang.org" + sha256: "814c78232a2043762cb015bebd90b51cb95a37e6c636a91189f9193eabbddf78" + url: "https://pub.dev" source: hosted version: "0.2.0" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted version: "1.3.1" ffi: dependency: transitive description: name: ffi - url: "https://pub.dartlang.org" + sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + url: "https://pub.dev" source: hosted version: "2.0.1" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" source: hosted version: "6.1.4" fixnum: dependency: transitive description: name: fixnum - url: "https://pub.dartlang.org" + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.1.0" flip_card: dependency: "direct main" description: name: flip_card - url: "https://pub.dartlang.org" + sha256: "5d4aa58f3983cced0782f4ce45826b7eea36e8e464964d9209dcbc7a87b2292f" + url: "https://pub.dev" source: hosted version: "0.7.0" flutter: @@ -360,126 +418,144 @@ packages: dependency: "direct main" description: name: flutter_background_service - url: "https://pub.dartlang.org" + sha256: "7b9f15ab7d1a5784850ecfde722be4ace4dbcf1072a1fe33b7f9cbe871241e53" + url: "https://pub.dev" source: hosted version: "2.4.6" flutter_background_service_android: dependency: transitive description: name: flutter_background_service_android - url: "https://pub.dartlang.org" + sha256: "57fd631d800f7e56ca5bfadcfc00c8903eb721b23506b1a387342039521883ec" + url: "https://pub.dev" source: hosted version: "3.0.3" flutter_background_service_ios: dependency: transitive description: name: flutter_background_service_ios - url: "https://pub.dartlang.org" + sha256: d3f1dc009137c1ac19f5e3d88668836f088a7e078396733547339765d46ff12f + url: "https://pub.dev" source: hosted version: "2.4.0" flutter_background_service_platform_interface: dependency: transitive description: name: flutter_background_service_platform_interface - url: "https://pub.dartlang.org" + sha256: "5f0480ee8378984f718d640abbe09b4d6d024d58a72b2d8b86bdedb3cf095ff8" + url: "https://pub.dev" source: hosted version: "2.2.0" flutter_blurhash: dependency: transitive description: name: flutter_blurhash - url: "https://pub.dartlang.org" + sha256: "05001537bd3fac7644fa6558b09ec8c0a3f2eba78c0765f88912882b1331a5c6" + url: "https://pub.dev" source: hosted version: "0.7.0" flutter_cache_manager: dependency: transitive description: name: flutter_cache_manager - url: "https://pub.dartlang.org" + sha256: "32cd900555219333326a2d0653aaaf8671264c29befa65bbd9856d204a4c9fb3" + url: "https://pub.dev" source: hosted version: "3.3.0" flutter_config: dependency: "direct main" description: name: flutter_config - url: "https://pub.dartlang.org" + sha256: "8e2be2d560a52e06d2ef53a31913a11fc80ef708a442571c96194fd32e29fb1a" + url: "https://pub.dev" source: hosted version: "2.0.0" flutter_foreground_task: dependency: "direct main" description: name: flutter_foreground_task - url: "https://pub.dartlang.org" + sha256: "5eb81adfd98c77f4d4803ae80d7e0573fd35f706fce6aaa7376656a15ba2d1e0" + url: "https://pub.dev" source: hosted version: "3.10.0" flutter_intl: dependency: "direct main" description: name: flutter_intl - url: "https://pub.dartlang.org" + sha256: "17b138fab0477c7d17abd8ba67d294786eef8fe80342e58b6253aef7d0ca2bad" + url: "https://pub.dev" source: hosted version: "0.0.1" flutter_isolate: dependency: "direct main" description: name: flutter_isolate - url: "https://pub.dartlang.org" + sha256: "994ddec596da4ca12ca52154fd59404077584643eb7e3f1008a55fda9fe0b76b" + url: "https://pub.dev" source: hosted version: "2.0.4" flutter_lints: dependency: "direct dev" description: name: flutter_lints - url: "https://pub.dartlang.org" + sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + url: "https://pub.dev" source: hosted version: "2.0.1" flutter_local_notifications: dependency: "direct main" description: name: flutter_local_notifications - url: "https://pub.dartlang.org" + sha256: "293995f94e120c8afce768981bd1fa9c5d6de67c547568e3b42ae2defdcbb4a0" + url: "https://pub.dev" source: hosted version: "13.0.0" flutter_local_notifications_linux: dependency: transitive description: name: flutter_local_notifications_linux - url: "https://pub.dartlang.org" + sha256: "8f6c1611e0c4a88a382691a97bb3c3feb24cc0c0b54152b8b5fb7ffb837f7fbf" + url: "https://pub.dev" source: hosted version: "3.0.0" flutter_local_notifications_platform_interface: dependency: transitive description: name: flutter_local_notifications_platform_interface - url: "https://pub.dartlang.org" + sha256: "5ec1feac5f7f7d9266759488bc5f76416152baba9aa1b26fe572246caa00d1ab" + url: "https://pub.dev" source: hosted version: "6.0.0" flutter_map: dependency: transitive description: name: flutter_map - url: "https://pub.dartlang.org" + sha256: "59dfd14267b691bea55760786b47d3172d47cdcc0d79ff930746a5ad123491b8" + url: "https://pub.dev" source: hosted version: "3.1.0" flutter_native_splash: dependency: "direct main" description: name: flutter_native_splash - url: "https://pub.dartlang.org" + sha256: "048bd1f1dc0e5ea25899f702815934d9a9e916fe23451c320e7dd94d5e3ad933" + url: "https://pub.dev" source: hosted version: "2.2.17" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - url: "https://pub.dartlang.org" + sha256: "60fc7b78455b94e6de2333d2f95196d32cf5c22f4b0b0520a628804cb463503b" + url: "https://pub.dev" source: hosted version: "2.0.7" flutter_spinkit: dependency: "direct main" description: name: flutter_spinkit - url: "https://pub.dartlang.org" + sha256: "77a2117c0517ff909221f3160b8eb20052ab5216107581168af574ac1f05dff8" + url: "https://pub.dev" source: hosted version: "5.1.0" flutter_test: @@ -496,539 +572,608 @@ packages: dependency: transitive description: name: frontend_server_client - url: "https://pub.dartlang.org" + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" source: hosted version: "3.2.0" geocoding: dependency: "direct main" description: name: geocoding - url: "https://pub.dartlang.org" + sha256: "26218460a902d4249b81e6baf9d55ce400fd1ebe6fc0a7e92b2c12b0b8e1e14e" + url: "https://pub.dev" source: hosted version: "2.0.5" geocoding_platform_interface: dependency: transitive description: name: geocoding_platform_interface - url: "https://pub.dartlang.org" + sha256: "8848605d307d844d89937cdb4b8ad7dfa880552078f310fa24d8a460f6dddab4" + url: "https://pub.dev" source: hosted version: "2.0.1" geolocator: dependency: "direct main" description: name: geolocator - url: "https://pub.dartlang.org" + sha256: b8f520252c5c66851295bcc263bc8ae7555501938427f72216ba7688702e261d + url: "https://pub.dev" source: hosted version: "7.7.1" geolocator_android: dependency: transitive description: name: geolocator_android - url: "https://pub.dartlang.org" + sha256: "2f84d6d68b97a3774f2c4111ac95ec5898cd9b98f12193fc3ea7fa21d7a8b46c" + url: "https://pub.dev" source: hosted version: "2.1.0" geolocator_apple: dependency: transitive description: name: geolocator_apple - url: "https://pub.dartlang.org" + sha256: "1e8e398cc92151d946a4bbd34e2075885333e42d35ca33e418e7ce7b0a29991e" + url: "https://pub.dev" source: hosted version: "1.2.2" geolocator_platform_interface: dependency: transitive description: name: geolocator_platform_interface - url: "https://pub.dartlang.org" + sha256: "9d6f34a8a4b704d504f34acc5e52d880a7d2caedd99739902d6319179b0336d4" + url: "https://pub.dev" source: hosted version: "2.3.6" geolocator_web: dependency: transitive description: name: geolocator_web - url: "https://pub.dartlang.org" + sha256: "0b9e0ec13ce2211085cae0055b3516c975bd6cfe2878a20c8f13611f1a259855" + url: "https://pub.dev" source: hosted version: "2.0.6" glob: dependency: transitive description: name: glob - url: "https://pub.dartlang.org" + sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" + url: "https://pub.dev" source: hosted version: "2.1.1" google_fonts: dependency: "direct main" description: name: google_fonts - url: "https://pub.dartlang.org" + sha256: "8f099045e2f2a30e4d4d0a35f40c6bc941a8f2ca0e10ad9d214ee9edd3f37483" + url: "https://pub.dev" source: hosted version: "3.0.1" graphs: dependency: transitive description: name: graphs - url: "https://pub.dartlang.org" + sha256: f9e130f3259f52d26f0cfc0e964513796dafed572fa52e45d2f8d6ca14db39b2 + url: "https://pub.dev" source: hosted version: "2.2.0" html: dependency: transitive description: name: html - url: "https://pub.dartlang.org" + sha256: d9793e10dbe0e6c364f4c59bf3e01fb33a9b2a674bc7a1081693dba0614b6269 + url: "https://pub.dev" source: hosted version: "0.15.1" http: dependency: "direct main" description: name: http - url: "https://pub.dartlang.org" + sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + url: "https://pub.dev" source: hosted version: "0.13.5" http_multi_server: dependency: transitive description: name: http_multi_server - url: "https://pub.dartlang.org" + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" source: hosted version: "3.2.1" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" source: hosted version: "4.0.2" image: dependency: transitive description: name: image - url: "https://pub.dartlang.org" + sha256: "3686865febd85c57a632d87a0fb1f0a8a9ef602fdb68d909c3e9aa29ec70fd24" + url: "https://pub.dev" source: hosted - version: "4.0.12" + version: "4.0.13" infinite_listview: dependency: transitive description: name: infinite_listview - url: "https://pub.dartlang.org" + sha256: f6062c1720eb59be553dfa6b89813d3e8dd2f054538445aaa5edaddfa5195ce6 + url: "https://pub.dev" source: hosted version: "1.1.0" intl: dependency: "direct main" description: name: intl - url: "https://pub.dartlang.org" + sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + url: "https://pub.dev" source: hosted version: "0.17.0" io: dependency: transitive description: name: io - url: "https://pub.dartlang.org" + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" source: hosted version: "1.0.4" ipfs_client_flutter: dependency: "direct main" description: name: ipfs_client_flutter - url: "https://pub.dartlang.org" + sha256: e9ec8c3b33af20240cdfcb1316ef0804be68d5237df65a82ff3f3a2cfc2fd497 + url: "https://pub.dev" source: hosted version: "1.0.7" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + url: "https://pub.dev" source: hosted - version: "0.6.4" + version: "0.6.5" json_annotation: dependency: transitive description: name: json_annotation - url: "https://pub.dartlang.org" + sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 + url: "https://pub.dev" source: hosted version: "4.8.0" json_rpc_2: dependency: transitive description: name: json_rpc_2 - url: "https://pub.dartlang.org" + sha256: "5e469bffa23899edacb7b22787780068d650b106a21c76db3c49218ab7ca447e" + url: "https://pub.dev" source: hosted version: "3.0.2" latlong2: dependency: transitive description: name: latlong2 - url: "https://pub.dartlang.org" + sha256: "408993a0e3f46e79ce1f129e4cb0386eef6d48dfa6394939ecacfbd7049154ec" + url: "https://pub.dev" source: hosted version: "0.8.1" lints: dependency: transitive description: name: lints - url: "https://pub.dartlang.org" + sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + url: "https://pub.dev" source: hosted version: "2.0.1" lists: dependency: transitive description: name: lists - url: "https://pub.dartlang.org" + sha256: "4ca5c19ae4350de036a7e996cdd1ee39c93ac0a2b840f4915459b7d0a7d4ab27" + url: "https://pub.dev" source: hosted version: "1.0.1" logging: dependency: transitive description: name: logging - url: "https://pub.dartlang.org" + sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + url: "https://pub.dev" source: hosted - version: "0.12.12" + version: "0.12.13" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" source: hosted - version: "0.1.5" + version: "0.2.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + url: "https://pub.dev" source: hosted version: "1.8.0" mgrs_dart: dependency: transitive description: name: mgrs_dart - url: "https://pub.dartlang.org" + sha256: fb89ae62f05fa0bb90f70c31fc870bcbcfd516c843fb554452ab3396f78586f7 + url: "https://pub.dev" source: hosted version: "2.0.0" mime: dependency: transitive description: name: mime - url: "https://pub.dartlang.org" + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" source: hosted version: "1.0.4" numberpicker: dependency: "direct main" description: name: numberpicker - url: "https://pub.dartlang.org" + sha256: "73723bd13c940ebcd9e5f0ed56b4874588c1748a9a6a38254f97ad627715142e" + url: "https://pub.dev" source: hosted version: "2.1.1" octo_image: dependency: transitive description: name: octo_image - url: "https://pub.dartlang.org" + sha256: "107f3ed1330006a3bea63615e81cf637433f5135a52466c7caa0e7152bca9143" + url: "https://pub.dev" source: hosted version: "1.0.2" open_street_map_search_and_pick: dependency: "direct main" description: name: open_street_map_search_and_pick - url: "https://pub.dartlang.org" + sha256: "806c24b042b01658be0d083f34e9b43563ab6c0a49f4583b10e6b36b41f59167" + url: "https://pub.dev" source: hosted version: "0.0.15" package_config: dependency: transitive description: name: package_config - url: "https://pub.dartlang.org" + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" source: hosted version: "2.1.0" path: dependency: "direct main" description: name: path - url: "https://pub.dartlang.org" + sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + url: "https://pub.dev" source: hosted version: "1.8.2" path_provider: dependency: "direct main" description: name: path_provider - url: "https://pub.dartlang.org" + sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + url: "https://pub.dev" source: hosted - version: "2.0.11" + version: "2.0.12" path_provider_android: dependency: transitive description: name: path_provider_android - url: "https://pub.dartlang.org" + sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + url: "https://pub.dev" source: hosted version: "2.0.22" - path_provider_ios: + path_provider_foundation: dependency: transitive description: - name: path_provider_ios - url: "https://pub.dartlang.org" + name: path_provider_foundation + sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + url: "https://pub.dev" source: hosted - version: "2.0.11" + version: "2.1.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - url: "https://pub.dartlang.org" + sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + url: "https://pub.dev" source: hosted version: "2.1.7" - path_provider_macos: - dependency: transitive - description: - name: path_provider_macos - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.7" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - url: "https://pub.dartlang.org" + sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + url: "https://pub.dev" source: hosted version: "2.0.5" path_provider_windows: dependency: transitive description: name: path_provider_windows - url: "https://pub.dartlang.org" + sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c + url: "https://pub.dev" source: hosted version: "2.1.3" pedantic: dependency: transitive description: name: pedantic - url: "https://pub.dartlang.org" + sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602" + url: "https://pub.dev" source: hosted version: "1.11.1" permission_handler: dependency: "direct main" description: name: permission_handler - url: "https://pub.dartlang.org" + sha256: "33c6a1253d1f95fd06fa74b65b7ba907ae9811f9d5c1d3150e51417d04b8d6a8" + url: "https://pub.dev" source: hosted version: "10.2.0" permission_handler_android: dependency: transitive description: name: permission_handler_android - url: "https://pub.dartlang.org" + sha256: "8028362b40c4a45298f1cbfccd227c8dd6caf0e27088a69f2ba2ab15464159e2" + url: "https://pub.dev" source: hosted version: "10.2.0" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - url: "https://pub.dartlang.org" + sha256: "9c370ef6a18b1c4b2f7f35944d644a56aa23576f23abee654cf73968de93f163" + url: "https://pub.dev" source: hosted version: "9.0.7" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - url: "https://pub.dartlang.org" + sha256: "68abbc472002b5e6dfce47fe9898c6b7d8328d58b5d2524f75e277c07a97eb84" + url: "https://pub.dev" source: hosted version: "3.9.0" permission_handler_windows: dependency: transitive description: name: permission_handler_windows - url: "https://pub.dartlang.org" + sha256: f67cab14b4328574938ecea2db3475dad7af7ead6afab6338772c5f88963e38b + url: "https://pub.dev" source: hosted version: "0.1.2" petitparser: dependency: transitive description: name: petitparser - url: "https://pub.dartlang.org" + sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" + url: "https://pub.dev" source: hosted version: "5.1.0" platform: dependency: transitive description: name: platform - url: "https://pub.dartlang.org" + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" source: hosted version: "3.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a + url: "https://pub.dev" source: hosted version: "2.1.3" pointycastle: dependency: transitive description: name: pointycastle - url: "https://pub.dartlang.org" + sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346 + url: "https://pub.dev" source: hosted version: "3.6.2" polylabel: dependency: transitive description: name: polylabel - url: "https://pub.dartlang.org" + sha256: "41b9099afb2aa6c1730bdd8a0fab1400d287694ec7615dd8516935fa3144214b" + url: "https://pub.dev" source: hosted version: "1.0.1" pool: dependency: transitive description: name: pool - url: "https://pub.dartlang.org" + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" source: hosted version: "1.5.1" positioned_tap_detector_2: dependency: transitive description: name: positioned_tap_detector_2 - url: "https://pub.dartlang.org" + sha256: "52e06863ad3e1f82b058fd05054fc8c9caeeb3b47d5cea7a24bd9320746059c1" + url: "https://pub.dev" source: hosted version: "1.0.4" process: dependency: transitive description: name: process - url: "https://pub.dartlang.org" + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" source: hosted version: "4.2.4" proj4dart: dependency: transitive description: name: proj4dart - url: "https://pub.dartlang.org" + sha256: c8a659ac9b6864aa47c171e78d41bbe6f5e1d7bd790a5814249e6b68bc44324e + url: "https://pub.dev" source: hosted version: "2.1.0" pub_semver: dependency: transitive description: name: pub_semver - url: "https://pub.dartlang.org" + sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" + url: "https://pub.dev" source: hosted version: "2.1.3" pubspec_parse: dependency: transitive description: name: pubspec_parse - url: "https://pub.dartlang.org" + sha256: "75f6614d6dde2dc68948dffbaa4fe5dae32cd700eb9fb763fe11dfb45a3c4d0a" + url: "https://pub.dev" source: hosted version: "1.2.1" qr: dependency: transitive description: name: qr - url: "https://pub.dartlang.org" + sha256: "5c4208b4dc0d55c3184d10d83ee0ded6212dc2b5e2ba17c5a0c0aab279128d21" + url: "https://pub.dev" source: hosted version: "2.1.0" qr_flutter: dependency: transitive description: name: qr_flutter - url: "https://pub.dartlang.org" + sha256: c5c121c54cb6dd837b9b9d57eb7bc7ec6df4aee741032060c8833a678c80b87e + url: "https://pub.dev" source: hosted version: "4.0.0" quiver: dependency: transitive description: name: quiver - url: "https://pub.dartlang.org" + sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 + url: "https://pub.dev" source: hosted version: "3.2.1" rxdart: dependency: transitive description: name: rxdart - url: "https://pub.dartlang.org" + sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" + url: "https://pub.dev" source: hosted version: "0.27.7" sec: dependency: transitive description: name: sec - url: "https://pub.dartlang.org" + sha256: "78e2ed80b8782fe03496ff3c626d5f6139efbe00c577327c613ad8540ea4b14a" + url: "https://pub.dev" source: hosted version: "1.0.1" shared_preferences: dependency: "direct main" description: name: shared_preferences - url: "https://pub.dartlang.org" + sha256: "5949029e70abe87f75cfe59d17bf5c397619c4b74a099b10116baeb34786fad9" + url: "https://pub.dev" source: hosted version: "2.0.17" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - url: "https://pub.dartlang.org" + sha256: "955e9736a12ba776bdd261cf030232b30eadfcd9c79b32a3250dd4a494e8c8f7" + url: "https://pub.dev" source: hosted version: "2.0.15" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - url: "https://pub.dartlang.org" + sha256: "2b55c18636a4edc529fa5cd44c03d3f3100c00513f518c5127c951978efcccd0" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" shared_preferences_ios: dependency: transitive description: name: shared_preferences_ios - url: "https://pub.dartlang.org" + sha256: "585a14cefec7da8c9c2fb8cd283a3bb726b4155c0952afe6a0caaa7b2272de34" + url: "https://pub.dev" source: hosted version: "2.1.1" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - url: "https://pub.dartlang.org" + sha256: f8ea038aa6da37090093974ebdcf4397010605fd2ff65c37a66f9d28394cb874 + url: "https://pub.dev" source: hosted version: "2.1.3" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - url: "https://pub.dartlang.org" + sha256: da9431745ede5ece47bc26d5d73a9d3c6936ef6945c101a5aca46f62e52c1cf3 + url: "https://pub.dev" source: hosted version: "2.1.0" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - url: "https://pub.dartlang.org" + sha256: a4b5bc37fe1b368bbc81f953197d55e12f49d0296e7e412dfe2d2d77d6929958 + url: "https://pub.dev" source: hosted version: "2.0.4" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - url: "https://pub.dartlang.org" + sha256: "5eaf05ae77658d3521d0e993ede1af962d4b326cd2153d312df716dc250f00c9" + url: "https://pub.dev" source: hosted version: "2.1.3" shelf: dependency: transitive description: name: shelf - url: "https://pub.dartlang.org" + sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c + url: "https://pub.dev" source: hosted version: "1.4.0" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - url: "https://pub.dartlang.org" + sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 + url: "https://pub.dev" source: hosted version: "1.0.3" shimmer: dependency: transitive description: name: shimmer - url: "https://pub.dartlang.org" + sha256: "1f1009b5845a1f88f1c5630212279540486f97409e9fc3f63883e71070d107bf" + url: "https://pub.dev" source: hosted version: "2.0.0" sky_engine: @@ -1040,296 +1185,346 @@ packages: dependency: "direct main" description: name: slider_button - url: "https://pub.dartlang.org" + sha256: "9e23a806af48fa615b0891a18be87bb751ae3b6ca8dd5a299ecaafdf351623ef" + url: "https://pub.dev" source: hosted version: "2.0.0" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" sqflite: dependency: "direct main" description: name: sqflite - url: "https://pub.dartlang.org" + sha256: "78324387dc81df14f78df06019175a86a2ee0437624166c382e145d0a7fd9a4f" + url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.2.4+1" sqflite_common: dependency: transitive description: name: sqflite_common - url: "https://pub.dartlang.org" + sha256: bfd6973aaeeb93475bc0d875ac9aefddf7965ef22ce09790eb963992ffc5183f + url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2+2" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" stream_transform: dependency: transitive description: name: stream_transform - url: "https://pub.dartlang.org" + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" source: hosted version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" syncfusion_flutter_charts: dependency: "direct main" description: name: syncfusion_flutter_charts - url: "https://pub.dartlang.org" + sha256: "91204839376779c4ea4d7d7734abb039b429c4248a051c43079bff2e9b920a6e" + url: "https://pub.dev" source: hosted - version: "20.4.44" + version: "20.4.48" syncfusion_flutter_core: dependency: transitive description: name: syncfusion_flutter_core - url: "https://pub.dartlang.org" + sha256: b3e500b1896d40c8961ab430a94fc22eff8fa1b33af03584e2f0b89371c3fa6a + url: "https://pub.dev" source: hosted - version: "20.4.44" + version: "20.4.48" synchronized: dependency: transitive description: name: synchronized - url: "https://pub.dartlang.org" + sha256: "33b31b6beb98100bf9add464a36a8dd03eb10c7a8cf15aeec535e9b054aaf04b" + url: "https://pub.dev" source: hosted version: "3.0.1" tar: dependency: "direct main" description: name: tar - url: "https://pub.dartlang.org" + sha256: "85ffd53e277f2bac8afa2885e6b195e26937e9c402424c3d88d92fd920b56de9" + url: "https://pub.dev" source: hosted version: "0.5.6" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + url: "https://pub.dev" source: hosted - version: "0.4.12" + version: "0.4.16" timezone: dependency: transitive description: name: timezone - url: "https://pub.dartlang.org" + sha256: "24c8fcdd49a805d95777a39064862133ff816ebfffe0ceff110fb5960e557964" + url: "https://pub.dev" source: hosted version: "0.9.1" timing: dependency: transitive description: name: timing - url: "https://pub.dartlang.org" + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" source: hosted version: "1.0.1" tuple: dependency: transitive description: name: tuple - url: "https://pub.dartlang.org" + sha256: "0ea99cd2f9352b2586583ab2ce6489d1f95a5f6de6fb9492faaf97ae2060f0aa" + url: "https://pub.dev" source: hosted version: "2.0.1" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" source: hosted version: "1.3.1" unicode: dependency: transitive description: name: unicode - url: "https://pub.dartlang.org" + sha256: "0f69e46593d65245774d4f17125c6084d2c20b4e473a983f6e21b7d7762218f1" + url: "https://pub.dev" source: hosted version: "0.3.1" universal_io: dependency: transitive description: name: universal_io - url: "https://pub.dartlang.org" + sha256: "79f78ddad839ee3aae3ec7c01eb4575faf0d5c860f8e5223bc9f9c17f7f03cef" + url: "https://pub.dev" source: hosted version: "2.0.4" url_launcher: dependency: "direct main" description: name: url_launcher - url: "https://pub.dartlang.org" + sha256: "698fa0b4392effdc73e9e184403b627362eb5fbf904483ac9defbb1c2191d809" + url: "https://pub.dev" source: hosted version: "6.1.8" url_launcher_android: dependency: transitive description: name: url_launcher_android - url: "https://pub.dartlang.org" + sha256: "3e2f6dfd2c7d9cd123296cab8ef66cfc2c1a13f5845f42c7a0f365690a8a7dd1" + url: "https://pub.dev" source: hosted version: "6.0.23" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - url: "https://pub.dartlang.org" + sha256: bb328b24d3bccc20bdf1024a0990ac4f869d57663660de9c936fb8c043edefe3 + url: "https://pub.dev" source: hosted version: "6.0.18" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - url: "https://pub.dartlang.org" + sha256: "318c42cba924e18180c029be69caf0a1a710191b9ec49bb42b5998fdcccee3cc" + url: "https://pub.dev" source: hosted version: "3.0.2" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - url: "https://pub.dartlang.org" + sha256: "41988b55570df53b3dd2a7fc90c76756a963de6a8c5f8e113330cb35992e2094" + url: "https://pub.dev" source: hosted version: "3.0.2" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - url: "https://pub.dartlang.org" + sha256: "4eae912628763eb48fc214522e58e942fd16ce195407dbf45638239523c759a6" + url: "https://pub.dev" source: hosted version: "2.1.1" url_launcher_web: dependency: transitive description: name: url_launcher_web - url: "https://pub.dartlang.org" + sha256: "44d79408ce9f07052095ef1f9a693c258d6373dc3944249374e30eff7219ccb0" + url: "https://pub.dev" source: hosted version: "2.0.14" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - url: "https://pub.dartlang.org" + sha256: b6217370f8eb1fd85c8890c539f5a639a01ab209a36db82c921ebeacefc7a615 + url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" uuid: dependency: transitive description: name: uuid - url: "https://pub.dartlang.org" + sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + url: "https://pub.dev" source: hosted version: "3.0.7" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" vibration: dependency: transitive description: name: vibration - url: "https://pub.dartlang.org" + sha256: "1dc9d1a0d62b12f1276eb7146b21585db5fe01771b8ca0234fefdf74ba51f963" + url: "https://pub.dev" source: hosted version: "1.7.6" + wallet: + dependency: transitive + description: + name: wallet + sha256: "2cabf10d4543b95773219fc401b184f8cbb0bba9359883f5ee5b9f2c46b85de3" + url: "https://pub.dev" + source: hosted + version: "0.0.7" walletconnect_dart: dependency: "direct main" description: name: walletconnect_dart - url: "https://pub.dartlang.org" + sha256: "6d69d3f7ed43b4a111458da0ba078f4ea291ff11328068c9cbf5cab3bd86593f" + url: "https://pub.dev" source: hosted version: "0.0.11" walletconnect_qrcode_modal_dart: dependency: "direct main" description: name: walletconnect_qrcode_modal_dart - url: "https://pub.dartlang.org" + sha256: "3ae5ff25e33b3c647fc5ec03d5c943d21e145371e9577e340f4be07e9f97a73c" + url: "https://pub.dev" source: hosted version: "0.0.6" watcher: dependency: transitive description: name: watcher - url: "https://pub.dartlang.org" + sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + url: "https://pub.dev" source: hosted version: "1.0.2" web3dart: dependency: "direct main" description: name: web3dart - url: "https://pub.dartlang.org" + sha256: "0b96223a6b284e3146e65dc842ded139eca68a85c4ab79c5ba1a73284927d3cd" + url: "https://pub.dev" source: hosted - version: "2.5.1" + version: "2.6.1" web_socket_channel: dependency: transitive description: name: web_socket_channel - url: "https://pub.dartlang.org" + sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b + url: "https://pub.dev" source: hosted version: "2.3.0" win32: dependency: transitive description: name: win32 - url: "https://pub.dartlang.org" + sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 + url: "https://pub.dev" source: hosted version: "3.1.3" wkt_parser: dependency: transitive description: name: wkt_parser - url: "https://pub.dartlang.org" + sha256: "8a555fc60de3116c00aad67891bcab20f81a958e4219cc106e3c037aa3937f13" + url: "https://pub.dev" source: hosted version: "2.0.0" workmanager: dependency: "direct main" description: name: workmanager - url: "https://pub.dartlang.org" + sha256: e0be7e35d644643f164ee45d2ce14414f0e0fdde19456aa66065f35a0b1d2ea1 + url: "https://pub.dev" source: hosted version: "0.5.1" xdg_directories: dependency: transitive description: name: xdg_directories - url: "https://pub.dartlang.org" + sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 + url: "https://pub.dev" source: hosted version: "0.2.0+3" xml: dependency: transitive description: name: xml - url: "https://pub.dartlang.org" + sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" + url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "6.2.2" yaml: dependency: transitive description: name: yaml - url: "https://pub.dartlang.org" + sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + url: "https://pub.dev" source: hosted version: "3.1.1" sdks: - dart: ">=2.18.0 <3.0.0" + dart: ">=2.19.0 <3.0.0" flutter: ">=3.3.0" From 8a517ac11e9ab9841f9de85da554e95ab3f1e364 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Thu, 2 Feb 2023 18:57:08 +0100 Subject: [PATCH 13/34] refactor close campaign --- .../close_campaign_controller.dart | 38 --- .../sourcer_campaign_controller.dart | 296 ++++++++++-------- lib/main.dart | 6 - lib/models/close_campaign_model.dart | 5 - lib/views/close_campaign_view.dart | 39 --- 5 files changed, 158 insertions(+), 226 deletions(-) delete mode 100644 lib/controllers/close_campaign_controller.dart delete mode 100644 lib/views/close_campaign_view.dart diff --git a/lib/controllers/close_campaign_controller.dart b/lib/controllers/close_campaign_controller.dart deleted file mode 100644 index e40f1f5..0000000 --- a/lib/controllers/close_campaign_controller.dart +++ /dev/null @@ -1,38 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:mobile_crowd_sensing/utils/spalsh_screens.dart'; -import '../views/dialog_view.dart'; -import '../models/close_campaign_model.dart'; - -class CloseCampaignController extends StatefulWidget { - final String address; - const CloseCampaignController({super.key,required this.address}); - - @override - State createState() => - _CloseCampaignControllerState(); -} - -class _CloseCampaignControllerState extends State { - @override - Widget build(BuildContext context) { - _getData(context); - return CustomSplashScreen.fadingCubeBlueBg(context); - } - - Future _getData(BuildContext context) async { - String result = await CloseCampaignModel.closeMyCampaign(widget.address); - - if (result.contains("Campaign Closed")) { - if (!mounted) return; - Navigator.of(context) - .pushNamedAndRemoveUntil('/home', (Route route) => false); - } else { - if (!mounted) return; - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (context) => DialogView( - message: "Error on result:\n${result.toString()}"))); - } - } -} diff --git a/lib/controllers/sourcer_campaign_controller.dart b/lib/controllers/sourcer_campaign_controller.dart index a5cc350..16dbd58 100644 --- a/lib/controllers/sourcer_campaign_controller.dart +++ b/lib/controllers/sourcer_campaign_controller.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'package:flutter/material.dart'; +import '../models/close_campaign_model.dart'; import '../models/sourcer_campaign_model.dart'; import '../utils/styles.dart'; @@ -15,18 +16,18 @@ class _SourcerCampaignControllerState extends State { Object? parameters; dynamic jsonParameters = {}; dynamic jsonCounters = {}; - + bool showCiucular = false; String fileCount = '0'; String fileChecked = '0'; String workersCount = '0'; - late String name ='', - lat ='', - lng ='', - range ='', - type ='', - crowdsourcer ='', - contractAddress ='', - readebleLocation =''; + late String name = '', + lat = '', + lng = '', + range = '', + type = '', + crowdsourcer = '', + contractAddress = '', + readebleLocation = ''; _formatData(String contractAddress) async { await SourcerCampaignModel.getCountersData(contractAddress).then((val) { @@ -41,149 +42,168 @@ class _SourcerCampaignControllerState extends State { }); } }); - } @override Widget build(BuildContext context) { - parameters = ModalRoute - .of(context)! - .settings - .arguments; - jsonParameters = jsonDecode(jsonEncode(parameters)); - name = jsonParameters["name"]; - lat = jsonParameters["lat"]; - lng = jsonParameters["lng"]; - range = jsonParameters["range"]; - type = jsonParameters["campaignType"]; - crowdsourcer = jsonParameters["addressCrowdSourcer"]; - contractAddress = jsonParameters["contractAddress"]; - readebleLocation = jsonParameters["redebleLocation"]; - _formatData(contractAddress); - return _buildPage(context); - + parameters = ModalRoute.of(context)!.settings.arguments; + jsonParameters = jsonDecode(jsonEncode(parameters)); + name = jsonParameters["name"]; + lat = jsonParameters["lat"]; + lng = jsonParameters["lng"]; + range = jsonParameters["range"]; + type = jsonParameters["campaignType"]; + crowdsourcer = jsonParameters["addressCrowdSourcer"]; + contractAddress = jsonParameters["contractAddress"]; + readebleLocation = jsonParameters["redebleLocation"]; + _formatData(contractAddress); + return _buildPage(context); } - Widget _buildPage(context) { - if (contractAddress != "0x0000000000000000000000000000000000000000" || contractAddress.isEmpty) { + if (contractAddress != "0x0000000000000000000000000000000000000000" || + contractAddress.isEmpty) { return Container( - padding: const EdgeInsets.fromLTRB(10, 30, 10, 10), - width: double.maxFinite, - child: Column(children: [ - Card( - shadowColor: Colors.blue[600], - color: Colors.white54, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20.0), - ), - child: Padding( - padding: const EdgeInsets.all(20), - child: Stack( - children: [ - Align( - alignment: Alignment.topLeft, - child: Column(children: [ - Row(children: [ - //loop - (name.isEmpty) - ? GlobalText.loadingText(context) - : Expanded( - flex: 5, - child: Text("Name: $name", - style: CustomTextStyle.spaceMono( - context))), - ]), - Row(children: [ - (lat.isEmpty) - ? GlobalText.loadingText(context) - : Text( - "Latitude: ${(int.parse(lat) / 10000000)}", - style: CustomTextStyle.spaceMono(context), - ), - ]), - Row(children: [ - (lng.isEmpty) - ? GlobalText.loadingText(context) - : Text( - "Longitude: ${(int.parse(lng) / 10000000)}", - style: - CustomTextStyle.spaceMono(context)), - ]), - Column(children: [ - (readebleLocation.isEmpty) - ? GlobalText.loadingText(context) - : Text( - "Location: $readebleLocation", - style: CustomTextStyle.spaceMono(context), - ), - ]), - Row(children: [ - (range.isEmpty) - ? GlobalText.loadingText(context) - : Text( - "Range: $range", - style: CustomTextStyle.spaceMono(context), - ), - ]), - Row(children: [ - (type.isEmpty) - ? GlobalText.loadingText(context) - : Text( - "Type: $type", - style: CustomTextStyle.spaceMono(context), - ), - ]), - ])), - ], + padding: const EdgeInsets.fromLTRB(10, 30, 10, 10), + width: double.maxFinite, + child: Column(children: [ + Card( + shadowColor: Colors.blue[600], + color: Colors.white54, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20.0), ), + child: Padding( + padding: const EdgeInsets.all(20), + child: Stack( + children: [ + Align( + alignment: Alignment.topLeft, + child: Column(children: [ + Row(children: [ + //loop + (name.isEmpty) + ? GlobalText.loadingText(context) + : Expanded( + flex: 5, + child: Text("Name: $name", + style: CustomTextStyle.spaceMono( + context))), + ]), + Row(children: [ + (lat.isEmpty) + ? GlobalText.loadingText(context) + : Text( + "Latitude: ${(int.parse(lat) / 10000000)}", + style: CustomTextStyle.spaceMono(context), + ), + ]), + Row(children: [ + (lng.isEmpty) + ? GlobalText.loadingText(context) + : Text( + "Longitude: ${(int.parse(lng) / 10000000)}", + style: CustomTextStyle.spaceMono(context)), + ]), + Column(children: [ + (readebleLocation.isEmpty) + ? GlobalText.loadingText(context) + : Text( + "Location: $readebleLocation", + style: CustomTextStyle.spaceMono(context), + ), + ]), + Row(children: [ + (range.isEmpty) + ? GlobalText.loadingText(context) + : Text( + "Range: $range", + style: CustomTextStyle.spaceMono(context), + ), + ]), + Row(children: [ + (type.isEmpty) + ? GlobalText.loadingText(context) + : Text( + "Type: $type", + style: CustomTextStyle.spaceMono(context), + ), + ]), + ])), + ], + ), + ), + ), + Flexible( + flex: 5, + child: Text( + "Sourcing Status:\nuploaded $fileCount files\nchecked $fileChecked of $fileCount\nwhit the contribution of $workersCount workers", + style: CustomTextStyle.spaceMono(context), + )), + const SizedBox( + height: 20, ), - ), - Flexible( - flex: 5, - child: Text( - "Sourcing Status:\nuploaded $fileCount files\nchecked $fileChecked of $fileCount\nwhit the contribution of $workersCount workers", - style: CustomTextStyle.spaceMono(context), - )), - const SizedBox(height: 20,), - FloatingActionButton( - backgroundColor: CustomColors.red600(context), - child: Icon(Icons.close,color: CustomColors.customWhite(context),), - onPressed: () { - showDialog( - context: context, - builder: (ctx) => AlertDialog( - title: const Text('Are you sure?'), - content: const Text('Do you want to close this campaign?'), - actions: [ - TextButton( - child: const Text('No'), - onPressed: () { - Navigator.of(ctx).pop(false); - }), - TextButton( - child: const Text('Yes'), - onPressed: () { - Navigator.of(ctx).pop(true); - Navigator.popAndPushNamed(context, - "/sourcer_close_campaign_service_provider", - arguments: { - 'address': contractAddress.toString(), - }); - }), - ], - ), - ); - }) - ]) - ); + (!showCiucular) + ? FloatingActionButton( + backgroundColor: CustomColors.red600(context), + child: Icon( + Icons.close, + color: CustomColors.customWhite(context), + ), + onPressed: () { + showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: const Text('Are you sure?'), + content: + const Text('Do you want to close this campaign?'), + actions: [ + TextButton( + child: const Text('No'), + onPressed: () { + Navigator.of(ctx).pop(false); + }), + TextButton( + child: const Text('Yes'), + onPressed: () { + setState(() async { + Navigator.of(ctx).pop(true); + String result = await CloseCampaignModel + .closeMyCampaign(contractAddress); + if (result.contains("Campaign Closed")) { + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + 'Campaign Closed', + style: CustomTextStyle.spaceMonoWhite( + context), + ))); + Navigator.of(context) + .pushNamedAndRemoveUntil('/home', + (Route route) => false); + } else { + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + result, + style: CustomTextStyle.spaceMonoWhite( + context), + ))); + } + }); + }) + ], + ), + ); + }) + : const Center(child: CircularProgressIndicator()) + ])); } else { - return Center(child: Text( + return Center( + child: Text( 'No active campaign at the moment...', style: CustomTextStyle.spaceMono(context), )); } } } - - diff --git a/lib/main.dart b/lib/main.dart index 1759fff..aec028b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,4 @@ import 'dart:io'; - import 'package:flip_card/flip_card.dart'; import 'package:flutter/material.dart'; import 'package:flutter_config/flutter_config.dart'; @@ -7,7 +6,6 @@ import 'package:mobile_crowd_sensing/utils/internet_connection.dart'; import 'package:mobile_crowd_sensing/utils/styles.dart'; import 'package:mobile_crowd_sensing/utils/verifier_campaign_data_factory.dart'; import 'package:mobile_crowd_sensing/views/all_campaign_view.dart'; -import 'package:mobile_crowd_sensing/views/close_campaign_view.dart'; import 'package:mobile_crowd_sensing/views/create_campaign_form_view.dart'; import 'package:mobile_crowd_sensing/controllers/sourcer_past_campaigns_controller.dart'; import 'package:mobile_crowd_sensing/utils/worker_campaign_data_factory.dart'; @@ -34,8 +32,6 @@ Future main(List args) async { } else { runApp(const MyApp()); } - // WalletConnectSession? s = - // await SessionModel().connector.sessionStorage?.getSession(); } class NoConnection extends StatelessWidget { @@ -145,8 +141,6 @@ class _MyAppState extends State { '/sourcer_campaigns_provider': (context) => const MyCampaignView(), '/sourcer_close_campaign_provider': (context) => const SourcerPastCampaignsController(), - '/sourcer_close_campaign_service_provider': (context) => - const CloseCampaignView(), '/wallet': (context) => const WalletView(), '/join_campaign': (context) => JoinCampaignFactory.fromTypeName(context), diff --git a/lib/models/close_campaign_model.dart b/lib/models/close_campaign_model.dart index 951f31c..14f1b6b 100644 --- a/lib/models/close_campaign_model.dart +++ b/lib/models/close_campaign_model.dart @@ -1,10 +1,5 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_config/flutter_config.dart'; -import 'package:mobile_crowd_sensing/controllers/close_campaign_controller.dart'; import 'smart_contract_model.dart'; import 'session_model.dart'; -import '../views/dialog_view.dart'; class CloseCampaignModel { static Future closeMyCampaign(String address) async { diff --git a/lib/views/close_campaign_view.dart b/lib/views/close_campaign_view.dart deleted file mode 100644 index d32fd39..0000000 --- a/lib/views/close_campaign_view.dart +++ /dev/null @@ -1,39 +0,0 @@ -import 'dart:convert'; -import 'package:flutter/material.dart'; -import '../controllers/close_campaign_controller.dart'; - - -class CloseCampaignView extends StatefulWidget { - const CloseCampaignView({super.key}); - @override - // ignore: library_private_types_in_public_api - _CloseCampaignViewState createState() => _CloseCampaignViewState(); -} - -class _CloseCampaignViewState extends State { - Object? parameters; - dynamic jsonParameters = {}; - - @override - Widget build(BuildContext context) { - parameters = ModalRoute.of(context)!.settings.arguments; - jsonParameters = jsonDecode(jsonEncode(parameters)); - return CloseCampaignController(address: jsonParameters['address'],); - } - - -} - - - - - - - - - - - - - - From 130883be17fac243b48ff7b0fcc81d09fef9092b Mon Sep 17 00:00:00 2001 From: Giacomo Date: Fri, 3 Feb 2023 16:19:19 +0100 Subject: [PATCH 14/34] geofence --- lib/models/db_capaign_model.dart | 2 - lib/models/login_metamask_model.dart | 20 +++--- lib/services/geofencing.dart | 6 +- lib/services/geofencing_controller.dart | 13 +++- lib/services/services.dart | 93 +++++++++++++------------ pubspec.lock | 8 --- pubspec.yaml | 1 - 7 files changed, 73 insertions(+), 70 deletions(-) diff --git a/lib/models/db_capaign_model.dart b/lib/models/db_capaign_model.dart index 1f81be6..647db91 100644 --- a/lib/models/db_capaign_model.dart +++ b/lib/models/db_capaign_model.dart @@ -3,8 +3,6 @@ import 'package:mobile_crowd_sensing/services/services_controller.dart'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; -import '../services/closed_campaign_service.dart'; - class DbCampaignModel { static final DbCampaignModel _instance = DbCampaignModel._internal(); diff --git a/lib/models/login_metamask_model.dart b/lib/models/login_metamask_model.dart index 27e1a7e..87cfbc6 100644 --- a/lib/models/login_metamask_model.dart +++ b/lib/models/login_metamask_model.dart @@ -32,16 +32,16 @@ class LoginMetamaskModel { if(!ServicesController.statusGeofencingService) { print('\x1B[31m [GEOFENCE SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); - //await ClosedCampaignService().initializeClosedCampaignService(); - // DEBUG - // await DbCampaignModel().insertCampaign( - // const Campaign( - // title: "testing campaign", - // lat: "44.3883014", - // lng: "11.3467744", - // radius: "17", - // address: "0x000000000000") - // ); + // await ClosedCampaignService().initializeClosedCampaignService(); + //DEBUG + await DbCampaignModel().insertCampaign( + const Campaign( + title: "testing campaign", + lat: "44.3883014", + lng: "11.3467744", + radius: "17", + address: "0x000000000000") + ); ServicesController.initializeGeofencingService(); } diff --git a/lib/services/geofencing.dart b/lib/services/geofencing.dart index 987204f..eb45930 100644 --- a/lib/services/geofencing.dart +++ b/lib/services/geofencing.dart @@ -76,9 +76,9 @@ class Geofencing { _previusStatus = _status; } - if (kDebugMode) { - print("STATUS GEOFENCE: $_status IS CHANGED: $isStatusChanged"); - } + // if (kDebugMode) { + // print("STATUS GEOFENCE: $_status IS CHANGED: $isStatusChanged"); + // } } GeofenceStatus getStatus() { diff --git a/lib/services/geofencing_controller.dart b/lib/services/geofencing_controller.dart index ae58fbe..66c20f1 100644 --- a/lib/services/geofencing_controller.dart +++ b/lib/services/geofencing_controller.dart @@ -1,7 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:mobile_crowd_sensing/models/db_capaign_model.dart'; - -import 'Geofencing.dart'; +import 'package:mobile_crowd_sensing/services/geofencing.dart'; class GeofencingController { final List _activeGeofencing = []; @@ -46,6 +45,16 @@ class GeofencingController { return _activeGeofencing; } + List> getStreamList() { + List> out = []; + for(Geofencing g in _activeGeofencing) { + if(g.getGeofenceStream() != null) { + out.add(g.getGeofenceStream()!); + } + } + return out; + } + Future initializeFromDB() async { DbCampaignModel db = DbCampaignModel(); List res = await db.campaigns(); diff --git a/lib/services/services.dart b/lib/services/services.dart index ae7f4a5..71913e2 100644 --- a/lib/services/services.dart +++ b/lib/services/services.dart @@ -128,59 +128,64 @@ class Services { ?.createNotificationChannel(NotificationChannel.importantChannel); GeofencingController controller = GeofencingController(); - Timer.periodic(const Duration(seconds: 5), (timer) async { + //Timer.periodic(const Duration(seconds: 5), (timer) async { ServicesController.statusGeofencingService = true; - controller.initializeFromDB(); + await controller.initializeFromDB(); print('\x1B[31m [GEOFENCING SERVICE] DEBUG: numero di geofencing attivi ${controller.getNumberOfActiveGeofence()} \x1B[0m'); - + + List> streamList = controller.getStreamList(); if (controller.getNumberOfActiveGeofence() > 0) { - for (Geofencing g in controller.getListOfActiveGeofences()) { - print('\x1B[31m [GEOFENCING SERVICE] DEBUG: ${g.isStatusChanged} \x1B[0m'); - if (g.isStatusChanged) { - switch (g.getStatus()) { - case GeofenceStatus.init: - print( - '\x1B[31m [GEOFENCING SERVICE] enter in Init state. \x1B[0m'); - break; - case GeofenceStatus.enter: - notification.show( - 888, - 'Enter in a Campaign Area', - 'inside the area', - const NotificationDetails( - android: AndroidNotificationDetails( - 'important_channel', - 'MY FOREGROUND SERVICE', - icon: 'ic_bg_service_small', - ongoing: false, - ), - ), - ); - break; - case GeofenceStatus.exit: - notification.show( - 888, - 'Exit from Campaign Area', - 'inside the area', - const NotificationDetails( - android: AndroidNotificationDetails( - 'important_channel', - 'MY FOREGROUND SERVICE', - icon: 'ic_bg_service_small', - ongoing: false, - )) - ); - break; - } - } + for (Stream s in streamList) { + s.listen((GeofenceStatus status) { + print(status.toString()); + // if (g.isStatusChanged) { + // switch (g.getStatus()) { + // case GeofenceStatus.init: + // print( + // '\x1B[31m [GEOFENCING SERVICE] enter in Init state. \x1B[0m'); + // break; + // case GeofenceStatus.enter: + // notification.show( + // 888, + // 'Enter in a Campaign Area', + // 'inside the area', + // const NotificationDetails( + // android: AndroidNotificationDetails( + // 'important_channel', + // 'MY FOREGROUND SERVICE', + // icon: 'ic_bg_service_small', + // ongoing: false, + // ), + // ), + // ); + // break; + // case GeofenceStatus.exit: + // notification.show( + // 888, + // 'Exit from Campaign Area', + // 'inside the area', + // const NotificationDetails( + // android: AndroidNotificationDetails( + // 'important_channel', + // 'MY FOREGROUND SERVICE', + // icon: 'ic_bg_service_small', + // ongoing: false, + // )) + // ); + // break; + // } + // } + // } + }); } } else { ServicesController.statusGeofencingService = false; - timer.cancel(); + //timer.cancel(); print('\x1B[31m [GEOFENCING SERVICE] No campaigns to follow. stop the service.\x1B[0m'); } - }); + //controller.closeAllGeofencing(); + //}); } } diff --git a/pubspec.lock b/pubspec.lock index 69dc779..86ace8e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -337,14 +337,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.6" - easy_geofencing: - dependency: "direct main" - description: - name: easy_geofencing - sha256: "27f3e06988fd6653ec8a7e65a08d006d8106a2b0301a890a87cd9a2132fdc00e" - url: "https://pub.dev" - source: hosted - version: "0.2.0" eip1559: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 6299204..86966fd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -69,7 +69,6 @@ dependencies: flip_card: ^0.7.0 connectivity: ^3.0.6 flutter_isolate: ^2.0.4 - easy_geofencing: ^0.2.0 dev_dependencies: flutter_test: From f81670dee5b70220ca5e5bed787de7c9e5eabde0 Mon Sep 17 00:00:00 2001 From: Giacomo Galletti Date: Sun, 5 Feb 2023 15:40:56 +0100 Subject: [PATCH 15/34] geofence fix --- lib/models/db_capaign_model.dart | 11 +- lib/models/login_metamask_model.dart | 16 +- lib/models/search_places_model.dart | 12 +- lib/services/closed_campaign_service.dart | 273 ---------- lib/services/geofencing.dart | 105 ---- lib/services/geofencing_controller.dart | 74 --- lib/services/services.dart | 197 +++---- lib/services/services_controller.dart | 28 +- pubspec.lock | 633 ++++++++-------------- pubspec.yaml | 1 + 10 files changed, 363 insertions(+), 987 deletions(-) delete mode 100644 lib/services/closed_campaign_service.dart delete mode 100644 lib/services/geofencing.dart delete mode 100644 lib/services/geofencing_controller.dart diff --git a/lib/models/db_capaign_model.dart b/lib/models/db_capaign_model.dart index 647db91..8572b8b 100644 --- a/lib/models/db_capaign_model.dart +++ b/lib/models/db_capaign_model.dart @@ -43,15 +43,7 @@ class DbCampaignModel { conflictAlgorithm: ConflictAlgorithm.replace, ); - if(ServicesController.statusGeofencingService) { - print('\x1B[31m [GEOFENCING SERVICE] INITIALIZE AFTER INSERT IN DB\x1B[0m'); - ServicesController.initializeGeofencingService(); - } - if(ServicesController.statusCloseCampaignService) { - print('\x1B[31m [CLOSED CAMPAIGN SERVICE] INITIALIZE AFTER INSERT IN DB\x1B[0m'); - //await ClosedCampaignService().initializeClosedCampaignService(); - ServicesController.initializeCloseCampaignService(); - } + ServicesController.resetServicies(); } Future> campaigns() async { @@ -86,6 +78,7 @@ class DbCampaignModel { where: 'address = ?', whereArgs: [address], ); + ServicesController.resetServicies(); } } diff --git a/lib/models/login_metamask_model.dart b/lib/models/login_metamask_model.dart index 87cfbc6..7c6c98b 100644 --- a/lib/models/login_metamask_model.dart +++ b/lib/models/login_metamask_model.dart @@ -1,12 +1,11 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:mobile_crowd_sensing/models/db_capaign_model.dart'; +import 'package:mobile_crowd_sensing/models/search_places_model.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; -import 'package:mobile_crowd_sensing/services/geofencing_controller.dart'; import 'package:mobile_crowd_sensing/services/services_controller.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher_string.dart'; -import '../services/closed_campaign_service.dart'; class LoginMetamaskModel { @@ -32,22 +31,13 @@ class LoginMetamaskModel { if(!ServicesController.statusGeofencingService) { print('\x1B[31m [GEOFENCE SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); - // await ClosedCampaignService().initializeClosedCampaignService(); - //DEBUG - await DbCampaignModel().insertCampaign( - const Campaign( - title: "testing campaign", - lat: "44.3883014", - lng: "11.3467744", - radius: "17", - address: "0x000000000000") - ); + SearchPlacesModel search = SearchPlacesModel(); + await search.getPermissions(); ServicesController.initializeGeofencingService(); } if(!ServicesController.statusCloseCampaignService) { print('\x1B[31m [CLOSED CAMPAIGN SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); - //await ClosedCampaignService().initializeClosedCampaignService(); ServicesController.initializeCloseCampaignService(); } diff --git a/lib/models/search_places_model.dart b/lib/models/search_places_model.dart index 3984a8e..cf00e4a 100644 --- a/lib/models/search_places_model.dart +++ b/lib/models/search_places_model.dart @@ -9,7 +9,8 @@ class SearchPlacesModel { String address = ""; late Position position; var client = http.Client(); - + bool serviceEnabled = false; + late LocationPermission permission; Future updateLocalPosition() async { await Future.delayed(Duration(seconds: 1)); @@ -22,10 +23,7 @@ class SearchPlacesModel { } } - Future _getGeoLocationPosition() async { - bool serviceEnabled; - LocationPermission permission; - + Future getPermissions() async { serviceEnabled = await Geolocator.isLocationServiceEnabled(); if (!serviceEnabled) { await Geolocator.openLocationSettings(); @@ -44,7 +42,11 @@ class SearchPlacesModel { return Future.error( 'Location permissions are permanently denied, we cannot request permissions.'); } + return true; + } + Future _getGeoLocationPosition() async { + getPermissions(); return await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.best); } diff --git a/lib/services/closed_campaign_service.dart b/lib/services/closed_campaign_service.dart deleted file mode 100644 index 0a88053..0000000 --- a/lib/services/closed_campaign_service.dart +++ /dev/null @@ -1,273 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_local_notifications/flutter_local_notifications.dart'; -import 'package:http/http.dart' as http; -import 'package:mobile_crowd_sensing/services/geofencing.dart'; -import 'package:mobile_crowd_sensing/services/notification_channels.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:web3dart/contracts.dart'; -import 'package:web3dart/credentials.dart'; -import 'package:web3dart/web3dart.dart'; -import '../models/db_capaign_model.dart'; -import 'dart:async'; -import 'dart:ui'; -import 'package:flutter_background_service/flutter_background_service.dart'; -import 'package:flutter_background_service_android/flutter_background_service_android.dart'; - -class ClosedCampaignService { - static final ClosedCampaignService _instance = - ClosedCampaignService._internal(); - - static late bool isInitialized; - - void setIsInizialized(bool status) { - ClosedCampaignService.isInitialized = status; - } - - bool checkIfInitialized() { - return ClosedCampaignService.isInitialized; - } - - factory ClosedCampaignService() { - return _instance; - } - - ClosedCampaignService._internal() { - ClosedCampaignService.isInitialized = false; - } - - static void onStart(ServiceInstance service) async { - DartPluginRegistrant.ensureInitialized(); - DbCampaignModel db = DbCampaignModel(); - List res = []; - - SharedPreferences shared = await SharedPreferences.getInstance(); - String? accountAddress = shared.getString('address'); - - //List geofencingList = []; - - final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = - FlutterLocalNotificationsPlugin(); - - Timer.periodic(const Duration(seconds: 10), (timer) async { - res = await db.campaigns(); - //geofencingList.clear(); - - SmartContractModelBs smartContract; - if (kDebugMode) { - print( - '\x1B[31m[CLOSED CAMPAIGN SERVICE]check db. IS EMPTY? ${res.isEmpty} \x1B[0m'); - } - if (res.isNotEmpty) { - int counter = 0; - for (Campaign c in res) { - Geofencing g = Geofencing( - id: c.address, - pointedLatitude: c.lat, - pointedLongitude: c.lng, - radiusMeter: c.radius); - - switch (g.getStatus()) { - case GeofenceStatus.init: - print('\x1B[31m [GEOFENCE] status: Init\x1B[0m'); - break; - case GeofenceStatus.enter: - print('\x1B[31m [GEOFENCE] status: Enter\x1B[0m'); - flutterLocalNotificationsPlugin.show( - 888, - 'Entered in Campaign Area', - '[${c.title}] \nat address: ${c.address}', - const NotificationDetails( - android: AndroidNotificationDetails( - 'important_channel', - 'MY FOREGROUND SERVICE', - icon: 'ic_bg_service_small', - ongoing: true, - ), - ), - ); - break; - case GeofenceStatus.exit: - print('\x1B[31m [GEOFENCE] status: Exit\x1B[0m'); - flutterLocalNotificationsPlugin.show( - 888, - 'Exit from Campaign Area', - '[${c.title}] \nat address: ${c.address}', - const NotificationDetails( - android: AndroidNotificationDetails( - 'important_channel', - 'MY FOREGROUND SERVICE', - icon: 'ic_bg_service_small', - ongoing: true, - ), - )); - break; - default: - print( - '\x1B[31m [GEOFENCE] status DEFAULT Exit: ${g.getStatus()}\x1B[0m'); - break; - } - - g.stopGeofenceService(); - - if (accountAddress == null) { - throw Error(); - } - String address = c.address; - String title = c.title; - - smartContract = SmartContractModelBs( - contractAddress: address, - abiName: 'Campaign', - abiFileRoot: 'assets/abi_campaign.json', - accountAddress: accountAddress); - - List? isClosedRaw = - await smartContract.queryCall('isClosed', []); - if (isClosedRaw != null) { - String answer = isClosedRaw[0].toString(); - - if (answer == "true") { - // the campaign result closed - if (kDebugMode) { - print('\x1B[31mThe campaign was closed\x1B[0m'); - } - if (service is AndroidServiceInstance) { - if (await service.isForegroundService()) { - flutterLocalNotificationsPlugin.show( - 888, - 'Campaign Closed', - 'The campaign [$title] \nat address $address \n was closed by crowdsourcer', - const NotificationDetails( - android: AndroidNotificationDetails( - 'important_channel', - 'MY FOREGROUND SERVICE', - icon: 'ic_bg_service_small', - ongoing: true, - ), - ), - ); - } - } - await db.deleteCampaign(address); - } else { - print( - '\x1B[31mThe campaign still open: nothing to notify\x1B[0m'); - } - } else { - return Future.error(StackTrace); - } - - counter++; - } - if (kDebugMode) { - print( - "\n [CLOSED CAMPAIGN SERVICE]registered : $counter periodic Tasks\n"); - } - } else { - if (kDebugMode) { - print( - '\x1B[31m [CLOSED CAMPAIGN SERVICE] No campaigns to follow. stop the service.\x1B[0m'); - } - ClosedCampaignService().setIsInizialized(false); - print( - '\x1B[31m[DEBUG CANCELLAZIONE SERVIZIO]${ClosedCampaignService().checkIfInitialized()}\x1B[0m'); - timer.cancel(); - service.stopSelf(); - } - }); - - print('\x1B[31m[GEOFENCE SERVICE] try to execute the service\x1B[0m'); - } - - Future initializeClosedCampaignService() async { - ClosedCampaignService().setIsInizialized(true); - DbCampaignModel db = DbCampaignModel(); - List res = await db.campaigns(); - if (res.isNotEmpty) { - print( - '\x1B[31m [CLOSED CAMPAIGN SERVICE]Initialize service [CLOSED CAMPAIGN]\x1B[0m'); - - final service = FlutterBackgroundService(); - - final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = - FlutterLocalNotificationsPlugin(); - - await flutterLocalNotificationsPlugin - .resolvePlatformSpecificImplementation< - AndroidFlutterLocalNotificationsPlugin>() - ?.createNotificationChannel(NotificationChannel.importantChannel); - - await service.configure( - androidConfiguration: AndroidConfiguration( -// this will be executed when app is in foreground or background in separated isolate - onStart: ClosedCampaignService.onStart, - -// auto start service - autoStart: true, - isForegroundMode: true, - - notificationChannelId: 'important_channel', - initialNotificationTitle: 'closing campaign service', - initialNotificationContent: - 'this service notify eventually submitted campaign closed', - foregroundServiceNotificationId: 888, - ), - iosConfiguration: IosConfiguration(), - ); - - service.startService(); - } else { - if (kDebugMode) { - print( - '\x1B[31m [CLOSED CAMPAIGN SERVICE]The database is empty. no services to initialize\x1B[0m'); - } - } - } -} - -class SmartContractModelBs { - SmartContractModelBs( - {required this.accountAddress, - required this.contractAddress, - required this.abiName, - required this.abiFileRoot}); - final String accountAddress; - final String contractAddress; - final String abiName; - final String abiFileRoot; - late http.Client httpClient; - late Web3Client ethClient; - - Future loadContract(String contractAddress) async { - String abi = await rootBundle.loadString(abiFileRoot); - final contract = DeployedContract(ContractAbi.fromJson(abi, abiName), - EthereumAddress.fromHex(contractAddress)); - return contract; - } - - Future?> queryCall( - String functionName, List args) async { - try { - httpClient = http.Client(); - ethClient = Web3Client( - "https://goerli.infura.io/v3/5074605772bb4bc4b6970d2ce999efca", - httpClient); - - final contract = await loadContract(contractAddress); - final ethFunction = contract.function(functionName); - final result = await ethClient.call( - sender: EthereumAddress.fromHex(accountAddress), - contract: contract, - function: ethFunction, - params: args); - List res = result; - return res; - } catch (e) { - if (kDebugMode) { - print('\x1B[31m$e\x1B[0m'); - } - return null; - } - } -} diff --git a/lib/services/geofencing.dart b/lib/services/geofencing.dart deleted file mode 100644 index eb45930..0000000 --- a/lib/services/geofencing.dart +++ /dev/null @@ -1,105 +0,0 @@ -import 'dart:async'; -import 'package:flutter/foundation.dart'; -import 'package:geolocator/geolocator.dart'; - -enum GeofenceStatus { init, enter, exit } - -class Geofencing { - - late final String id, pointedLatitude, pointedLongitude, radiusMeter; - int? eventPeriodInSeconds; - - GeofenceStatus _previusStatus = GeofenceStatus.init; - GeofenceStatus _status = GeofenceStatus.init; - - bool isStatusChanged = false; - - StreamSubscription? _positionStream; - Stream? _geoFencestream; - final StreamController _controller = StreamController(); - - Geofencing({required this.id,required this.pointedLatitude, required this.pointedLongitude, required this.radiusMeter,this.eventPeriodInSeconds}) { - - double latitude = _parser(pointedLatitude); - double longitude = _parser(pointedLongitude); - double radiusInMeter = _parser(radiusMeter); - - if (_positionStream == null) { - _geoFencestream = _controller.stream; - _positionStream = Geolocator.getPositionStream( - desiredAccuracy: LocationAccuracy.high, - ).listen((Position position) { - double distanceInMeters = Geolocator.distanceBetween( - latitude, longitude, position.latitude, position.longitude); - //_printOnConsole(latitude, longitude, position, distanceInMeters, radiusInMeter); - _checkGeofence(distanceInMeters, radiusInMeter); - _positionStream!.pause(Future.delayed(Duration(seconds: (eventPeriodInSeconds != null)? eventPeriodInSeconds! : 2))); - }); - } - } - - double _parser(String? value) { - double doubledValue = 0.0; - - try { - if(value!.isEmpty) { - throw Error(); - } - doubledValue = double.parse(value.isEmpty ? "0" : value); - - } catch (e) { - print("VALUE IS ===> $value ${value?.isEmpty}"); - print("EXCEPTION DOUBLE===> $e"); - } - return doubledValue; - } - - _checkGeofence(double distanceInMeters, double radiusInMeter) { - if(_previusStatus == _status) { - isStatusChanged = false; - - if (distanceInMeters <= radiusInMeter) { - _status = GeofenceStatus.enter; - } else { - _status = GeofenceStatus.exit; - } - - } else { - isStatusChanged = true; - - if (distanceInMeters <= radiusInMeter) { - _status = GeofenceStatus.enter; - } else { - _status = GeofenceStatus.exit; - } - - _previusStatus = _status; - } - - // if (kDebugMode) { - // print("STATUS GEOFENCE: $_status IS CHANGED: $isStatusChanged"); - // } - } - - GeofenceStatus getStatus() { - return _status; - } - - stopGeofenceService() { - if (_positionStream != null) { - _positionStream!.cancel(); - } - } - - Stream? getGeofenceStream() { - return _geoFencestream; - } - - // _printOnConsole( - // latitude, longitude, Position position, distanceInMeters, radiusInMeter) { - // print("Started Position $latitude $longitude"); - // print("Current Position ${position.toJson()}"); - // print( - // "Distance in meters $distanceInMeters and Radius in Meter $radiusInMeter"); - // } -} diff --git a/lib/services/geofencing_controller.dart b/lib/services/geofencing_controller.dart deleted file mode 100644 index 66c20f1..0000000 --- a/lib/services/geofencing_controller.dart +++ /dev/null @@ -1,74 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:mobile_crowd_sensing/models/db_capaign_model.dart'; -import 'package:mobile_crowd_sensing/services/geofencing.dart'; - -class GeofencingController { - final List _activeGeofencing = []; - - registerGeofencing(String id, String pointedLatitude, - String pointedLongitude, String radiusMeter) { - _activeGeofencing.add(Geofencing( - id: id, - pointedLatitude: pointedLatitude, - pointedLongitude: pointedLongitude, - radiusMeter: radiusMeter)); - if (kDebugMode) { - print('\x1B[31m [GEOFENCING CONTROLLER] add Geofence id: $id. \x1B[0m'); - } - } - - closeAllGeofencing() { - for (Geofencing g in _activeGeofencing) { - g.stopGeofenceService(); - } - _activeGeofencing.clear(); - - if (kDebugMode) { - print('\x1B[31m [GEOFENCING CONTROLLER] delete all geofencing. \x1B[0m'); - } - } - - getNumberOfActiveGeofence() { - return _activeGeofencing.length; - } - - removeGeofenceFromId(String id) { - Geofencing selected = _activeGeofencing.firstWhere((item) => item.id == id); - selected.stopGeofenceService(); - _activeGeofencing.remove(selected); - if (kDebugMode) { - print('\x1B[31m [GEOFENCING CONTROLLER] delete geofence id: $id \n number of active geofence: ${getNumberOfActiveGeofence()} \x1B[0m'); - } - } - - getListOfActiveGeofences(){ - return _activeGeofencing; - } - - List> getStreamList() { - List> out = []; - for(Geofencing g in _activeGeofencing) { - if(g.getGeofenceStream() != null) { - out.add(g.getGeofenceStream()!); - } - } - return out; - } - - Future initializeFromDB() async { - DbCampaignModel db = DbCampaignModel(); - List res = await db.campaigns(); - - for(Campaign c in res) { - registerGeofencing( - c.address, - c.lat, - c.lng, - c.radius); - } - if (kDebugMode) { - print('\x1B[31m [GEOFENCING CONTROLLER] initialized: ${res.length} campaigns \x1B[0m'); - } - } - -} diff --git a/lib/services/services.dart b/lib/services/services.dart index 71913e2..daa91e1 100644 --- a/lib/services/services.dart +++ b/lib/services/services.dart @@ -1,19 +1,17 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; -import 'package:geolocator/geolocator.dart'; import 'package:http/http.dart' as http; -import 'package:mobile_crowd_sensing/services/geofencing.dart'; -import 'package:mobile_crowd_sensing/services/geofencing_controller.dart'; import 'package:mobile_crowd_sensing/services/notification_channels.dart'; import 'package:mobile_crowd_sensing/services/services_controller.dart'; -import 'package:web3dart/contracts.dart'; -import 'package:web3dart/credentials.dart'; import 'package:web3dart/web3dart.dart'; import '../models/db_capaign_model.dart'; import 'dart:async'; import 'dart:ui'; + +import 'package:geofence_flutter/geofence_flutter.dart'; + class Services { @pragma('vm:entry-point') static void checkCloseCampaign(Map args) async { @@ -72,52 +70,32 @@ class Services { await db.deleteCampaign(address); } else { - print( - '\x1B[31m [CLOSED CAMPAIGN SERVICE] The campaign still open: nothing to notify. \x1B[0m'); + if (kDebugMode) { + print('\x1B[31m [CLOSED CAMPAIGN SERVICE] The campaign still open: nothing to notify. \x1B[0m'); + } } } else { - print( + if (kDebugMode) { + print( '\x1B[31m [CLOSED CAMPAIGN SERVICE]an error occurred. \x1B[0m'); + } } } } else { ServicesController.statusCloseCampaignService = false; timer.cancel(); - print( + if (kDebugMode) { + print( '\x1B[31m [CLOSED CAMPAIGN SERVICE] No campaigns to follow. stop the service.\x1B[0m'); + } } }); } @pragma('vm:entry-point') - static void checkGeofence(Map args) async { + static void checkGeofence(Map args) async { DartPluginRegistrant.ensureInitialized(); - //.... - - bool serviceEnabled; - LocationPermission permission; - - serviceEnabled = await Geolocator.isLocationServiceEnabled(); - if (!serviceEnabled) { - await Geolocator.openLocationSettings(); - return Future.error('Location services are disabled.'); - } - - permission = await Geolocator.checkPermission(); - if (permission == LocationPermission.denied) { - permission = await Geolocator.requestPermission(); - if (permission == LocationPermission.denied) { - return Future.error('Location permissions are denied'); - } - } - - if (permission == LocationPermission.deniedForever) { - return Future.error( - 'Location permissions are permanently denied, we cannot request permissions.'); - } - - - //.... + String debugString = "[GEOFENCE ${args["title"]!}"; final FlutterLocalNotificationsPlugin notification = FlutterLocalNotificationsPlugin(); @@ -127,65 +105,94 @@ class Services { AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(NotificationChannel.importantChannel); - GeofencingController controller = GeofencingController(); - //Timer.periodic(const Duration(seconds: 5), (timer) async { - ServicesController.statusGeofencingService = true; - - await controller.initializeFromDB(); - print('\x1B[31m [GEOFENCING SERVICE] DEBUG: numero di geofencing attivi ${controller.getNumberOfActiveGeofence()} \x1B[0m'); - - List> streamList = controller.getStreamList(); - if (controller.getNumberOfActiveGeofence() > 0) { - for (Stream s in streamList) { - s.listen((GeofenceStatus status) { - print(status.toString()); - // if (g.isStatusChanged) { - // switch (g.getStatus()) { - // case GeofenceStatus.init: - // print( - // '\x1B[31m [GEOFENCING SERVICE] enter in Init state. \x1B[0m'); - // break; - // case GeofenceStatus.enter: - // notification.show( - // 888, - // 'Enter in a Campaign Area', - // 'inside the area', - // const NotificationDetails( - // android: AndroidNotificationDetails( - // 'important_channel', - // 'MY FOREGROUND SERVICE', - // icon: 'ic_bg_service_small', - // ongoing: false, - // ), - // ), - // ); - // break; - // case GeofenceStatus.exit: - // notification.show( - // 888, - // 'Exit from Campaign Area', - // 'inside the area', - // const NotificationDetails( - // android: AndroidNotificationDetails( - // 'important_channel', - // 'MY FOREGROUND SERVICE', - // icon: 'ic_bg_service_small', - // ongoing: false, - // )) - // ); - // break; - // } - // } - // } - }); - } - } else { - ServicesController.statusGeofencingService = false; - //timer.cancel(); - print('\x1B[31m [GEOFENCING SERVICE] No campaigns to follow. stop the service.\x1B[0m'); - } - //controller.closeAllGeofencing(); - //}); + if (kDebugMode) { + print('\x1B[31m [GEOFENCE SERVICE] geofence open for:' + '\n ${args['title']!}' + '\n ${args['address']!}' + '\n ${args['lat']!} ' + '\n ${args['lng']!} \x1B[0m'); + } + + await Geofence.startGeofenceService( + pointedLatitude: args['lat']!, + pointedLongitude: args['lng']!, + radiusMeter: args['radius']!, + eventPeriodInSeconds: 10 + ); + + GeofenceEvent? previous; + + Geofence.getGeofenceStream()?.listen( + (GeofenceEvent event) { + if (kDebugMode) { + print(event.toString()); + } + + if(previous == null || previous == GeofenceEvent.init) { + switch (event) { + case GeofenceEvent.enter: + previous = event; + break; + case GeofenceEvent.exit: + previous = event; + break; + default: + previous = event; + break; + } + } + + switch (event) { + case GeofenceEvent.init: + if (kDebugMode) { + print('\x1B[31m $debugString status: Init\x1B[0m'); + } + previous = event; + break; + case GeofenceEvent.enter: + if (kDebugMode) { + print('\x1B[31m $debugString status: Enter\x1B[0m'); + } + (previous != event)? + notification.show( + 888, + 'Entered in Campaign Area', + '[${args['title']!}] \nat address: ${args['address']!}', + const NotificationDetails( + android: AndroidNotificationDetails( + 'important_channel', + 'MY FOREGROUND SERVICE', + icon: 'ic_bg_service_small', + ongoing: true, + ), + ), + ) + : print('\x1B[31m $debugString status not changed \x1B[0m'); + previous = event; + break; + case GeofenceEvent.exit: + if (kDebugMode) { + print('\x1B[31m $debugString status: Exit\x1B[0m'); + } + (previous != event)? + notification.show( + 888, + 'Exit from Campaign Area', + '[${args['title']!}] \nat address: ${args['address']!}', + const NotificationDetails( + android: AndroidNotificationDetails( + 'important_channel', + 'MY FOREGROUND SERVICE', + icon: 'ic_bg_service_small', + ongoing: true, + ), + )) + : print('\x1B[31m $debugString status not changed \x1B[0m'); + previous = event; + + break; + } + }); } } diff --git a/lib/services/services_controller.dart b/lib/services/services_controller.dart index e01ab88..d32aead 100644 --- a/lib/services/services_controller.dart +++ b/lib/services/services_controller.dart @@ -1,7 +1,7 @@ import 'package:flutter_isolate/flutter_isolate.dart'; -import 'package:mobile_crowd_sensing/services/geofencing_controller.dart'; import 'package:mobile_crowd_sensing/services/services.dart'; +import '../models/db_capaign_model.dart'; import '../models/session_model.dart'; class ServicesController{ @@ -16,8 +16,30 @@ class ServicesController{ statusCloseCampaignService = true; } - static void initializeGeofencingService() async { - FlutterIsolate.spawn(Services.checkGeofence, {}); + static Future initializeGeofencingService() async { + + DbCampaignModel db = DbCampaignModel(); + List res = await db.campaigns(); + if(res.isNotEmpty) { + statusGeofencingService = true; + for(Campaign c in res) { + FlutterIsolate.spawn(Services.checkGeofence, { + 'address' : c.address, + 'title' : c.title, + 'lat' : c.lat, + 'lng' : c.lng, + 'radius' : c.radius + }); + } + } + + } + + static void resetServicies() async { + FlutterIsolate.killAll(); + statusCloseCampaignService = true; statusGeofencingService = true; + initializeCloseCampaignService(); + initializeGeofencingService(); } } \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 86ace8e..cc0d45d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,400 +5,343 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "0c80aeab9bc807ab10022cd3b2f4cf2ecdf231949dc1ddd9442406a003f19201" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "52.0.0" + version: "50.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: cd8ee83568a77f3ae6b913a36093a1c9b1264e7cb7f834d9ddd2311dade9c1f4 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "5.4.0" + version: "5.2.0" archive: dependency: "direct main" description: name: archive - sha256: d6347d54a2d8028e0437e3c099f66fdb8ae02c4720c1e7534c9f24c10351f85d - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.3.6" args: dependency: transitive description: name: args - sha256: "139d809800a412ebb26a3892da228b2d0ba36f0ef5d9a82166e5e52ec8d61611" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.3.2" async: dependency: transitive description: name: async - sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.10.0" + version: "2.9.0" boolean_selector: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.0" build: dependency: transitive description: name: build - sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.3.1" build_config: dependency: transitive description: name: build_config - sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.1.1" build_daemon: dependency: transitive description: name: build_daemon - sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.1.0" build_resolvers: dependency: transitive description: name: build_resolvers - sha256: "7c35a3a7868626257d8aee47b51c26b9dba11eaddf3431117ed2744951416aab" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.0" build_runner: dependency: "direct main" description: name: build_runner - sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.3.3" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "7.2.7" built_collection: dependency: transitive description: name: built_collection - sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "5.1.1" built_value: dependency: transitive description: name: built_value - sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "8.4.3" cached_network_image: dependency: transitive description: name: cached_network_image - sha256: fd3d0dc1d451f9a252b32d95d3f0c3c487bc41a75eba2e6097cb0b9c71491b15 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.2.3" cached_network_image_platform_interface: dependency: transitive description: name: cached_network_image_platform_interface - sha256: bb2b8403b4ccdc60ef5f25c70dead1f3d32d24b9d6117cfc087f496b178594a7 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.0" cached_network_image_web: dependency: transitive description: name: cached_network_image_web - sha256: b8eb814ebfcb4dea049680f8c1ffb2df399e4d03bf7a352c775e26fa06e02fa0 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.2" camera: dependency: "direct main" description: name: camera - sha256: e7ac55af24a890d20276821eb3c95857074d03b7de6f9892b99a205ee30bd179 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.10.3" camera_android: dependency: transitive description: name: camera_android - sha256: "4cef01e8e78fe27c809a429bf74352ab94ab76b0c980e3ec708f1414614e3d9f" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.10.3" + version: "0.10.4" camera_avfoundation: dependency: transitive description: name: camera_avfoundation - sha256: "6a68c20593d4cd58974d555f74a48b244f9db28cc9156de57781122d11b8754b" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.9.11" camera_platform_interface: dependency: transitive description: name: camera_platform_interface - sha256: "0eedd642d905ca24f1c483fe9ea0d0e7287b86a402845c28d24df28cc7b0ee6e" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.3.4" camera_web: dependency: transitive description: name: camera_web - sha256: "496de93c5d462738ce991dbfe91fb19026f115ed36406700a20a380fb0018299" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.3.1+1" characters: dependency: transitive description: name: characters - sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.2.1" checked_yaml: dependency: transitive description: name: checked_yaml - sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.2" clock: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.1.1" code_builder: dependency: transitive description: name: code_builder - sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "4.4.0" collection: dependency: transitive description: name: collection - sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.17.0" + version: "1.16.0" connectivity: dependency: "direct main" description: name: connectivity - sha256: a8e91263cf3e25fb5cc95e19dfde4999e32a648ac3b9e8a558a28165731678f8 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.0.6" connectivity_for_web: dependency: transitive description: name: connectivity_for_web - sha256: "01a390c1d5adc2ed1fa1f52d120c07fe9fd01166a93f965a832fd6cfc0ea6482" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.4.0+1" connectivity_macos: dependency: transitive description: name: connectivity_macos - sha256: "51ae08d5162eca9669b9d8951ed83ce19c5355a81149f94e4dee2740beb93628" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.2.1+2" connectivity_platform_interface: dependency: transitive description: name: connectivity_platform_interface - sha256: "2d82e942df9d49f29a24bb07fb5ce085d4a53e47818c62364d2b6deb9e0d7a8e" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.1" convert: dependency: transitive description: name: convert - sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.1.1" cross_file: dependency: transitive description: name: cross_file - sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.3.3+4" crypto: dependency: transitive description: name: crypto - sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.0.2" cryptography: dependency: transitive description: name: cryptography - sha256: e0e37f79665cd5c86e8897f9abe1accfe813c0cc5299dab22256e22fddc1fef8 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.5" csslib: dependency: transitive description: name: csslib - sha256: b36c7f7e24c0bdf1bf9a3da461c837d1de64b9f8beb190c9011d8c72a3dfd745 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.17.2" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.5" dart_style: dependency: transitive description: name: dart_style - sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.2.4" dbus: dependency: transitive description: name: dbus - sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.7.8" device_info_plus: dependency: "direct main" description: name: device_info_plus - sha256: "7ff671ed0a6356fa8f2e1ae7d3558d3fb7b6a41e24455e4f8df75b811fb8e4ab" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "8.0.0" device_info_plus_platform_interface: dependency: transitive description: name: device_info_plus_platform_interface - sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "7.0.0" dio: dependency: transitive description: name: dio - sha256: "7d328c4d898a61efc3cd93655a0955858e29a0aa647f0f9e02d59b3bb275e2e8" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "4.0.6" - eip1559: - dependency: transitive - description: - name: eip1559 - sha256: de454d6321bd753eb79116e9ec4f8df20895c2e97f9a3839a032f3a728985516 - url: "https://pub.dev" - source: hosted - version: "0.6.1" eip55: dependency: transitive description: name: eip55 - sha256: "213a9b86add87a5216328e8494b0ab836e401210c4d55eb5e521bd39e39169e1" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.2" environment_sensors: dependency: "direct main" description: name: environment_sensors - sha256: "814c78232a2043762cb015bebd90b51cb95a37e6c636a91189f9193eabbddf78" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.2.0" fake_async: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.3.1" ffi: dependency: transitive description: name: ffi - sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.1" file: dependency: transitive description: name: file - sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "6.1.4" fixnum: dependency: transitive description: name: fixnum - sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.0.1" flip_card: dependency: "direct main" description: name: flip_card - sha256: "5d4aa58f3983cced0782f4ce45826b7eea36e8e464964d9209dcbc7a87b2292f" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.7.0" flutter: @@ -410,144 +353,126 @@ packages: dependency: "direct main" description: name: flutter_background_service - sha256: "7b9f15ab7d1a5784850ecfde722be4ace4dbcf1072a1fe33b7f9cbe871241e53" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.4.6" flutter_background_service_android: dependency: transitive description: name: flutter_background_service_android - sha256: "57fd631d800f7e56ca5bfadcfc00c8903eb721b23506b1a387342039521883ec" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.0.3" flutter_background_service_ios: dependency: transitive description: name: flutter_background_service_ios - sha256: d3f1dc009137c1ac19f5e3d88668836f088a7e078396733547339765d46ff12f - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.4.0" flutter_background_service_platform_interface: dependency: transitive description: name: flutter_background_service_platform_interface - sha256: "5f0480ee8378984f718d640abbe09b4d6d024d58a72b2d8b86bdedb3cf095ff8" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.2.0" flutter_blurhash: dependency: transitive description: name: flutter_blurhash - sha256: "05001537bd3fac7644fa6558b09ec8c0a3f2eba78c0765f88912882b1331a5c6" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.7.0" flutter_cache_manager: dependency: transitive description: name: flutter_cache_manager - sha256: "32cd900555219333326a2d0653aaaf8671264c29befa65bbd9856d204a4c9fb3" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.3.0" flutter_config: dependency: "direct main" description: name: flutter_config - sha256: "8e2be2d560a52e06d2ef53a31913a11fc80ef708a442571c96194fd32e29fb1a" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.0" flutter_foreground_task: dependency: "direct main" description: name: flutter_foreground_task - sha256: "5eb81adfd98c77f4d4803ae80d7e0573fd35f706fce6aaa7376656a15ba2d1e0" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.10.0" flutter_intl: dependency: "direct main" description: name: flutter_intl - sha256: "17b138fab0477c7d17abd8ba67d294786eef8fe80342e58b6253aef7d0ca2bad" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.0.1" flutter_isolate: dependency: "direct main" description: name: flutter_isolate - sha256: "994ddec596da4ca12ca52154fd59404077584643eb7e3f1008a55fda9fe0b76b" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.4" flutter_lints: dependency: "direct dev" description: name: flutter_lints - sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.1" flutter_local_notifications: dependency: "direct main" description: name: flutter_local_notifications - sha256: "293995f94e120c8afce768981bd1fa9c5d6de67c547568e3b42ae2defdcbb4a0" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "13.0.0" flutter_local_notifications_linux: dependency: transitive description: name: flutter_local_notifications_linux - sha256: "8f6c1611e0c4a88a382691a97bb3c3feb24cc0c0b54152b8b5fb7ffb837f7fbf" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.0.0" flutter_local_notifications_platform_interface: dependency: transitive description: name: flutter_local_notifications_platform_interface - sha256: "5ec1feac5f7f7d9266759488bc5f76416152baba9aa1b26fe572246caa00d1ab" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "6.0.0" flutter_map: dependency: transitive description: name: flutter_map - sha256: "59dfd14267b691bea55760786b47d3172d47cdcc0d79ff930746a5ad123491b8" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.1.0" flutter_native_splash: dependency: "direct main" description: name: flutter_native_splash - sha256: "048bd1f1dc0e5ea25899f702815934d9a9e916fe23451c320e7dd94d5e3ad933" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.2.17" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "60fc7b78455b94e6de2333d2f95196d32cf5c22f4b0b0520a628804cb463503b" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.7" flutter_spinkit: dependency: "direct main" description: name: flutter_spinkit - sha256: "77a2117c0517ff909221f3160b8eb20052ab5216107581168af574ac1f05dff8" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "5.1.0" flutter_test: @@ -564,608 +489,546 @@ packages: dependency: transitive description: name: frontend_server_client - sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.2.0" geocoding: dependency: "direct main" description: name: geocoding - sha256: "26218460a902d4249b81e6baf9d55ce400fd1ebe6fc0a7e92b2c12b0b8e1e14e" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.5" geocoding_platform_interface: dependency: transitive description: name: geocoding_platform_interface - sha256: "8848605d307d844d89937cdb4b8ad7dfa880552078f310fa24d8a460f6dddab4" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.1" + geofence_flutter: + dependency: "direct main" + description: + name: geofence_flutter + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" geolocator: dependency: "direct main" description: name: geolocator - sha256: b8f520252c5c66851295bcc263bc8ae7555501938427f72216ba7688702e261d - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "7.7.1" + version: "9.0.2" geolocator_android: dependency: transitive description: name: geolocator_android - sha256: "2f84d6d68b97a3774f2c4111ac95ec5898cd9b98f12193fc3ea7fa21d7a8b46c" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "4.1.7" geolocator_apple: dependency: transitive description: name: geolocator_apple - sha256: "1e8e398cc92151d946a4bbd34e2075885333e42d35ca33e418e7ce7b0a29991e" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.2.2" + version: "2.2.5" geolocator_platform_interface: dependency: transitive description: name: geolocator_platform_interface - sha256: "9d6f34a8a4b704d504f34acc5e52d880a7d2caedd99739902d6319179b0336d4" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.3.6" + version: "4.0.7" geolocator_web: dependency: transitive description: name: geolocator_web - sha256: "0b9e0ec13ce2211085cae0055b3516c975bd6cfe2878a20c8f13611f1a259855" - url: "https://pub.dev" + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.6" + geolocator_windows: + dependency: transitive + description: + name: geolocator_windows + url: "https://pub.dartlang.org" source: hosted - version: "2.0.6" + version: "0.1.1" glob: dependency: transitive description: name: glob - sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.1" google_fonts: dependency: "direct main" description: name: google_fonts - sha256: "8f099045e2f2a30e4d4d0a35f40c6bc941a8f2ca0e10ad9d214ee9edd3f37483" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.0.1" graphs: dependency: transitive description: name: graphs - sha256: f9e130f3259f52d26f0cfc0e964513796dafed572fa52e45d2f8d6ca14db39b2 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.2.0" html: dependency: transitive description: name: html - sha256: d9793e10dbe0e6c364f4c59bf3e01fb33a9b2a674bc7a1081693dba0614b6269 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.15.1" http: dependency: "direct main" description: name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.13.5" http_multi_server: dependency: transitive description: name: http_multi_server - sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.2.1" http_parser: dependency: transitive description: name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "4.0.2" image: dependency: transitive description: name: image - sha256: "3686865febd85c57a632d87a0fb1f0a8a9ef602fdb68d909c3e9aa29ec70fd24" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "4.0.13" infinite_listview: dependency: transitive description: name: infinite_listview - sha256: f6062c1720eb59be553dfa6b89813d3e8dd2f054538445aaa5edaddfa5195ce6 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.1.0" intl: dependency: "direct main" description: name: intl - sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.17.0" io: dependency: transitive description: name: io - sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.4" ipfs_client_flutter: dependency: "direct main" description: name: ipfs_client_flutter - sha256: e9ec8c3b33af20240cdfcb1316ef0804be68d5237df65a82ff3f3a2cfc2fd497 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.7" js: dependency: transitive description: name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.6.5" + version: "0.6.4" json_annotation: dependency: transitive description: name: json_annotation - sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "4.8.0" json_rpc_2: dependency: transitive description: name: json_rpc_2 - sha256: "5e469bffa23899edacb7b22787780068d650b106a21c76db3c49218ab7ca447e" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.0.2" latlong2: dependency: transitive description: name: latlong2 - sha256: "408993a0e3f46e79ce1f129e4cb0386eef6d48dfa6394939ecacfbd7049154ec" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.8.1" lints: dependency: transitive description: name: lints - sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.1" lists: dependency: transitive description: name: lists - sha256: "4ca5c19ae4350de036a7e996cdd1ee39c93ac0a2b840f4915459b7d0a7d4ab27" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.1" logging: dependency: transitive description: name: logging - sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.1.1" matcher: dependency: transitive description: name: matcher - sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.12.13" + version: "0.12.12" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.2.0" + version: "0.1.5" meta: dependency: transitive description: name: meta - sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.8.0" mgrs_dart: dependency: transitive description: name: mgrs_dart - sha256: fb89ae62f05fa0bb90f70c31fc870bcbcfd516c843fb554452ab3396f78586f7 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.0" mime: dependency: transitive description: name: mime - sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.4" numberpicker: dependency: "direct main" description: name: numberpicker - sha256: "73723bd13c940ebcd9e5f0ed56b4874588c1748a9a6a38254f97ad627715142e" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.1" octo_image: dependency: transitive description: name: octo_image - sha256: "107f3ed1330006a3bea63615e81cf637433f5135a52466c7caa0e7152bca9143" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.2" open_street_map_search_and_pick: dependency: "direct main" description: name: open_street_map_search_and_pick - sha256: "806c24b042b01658be0d083f34e9b43563ab6c0a49f4583b10e6b36b41f59167" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.0.15" package_config: dependency: transitive description: name: package_config - sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.0" path: dependency: "direct main" description: name: path - sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.8.2" path_provider: dependency: "direct main" description: name: path_provider - sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.12" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.22" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.7" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.5" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.3" pedantic: dependency: transitive description: name: pedantic - sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.11.1" permission_handler: dependency: "direct main" description: name: permission_handler - sha256: "33c6a1253d1f95fd06fa74b65b7ba907ae9811f9d5c1d3150e51417d04b8d6a8" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "10.2.0" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: "8028362b40c4a45298f1cbfccd227c8dd6caf0e27088a69f2ba2ab15464159e2" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "10.2.0" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - sha256: "9c370ef6a18b1c4b2f7f35944d644a56aa23576f23abee654cf73968de93f163" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "9.0.7" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - sha256: "68abbc472002b5e6dfce47fe9898c6b7d8328d58b5d2524f75e277c07a97eb84" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.9.0" permission_handler_windows: dependency: transitive description: name: permission_handler_windows - sha256: f67cab14b4328574938ecea2db3475dad7af7ead6afab6338772c5f88963e38b - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.1.2" petitparser: dependency: transitive description: name: petitparser - sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "5.1.0" platform: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.3" pointycastle: dependency: transitive description: name: pointycastle - sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.6.2" polylabel: dependency: transitive description: name: polylabel - sha256: "41b9099afb2aa6c1730bdd8a0fab1400d287694ec7615dd8516935fa3144214b" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.1" pool: dependency: transitive description: name: pool - sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.5.1" positioned_tap_detector_2: dependency: transitive description: name: positioned_tap_detector_2 - sha256: "52e06863ad3e1f82b058fd05054fc8c9caeeb3b47d5cea7a24bd9320746059c1" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.4" process: dependency: transitive description: name: process - sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "4.2.4" proj4dart: dependency: transitive description: name: proj4dart - sha256: c8a659ac9b6864aa47c171e78d41bbe6f5e1d7bd790a5814249e6b68bc44324e - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.0" pub_semver: dependency: transitive description: name: pub_semver - sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.3" pubspec_parse: dependency: transitive description: name: pubspec_parse - sha256: "75f6614d6dde2dc68948dffbaa4fe5dae32cd700eb9fb763fe11dfb45a3c4d0a" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.2.1" qr: dependency: transitive description: name: qr - sha256: "5c4208b4dc0d55c3184d10d83ee0ded6212dc2b5e2ba17c5a0c0aab279128d21" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.0" qr_flutter: dependency: transitive description: name: qr_flutter - sha256: c5c121c54cb6dd837b9b9d57eb7bc7ec6df4aee741032060c8833a678c80b87e - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "4.0.0" quiver: dependency: transitive description: name: quiver - sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.2.1" rxdart: dependency: transitive description: name: rxdart - sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.27.7" sec: dependency: transitive description: name: sec - sha256: "78e2ed80b8782fe03496ff3c626d5f6139efbe00c577327c613ad8540ea4b14a" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.1" shared_preferences: dependency: "direct main" description: name: shared_preferences - sha256: "5949029e70abe87f75cfe59d17bf5c397619c4b74a099b10116baeb34786fad9" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.17" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "955e9736a12ba776bdd261cf030232b30eadfcd9c79b32a3250dd4a494e8c8f7" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.15" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "2b55c18636a4edc529fa5cd44c03d3f3100c00513f518c5127c951978efcccd0" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.3" shared_preferences_ios: dependency: transitive description: name: shared_preferences_ios - sha256: "585a14cefec7da8c9c2fb8cd283a3bb726b4155c0952afe6a0caaa7b2272de34" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.1" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: f8ea038aa6da37090093974ebdcf4397010605fd2ff65c37a66f9d28394cb874 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.3" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - sha256: da9431745ede5ece47bc26d5d73a9d3c6936ef6945c101a5aca46f62e52c1cf3 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.0" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - sha256: a4b5bc37fe1b368bbc81f953197d55e12f49d0296e7e412dfe2d2d77d6929958 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.4" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: "5eaf05ae77658d3521d0e993ede1af962d4b326cd2153d312df716dc250f00c9" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.3" shelf: dependency: transitive description: name: shelf - sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.4.0" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.3" shimmer: dependency: transitive description: name: shimmer - sha256: "1f1009b5845a1f88f1c5630212279540486f97409e9fc3f63883e71070d107bf" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.0" sky_engine: @@ -1177,346 +1040,296 @@ packages: dependency: "direct main" description: name: slider_button - sha256: "9e23a806af48fa615b0891a18be87bb751ae3b6ca8dd5a299ecaafdf351623ef" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.0" source_span: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.9.1" + version: "1.9.0" sqflite: dependency: "direct main" description: name: sqflite - sha256: "78324387dc81df14f78df06019175a86a2ee0437624166c382e145d0a7fd9a4f" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.2.4+1" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: bfd6973aaeeb93475bc0d875ac9aefddf7965ef22ce09790eb963992ffc5183f - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.4.2+2" stack_trace: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.11.0" + version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.0" stream_transform: dependency: transitive description: name: stream_transform - sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.1.1" syncfusion_flutter_charts: dependency: "direct main" description: name: syncfusion_flutter_charts - sha256: "91204839376779c4ea4d7d7734abb039b429c4248a051c43079bff2e9b920a6e" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "20.4.48" syncfusion_flutter_core: dependency: transitive description: name: syncfusion_flutter_core - sha256: b3e500b1896d40c8961ab430a94fc22eff8fa1b33af03584e2f0b89371c3fa6a - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "20.4.48" synchronized: dependency: transitive description: name: synchronized - sha256: "33b31b6beb98100bf9add464a36a8dd03eb10c7a8cf15aeec535e9b054aaf04b" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.0.1" tar: dependency: "direct main" description: name: tar - sha256: "85ffd53e277f2bac8afa2885e6b195e26937e9c402424c3d88d92fd920b56de9" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.5.6" term_glyph: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.2.1" test_api: dependency: transitive description: name: test_api - sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.4.16" + version: "0.4.12" timezone: dependency: transitive description: name: timezone - sha256: "24c8fcdd49a805d95777a39064862133ff816ebfffe0ceff110fb5960e557964" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.9.1" timing: dependency: transitive description: name: timing - sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.1" tuple: dependency: transitive description: name: tuple - sha256: "0ea99cd2f9352b2586583ab2ce6489d1f95a5f6de6fb9492faaf97ae2060f0aa" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.1" typed_data: dependency: transitive description: name: typed_data - sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.3.1" unicode: dependency: transitive description: name: unicode - sha256: "0f69e46593d65245774d4f17125c6084d2c20b4e473a983f6e21b7d7762218f1" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.3.1" universal_io: dependency: transitive description: name: universal_io - sha256: "79f78ddad839ee3aae3ec7c01eb4575faf0d5c860f8e5223bc9f9c17f7f03cef" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.4" url_launcher: dependency: "direct main" description: name: url_launcher - sha256: "698fa0b4392effdc73e9e184403b627362eb5fbf904483ac9defbb1c2191d809" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "6.1.8" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "3e2f6dfd2c7d9cd123296cab8ef66cfc2c1a13f5845f42c7a0f365690a8a7dd1" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "6.0.23" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: bb328b24d3bccc20bdf1024a0990ac4f869d57663660de9c936fb8c043edefe3 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "6.0.18" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: "318c42cba924e18180c029be69caf0a1a710191b9ec49bb42b5998fdcccee3cc" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.0.2" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "41988b55570df53b3dd2a7fc90c76756a963de6a8c5f8e113330cb35992e2094" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.0.2" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - sha256: "4eae912628763eb48fc214522e58e942fd16ce195407dbf45638239523c759a6" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.1" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "44d79408ce9f07052095ef1f9a693c258d6373dc3944249374e30eff7219ccb0" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.14" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: b6217370f8eb1fd85c8890c539f5a639a01ab209a36db82c921ebeacefc7a615 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.0.3" uuid: dependency: transitive description: name: uuid - sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.0.7" vector_math: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.4" + version: "2.1.2" vibration: dependency: transitive description: name: vibration - sha256: "1dc9d1a0d62b12f1276eb7146b21585db5fe01771b8ca0234fefdf74ba51f963" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.7.6" - wallet: - dependency: transitive - description: - name: wallet - sha256: "2cabf10d4543b95773219fc401b184f8cbb0bba9359883f5ee5b9f2c46b85de3" - url: "https://pub.dev" - source: hosted - version: "0.0.7" walletconnect_dart: dependency: "direct main" description: name: walletconnect_dart - sha256: "6d69d3f7ed43b4a111458da0ba078f4ea291ff11328068c9cbf5cab3bd86593f" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.0.11" walletconnect_qrcode_modal_dart: dependency: "direct main" description: name: walletconnect_qrcode_modal_dart - sha256: "3ae5ff25e33b3c647fc5ec03d5c943d21e145371e9577e340f4be07e9f97a73c" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.0.6" watcher: dependency: transitive description: name: watcher - sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.2" web3dart: dependency: "direct main" description: name: web3dart - sha256: "0b96223a6b284e3146e65dc842ded139eca68a85c4ab79c5ba1a73284927d3cd" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.6.1" + version: "2.5.1" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.3.0" win32: dependency: transitive description: name: win32 - sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.1.3" wkt_parser: dependency: transitive description: name: wkt_parser - sha256: "8a555fc60de3116c00aad67891bcab20f81a958e4219cc106e3c037aa3937f13" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.0" workmanager: dependency: "direct main" description: name: workmanager - sha256: e0be7e35d644643f164ee45d2ce14414f0e0fdde19456aa66065f35a0b1d2ea1 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.5.1" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.2.0+3" xml: dependency: transitive description: name: xml - sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "6.2.2" + version: "6.1.0" yaml: dependency: transitive description: name: yaml - sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.1.1" sdks: - dart: ">=2.19.0 <3.0.0" + dart: ">=2.18.1 <3.0.0" flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index 86966fd..323ee95 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -69,6 +69,7 @@ dependencies: flip_card: ^0.7.0 connectivity: ^3.0.6 flutter_isolate: ^2.0.4 + geofence_flutter: ^2.0.0 dev_dependencies: flutter_test: From b0dc3dc9d9a85aae5ffa9d4f06a38ff7c68eca30 Mon Sep 17 00:00:00 2001 From: Giacomo Galletti Date: Tue, 7 Feb 2023 10:25:59 +0100 Subject: [PATCH 16/34] background service integration --- .../campaign_data_photo_controller.dart | 5 +- lib/controllers/campaign_list_controller.dart | 24 +- lib/controllers/distance_controller.dart | 29 +- .../sourcer_campaign_controller.dart | 2 +- .../sourcer_closed_campaign_controller.dart | 2 +- .../validate_photo_controller.dart | 46 ++- .../verifier_campaign_data_controller.dart | 2 +- ...gn_model.dart => campaign_list_model.dart} | 34 +- lib/models/db_capaign_model.dart | 7 +- lib/models/ipfs_client_model.dart | 9 +- lib/models/login_metamask_model.dart | 10 +- lib/models/search_places_model.dart | 2 +- lib/models/validate_model.dart | 33 +- lib/services/notification_channels.dart | 2 +- lib/services/services.dart | 141 ++++---- lib/services/servicesV2.dart | 305 ++++++++++++++++++ lib/services/services_controller.dart | 4 +- lib/services/services_controllerV2.dart | 80 +++++ lib/views/campaign_data_photo_view.dart | 8 +- lib/views/light_join_campaign_view.dart | 2 +- lib/views/photo_join_campaign_view.dart | 2 +- lib/views/sourcer_closed_campaign_view.dart | 7 +- 22 files changed, 622 insertions(+), 134 deletions(-) rename lib/models/{verifier_campaign_model.dart => campaign_list_model.dart} (54%) create mode 100644 lib/services/servicesV2.dart create mode 100644 lib/services/services_controllerV2.dart diff --git a/lib/controllers/campaign_data_photo_controller.dart b/lib/controllers/campaign_data_photo_controller.dart index b218f0c..fee3893 100644 --- a/lib/controllers/campaign_data_photo_controller.dart +++ b/lib/controllers/campaign_data_photo_controller.dart @@ -28,8 +28,9 @@ class _CampaignDataPhotoControllerState for (dynamic i in res) { Stream? res = await ValidateModel.downloadPhotosFiles(i[4].toString()); if (res != null) { - res.forEach((element) { - pictures.add(File(element.path)); + res.forEach((element) async { + File f = File(element.path); + pictures.add(await f.create()); }); } } diff --git a/lib/controllers/campaign_list_controller.dart b/lib/controllers/campaign_list_controller.dart index 2e7ca24..f307a2b 100644 --- a/lib/controllers/campaign_list_controller.dart +++ b/lib/controllers/campaign_list_controller.dart @@ -1,6 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:mobile_crowd_sensing/models/verifier_campaign_model.dart'; +import 'package:mobile_crowd_sensing/models/campaign_list_model.dart'; import 'package:numberpicker/numberpicker.dart'; import '../models/db_capaign_model.dart'; import '../utils/styles.dart'; @@ -23,7 +23,7 @@ class CampaignListController extends StatefulWidget { class _CampaignListControllerState extends State { Future futureGetData() { - return VerifierCampaignModel.getData(widget.contractsAddresses)!; + return CampaignListModel.getData(widget.contractsAddresses); } Future futureGetPosition() async { @@ -84,7 +84,8 @@ class _CampaignListControllerState fileCount, contractAddress, readebleLocation, - isSubscribed; + isSubscribed, + balance; if (current != null && _isToShow(current)) { name = current[0]; lat = (int.parse(current[1].toString()) / 10000000) @@ -98,6 +99,7 @@ class _CampaignListControllerState contractAddress = current[7].toString(); readebleLocation = current[8]; isSubscribed = current[9]; + balance = "${current[10].toString()} wei"; return GestureDetector( onTap: () { @@ -132,6 +134,7 @@ class _CampaignListControllerState type!, fileCount, crowdsourcer, + balance, readebleLocation!), ); } else { @@ -162,6 +165,7 @@ class _CampaignListControllerState String type, String fileCount, String crowdsourcer, + String balance, String readebleLocation) { return Card( shadowColor: Colors.blue[600], @@ -233,7 +237,7 @@ class _CampaignListControllerState ]), Row(children: [ Text( - "Range: $range", + "Range: $range m", style: CustomTextStyle.spaceMono(context), ), ]), @@ -260,6 +264,12 @@ class _CampaignListControllerState ], ), ), + Row(children: [ + Text( + "Balance: $balance", + style: CustomTextStyle.spaceMono(context), + ), + ]), Row(children: [ Text( "fileCount: $fileCount", @@ -337,7 +347,7 @@ class _CampaignListControllerState widget.places.lat, widget.places.lng); if (kDebugMode) { - print("BEBUG::::::::::::::::: $distance"); + print("DEBUG::::::::::::::::: [${double.parse(data[1].toString()) / 10000000},${double.parse(data[2].toString()) / 10000000}] e [${widget.places.lat},${widget.places.lng}] => $distance"); } return (distance <= (_currentIntValue)) ? true : false; default: @@ -347,7 +357,7 @@ class _CampaignListControllerState bool _checkIfDeviceIsInArea(String lat, String lon, String range) { widget.places.updateLocalPosition(); - dynamic distance = DistanceController.distanceBetween(widget.places.lat, widget.places.lng, double.parse(lat), double.parse(lon)); - return (distance <= double.parse(range))? true : false; + dynamic distanceInMeters = DistanceController.distanceBetween(widget.places.lat, widget.places.lng, double.parse(lat), double.parse(lon))*1000; + return (distanceInMeters <= double.parse(range))? true : false; } } diff --git a/lib/controllers/distance_controller.dart b/lib/controllers/distance_controller.dart index 6eb7a88..53af011 100644 --- a/lib/controllers/distance_controller.dart +++ b/lib/controllers/distance_controller.dart @@ -2,13 +2,28 @@ import 'dart:math'; class DistanceController { - static distanceBetween(lat1, lon1, lat2, lon2) { - var p = 0.017453292519943295; - var c = cos; - var a = 0.5 - - c((lat2 - lat1) * p) / 2 + - c(lat1 * p) * c(lat2 * p) * (1 - c((lon2 - lon1) * p)) / 2; - return 12742 * asin(sqrt(a)); + static double distanceBetween( + double startLatitude, + double startLongitude, + double endLatitude, + double endLongitude, + ) { + //print("INPUT: $startLatitude,$startLongitude - $endLatitude,$endLongitude"); + var earthRadius = 6378137.0; + var dLat = _toRadians(endLatitude - startLatitude); + var dLon = _toRadians(endLongitude - startLongitude); + + var a = pow(sin(dLat / 2), 2) + + pow(sin(dLon / 2), 2) * + cos(_toRadians(startLatitude)) * + cos(_toRadians(endLatitude)); + var c = 2 * asin(sqrt(a)); + + return (earthRadius * c)/1000; + } + + static _toRadians(double degree) { + return degree * pi / 180; } } \ No newline at end of file diff --git a/lib/controllers/sourcer_campaign_controller.dart b/lib/controllers/sourcer_campaign_controller.dart index 16dbd58..0bdc789 100644 --- a/lib/controllers/sourcer_campaign_controller.dart +++ b/lib/controllers/sourcer_campaign_controller.dart @@ -117,7 +117,7 @@ class _SourcerCampaignControllerState extends State { (range.isEmpty) ? GlobalText.loadingText(context) : Text( - "Range: $range", + "Range: $range m", style: CustomTextStyle.spaceMono(context), ), ]), diff --git a/lib/controllers/sourcer_closed_campaign_controller.dart b/lib/controllers/sourcer_closed_campaign_controller.dart index 0ce8a9a..5b3d2a4 100644 --- a/lib/controllers/sourcer_closed_campaign_controller.dart +++ b/lib/controllers/sourcer_closed_campaign_controller.dart @@ -108,7 +108,7 @@ class _SourcerClosedCampaignControllerState extends State[ (range.length != widget.contractAddress!.length) ? GlobalText.loadingText(context) : Text( - "Range: ${range[index]}", + "Range: ${range[index]} m", style: CustomTextStyle.spaceMono(context), ), ]), diff --git a/lib/controllers/validate_photo_controller.dart b/lib/controllers/validate_photo_controller.dart index 6b3151a..83a00b8 100644 --- a/lib/controllers/validate_photo_controller.dart +++ b/lib/controllers/validate_photo_controller.dart @@ -21,20 +21,18 @@ class ValidatePhotoState extends State { bool downloadGate = true; late List pictures = []; - + late List fileData = []; Future? _prepareData() async { if (mounted) { pictures.clear(); Stream? res = await ValidateModel.downloadPhotosFiles( campaignSelectedData['ipfsHash']); if (res != null) { - res.forEach((element) { - pictures.add(File(element.path)); + res.forEach((FileSystemEntity element) async { + File f = File(element.path); + pictures.add(await f.create()); }); - downloadGate = !downloadGate; - if (kDebugMode) { - print("PREPARING DATA: ${pictures.length}"); - } + fileData = await ValidateModel.getFileData(campaignSelectedData['ipfsHash'],campaignSelectedData['contractAddress']); } } } @@ -90,7 +88,39 @@ class ValidatePhotoState extends State { '${campaignSelectedData['ipfsHash']}', style: CustomTextStyle.inconsolata(context), ), - ) + ), + const SizedBox( + height: 20, + ), + Column( + children:[ + Text( + 'This data was taken in', + style: CustomTextStyle.spaceMonoBold(context)), + Row(children: [ + Text( + 'Latitude: ', + style: CustomTextStyle.spaceMonoBold(context)), + Text( + '${(int.parse(fileData[5].toString()) / 10000000)}', + style: CustomTextStyle.inconsolata(context),) + ],), + Row(children: [ + Text( + 'Longitude: ', + style: CustomTextStyle.spaceMonoBold(context)), + Text( + '${(int.parse(fileData[6].toString()) / 10000000)}', + style: CustomTextStyle.inconsolata(context),) + ],), + Text( + 'Address: ', + style: CustomTextStyle.spaceMonoBold(context)), + Text( + '${fileData[7]}', + style: CustomTextStyle.inconsolata(context), + ), + ]) ], ), Padding( diff --git a/lib/controllers/verifier_campaign_data_controller.dart b/lib/controllers/verifier_campaign_data_controller.dart index 2b23e9a..75b86ca 100644 --- a/lib/controllers/verifier_campaign_data_controller.dart +++ b/lib/controllers/verifier_campaign_data_controller.dart @@ -92,7 +92,7 @@ class _VerifierCampaignDataPhotoController style: CustomTextStyle.spaceMonoBold(context), ), Text( - range, + "$range m", style: CustomTextStyle.spaceMono(context), ), Text( diff --git a/lib/models/verifier_campaign_model.dart b/lib/models/campaign_list_model.dart similarity index 54% rename from lib/models/verifier_campaign_model.dart rename to lib/models/campaign_list_model.dart index 47a1897..9f5db57 100644 --- a/lib/models/verifier_campaign_model.dart +++ b/lib/models/campaign_list_model.dart @@ -1,40 +1,50 @@ +import 'package:flutter_config/flutter_config.dart'; + import 'db_capaign_model.dart'; import 'smart_contract_model.dart'; import 'search_places_model.dart'; import 'session_model.dart'; -class VerifierCampaignModel { - static Future? getData(List? contractAddress) async { +class CampaignListModel { + static Future> getData(List? contractAddress) async { SessionModel sessionData = SessionModel(); SearchPlacesModel searchPlacesViewModel = SearchPlacesModel(); - List? resInfo = []; - List? dataFirstPart = []; + List? dataComposition = []; + List out = []; DbCampaignModel db = DbCampaignModel(); List res = await db.campaigns(); if (contractAddress != null) { SmartContractModel smartContractViewModel; + SmartContractModel factoryContract = SmartContractModel( + contractAddress: FlutterConfig.get('MCSfactory_CONTRACT_ADDRESS'), + abiName: 'MCSfactory', + abiFileRoot: 'assets/abi.json', + provider: sessionData.getProvider() + ); + for (int i = 0; i < contractAddress.length; i++) { smartContractViewModel = SmartContractModel( contractAddress: contractAddress[i].toString(), abiName: 'Campaign', abiFileRoot: 'assets/abi_campaign.json', provider: sessionData.getProvider()); - dataFirstPart = await smartContractViewModel.queryCall('getInfo', []); - dataFirstPart?.add(contractAddress[i].toString()); - dataFirstPart?.add( + dataComposition = await smartContractViewModel.queryCall('getInfo', []); + dataComposition?.add(contractAddress[i].toString()); + dataComposition?.add( (await searchPlacesViewModel.getReadebleLocationFromLatLng( - (double.parse(dataFirstPart[1].toString())) / 10000000, - (double.parse(dataFirstPart[2].toString())) / 10000000)) + (double.parse(dataComposition[1].toString())) / 10000000, + (double.parse(dataComposition[2].toString())) / 10000000)) .toString() .replaceAll(RegExp(r'[^\w\s]+'), '')); - dataFirstPart?.add((await _checkIfIsInCampaignsDb(res,dataFirstPart[7].toString())).toString()); - resInfo.add(dataFirstPart); + dataComposition?.add((await _checkIfIsInCampaignsDb(res,dataComposition[7].toString())).toString()); + dataComposition?.add((await factoryContract.queryCall('balanceOf', [contractAddress[i]]))![0]); + out.add(dataComposition); } } - return resInfo; + return out; } static Future _checkIfIsInCampaignsDb(List storedCampaigns,String campaignAddress) async { diff --git a/lib/models/db_capaign_model.dart b/lib/models/db_capaign_model.dart index 8572b8b..b4790f4 100644 --- a/lib/models/db_capaign_model.dart +++ b/lib/models/db_capaign_model.dart @@ -3,6 +3,8 @@ import 'package:mobile_crowd_sensing/services/services_controller.dart'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; +import '../services/services_controllerV2.dart'; + class DbCampaignModel { static final DbCampaignModel _instance = DbCampaignModel._internal(); @@ -42,8 +44,7 @@ class DbCampaignModel { cmp.toMap(), conflictAlgorithm: ConflictAlgorithm.replace, ); - - ServicesController.resetServicies(); + ServicesControllerV2.resetServicies(); } Future> campaigns() async { @@ -78,7 +79,7 @@ class DbCampaignModel { where: 'address = ?', whereArgs: [address], ); - ServicesController.resetServicies(); + ServicesControllerV2.resetServicies(); } } diff --git a/lib/models/ipfs_client_model.dart b/lib/models/ipfs_client_model.dart index 4cf2bd1..5d4e324 100644 --- a/lib/models/ipfs_client_model.dart +++ b/lib/models/ipfs_client_model.dart @@ -139,13 +139,16 @@ class IpfsClientModel { StreamedResponse response = await request.send(); var result = await http.Response.fromStream(response); if (result.statusCode == 200) { + print('\x1B[31m${result.statusCode.toString()}\x1B[0m'); File compressedFile = await File("$tmpPath/$localFolder/$name").writeAsBytes(result.bodyBytes); Directory dir = Directory("$tmpPath/$localFolder/out"); - extractFileToDisk(compressedFile.path, dir.path); + await extractFileToDisk(compressedFile.path, dir.path); - Directory folderUncompressed = await dir.list().first as Directory; - return folderUncompressed.list(); + FileSystemEntity entity = await dir.list().first; + Directory out = Directory(entity.path); + return out.list(); } + print('\x1B[31m${result.toString()}\x1B[0m'); return null; } diff --git a/lib/models/login_metamask_model.dart b/lib/models/login_metamask_model.dart index 7c6c98b..1953f38 100644 --- a/lib/models/login_metamask_model.dart +++ b/lib/models/login_metamask_model.dart @@ -7,6 +7,8 @@ import 'package:mobile_crowd_sensing/services/services_controller.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher_string.dart'; +import '../services/services_controllerV2.dart'; + class LoginMetamaskModel { static Future loginUsingMetamask(BuildContext context) async { @@ -29,16 +31,16 @@ class LoginMetamaskModel { '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n'); } - if(!ServicesController.statusGeofencingService) { + if(!ServicesControllerV2.statusGeofencingService) { print('\x1B[31m [GEOFENCE SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); SearchPlacesModel search = SearchPlacesModel(); await search.getPermissions(); - ServicesController.initializeGeofencingService(); + ServicesControllerV2.initializeGeofencingService(); } - if(!ServicesController.statusCloseCampaignService) { + if(!ServicesControllerV2.statusCloseCampaignService) { print('\x1B[31m [CLOSED CAMPAIGN SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); - ServicesController.initializeCloseCampaignService(); + ServicesControllerV2.initializeCloseCampaignService(); } } catch (exp) { diff --git a/lib/models/search_places_model.dart b/lib/models/search_places_model.dart index cf00e4a..5cb6ec2 100644 --- a/lib/models/search_places_model.dart +++ b/lib/models/search_places_model.dart @@ -19,7 +19,7 @@ class SearchPlacesModel { lat = position.latitude; address = await getReadebleLocationFromLatLng(lat,lng); if (kDebugMode) { - print("__________________________________________________________________________POSITION: \n[lat]$lat\n[lng]$lng"); + print("\n[DEVICE POSITION]: \n[lat]$lat\n[lng]$lng\n"); } } diff --git a/lib/models/validate_model.dart b/lib/models/validate_model.dart index a011208..8de162d 100644 --- a/lib/models/validate_model.dart +++ b/lib/models/validate_model.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; +import 'package:mobile_crowd_sensing/models/search_places_model.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; import 'package:mobile_crowd_sensing/models/smart_contract_model.dart'; import 'ipfs_client_model.dart'; @@ -18,12 +19,36 @@ class ValidateModel { static Future?> downloadPhotosFiles( hashToDownload) async { - Stream? res = - await IpfsClientModel.downloadDirectoryIPFS(hashToDownload, 'photos'); + Stream? res = await IpfsClientModel.downloadDirectoryIPFS(hashToDownload, 'photos'); + return res; + } + + static Future> getFileData( + String ipfsHash, String contractAddress) async { + SessionModel sessionData = SessionModel(); + SearchPlacesModel searchPlacesViewModel = SearchPlacesModel(); + + List out = []; + + SmartContractModel smartContractViewModel = SmartContractModel( + contractAddress: contractAddress, + abiName: 'Campaign', + abiFileRoot: 'assets/abi_campaign.json', + provider: sessionData.getProvider()); + List? res = + await smartContractViewModel.queryCall('files', [ipfsHash]); + if (res != null) { - return res; + out = res; + print("DEB: ${res.toString()}"); + out.add( + (await searchPlacesViewModel.getReadebleLocationFromLatLng( + (double.parse(res[5].toString())) / 10000000, + (double.parse(res[6].toString())) / 10000000)) + .toString() + .replaceAll(RegExp(r'[^\w\s]+'), '')); } - return null; + return out; } static Future approveOrNot(contractAddress, hash, bool status) async { diff --git a/lib/services/notification_channels.dart b/lib/services/notification_channels.dart index 86fcbeb..cf97031 100644 --- a/lib/services/notification_channels.dart +++ b/lib/services/notification_channels.dart @@ -13,7 +13,7 @@ class NotificationChannel { static AndroidNotificationChannel importantChannel_2 = const AndroidNotificationChannel( 'important_channel_2', // id - 'IMPORTANT NOTIFICATION CHANNEL', // title + 'IMPORTANT NOTIFICATION CHANNEL 2', // title description: 'This channel is used for important notification.', // description importance: Importance.max, // importance must be at low or higher level diff --git a/lib/services/services.dart b/lib/services/services.dart index daa91e1..c2527b6 100644 --- a/lib/services/services.dart +++ b/lib/services/services.dart @@ -4,12 +4,12 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:http/http.dart' as http; import 'package:mobile_crowd_sensing/services/notification_channels.dart'; import 'package:mobile_crowd_sensing/services/services_controller.dart'; +import 'package:mobile_crowd_sensing/services/services_controllerV2.dart'; import 'package:web3dart/web3dart.dart'; import '../models/db_capaign_model.dart'; import 'dart:async'; import 'dart:ui'; - import 'package:geofence_flutter/geofence_flutter.dart'; class Services { @@ -29,7 +29,7 @@ class Services { ?.createNotificationChannel(NotificationChannel.importantChannel); Timer.periodic(const Duration(seconds: 60), (timer) async { - ServicesController.statusCloseCampaignService = true; + ServicesControllerV2.statusCloseCampaignService = true; res = await db.campaigns(); if (res.isNotEmpty) { for (Campaign c in res) { @@ -71,22 +71,23 @@ class Services { await db.deleteCampaign(address); } else { if (kDebugMode) { - print('\x1B[31m [CLOSED CAMPAIGN SERVICE] The campaign still open: nothing to notify. \x1B[0m'); + print( + '\x1B[31m [CLOSED CAMPAIGN SERVICE] The campaign still open: nothing to notify. \x1B[0m'); } } } else { if (kDebugMode) { print( - '\x1B[31m [CLOSED CAMPAIGN SERVICE]an error occurred. \x1B[0m'); + '\x1B[31m [CLOSED CAMPAIGN SERVICE]an error occurred. \x1B[0m'); } } } } else { - ServicesController.statusCloseCampaignService = false; + ServicesControllerV2.statusCloseCampaignService = false; timer.cancel(); if (kDebugMode) { print( - '\x1B[31m [CLOSED CAMPAIGN SERVICE] No campaigns to follow. stop the service.\x1B[0m'); + '\x1B[31m [CLOSED CAMPAIGN SERVICE] No campaigns to follow. stop the service.\x1B[0m'); } } }); @@ -107,54 +108,52 @@ class Services { if (kDebugMode) { print('\x1B[31m [GEOFENCE SERVICE] geofence open for:' - '\n ${args['title']!}' - '\n ${args['address']!}' - '\n ${args['lat']!} ' - '\n ${args['lng']!} \x1B[0m'); + '\n ${args['title']!}' + '\n ${args['address']!}' + '\n ${args['lat']!} ' + '\n ${args['lng']!} \x1B[0m'); } await Geofence.startGeofenceService( pointedLatitude: args['lat']!, pointedLongitude: args['lng']!, radiusMeter: args['radius']!, - eventPeriodInSeconds: 10 - ); + eventPeriodInSeconds: 10); GeofenceEvent? previous; - Geofence.getGeofenceStream()?.listen( - (GeofenceEvent event) { + Geofence.getGeofenceStream()?.listen((GeofenceEvent event) { + if (kDebugMode) { + print(event.toString()); + } + + if (previous == null || previous == GeofenceEvent.init) { + switch (event) { + case GeofenceEvent.enter: + previous = event; + break; + case GeofenceEvent.exit: + previous = event; + break; + default: + previous = event; + break; + } + } + + switch (event) { + case GeofenceEvent.init: if (kDebugMode) { - print(event.toString()); + print('\x1B[31m $debugString status: Init\x1B[0m'); } - - if(previous == null || previous == GeofenceEvent.init) { - switch (event) { - case GeofenceEvent.enter: - previous = event; - break; - case GeofenceEvent.exit: - previous = event; - break; - default: - previous = event; - break; - } + previous = event; + break; + case GeofenceEvent.enter: + if (kDebugMode) { + print('\x1B[31m $debugString status: Enter\x1B[0m'); } - - switch (event) { - case GeofenceEvent.init: - if (kDebugMode) { - print('\x1B[31m $debugString status: Init\x1B[0m'); - } - previous = event; - break; - case GeofenceEvent.enter: - if (kDebugMode) { - print('\x1B[31m $debugString status: Enter\x1B[0m'); - } - (previous != event)? - notification.show( + (previous != event) + ? notification.show( 888, 'Entered in Campaign Area', '[${args['title']!}] \nat address: ${args['address']!}', @@ -163,36 +162,46 @@ class Services { 'important_channel', 'MY FOREGROUND SERVICE', icon: 'ic_bg_service_small', + styleInformation: BigTextStyleInformation( + "

String bigText

sisisisisisisisisi

", + htmlFormatBigText: true, + contentTitle: "

this is title

", + htmlFormatContentTitle: true, + summaryText: "

this is the summary text

", + htmlFormatSummaryText: true, + htmlFormatContent : true, + htmlFormatTitle : true + ), ongoing: true, ), ), ) : print('\x1B[31m $debugString status not changed \x1B[0m'); - previous = event; - break; - case GeofenceEvent.exit: - if (kDebugMode) { - print('\x1B[31m $debugString status: Exit\x1B[0m'); - } - (previous != event)? - notification.show( - 888, - 'Exit from Campaign Area', - '[${args['title']!}] \nat address: ${args['address']!}', - const NotificationDetails( - android: AndroidNotificationDetails( - 'important_channel', - 'MY FOREGROUND SERVICE', - icon: 'ic_bg_service_small', - ongoing: true, - ), - )) + previous = event; + break; + case GeofenceEvent.exit: + if (kDebugMode) { + print('\x1B[31m $debugString status: Exit\x1B[0m'); + } + (previous != event) + ? notification.show( + 888, + 'Exit from Campaign Area', + '[${args['title']!}] \nat address: ${args['address']!}', + const NotificationDetails( + android: AndroidNotificationDetails( + 'important_channel', + 'MY FOREGROUND SERVICE', + icon: 'ic_bg_service_small', + ongoing: true, + ), + )) : print('\x1B[31m $debugString status not changed \x1B[0m'); - previous = event; + previous = event; - break; - } - }); + break; + } + }); } } @@ -242,5 +251,3 @@ class SmartContractModelBs { } } } - - diff --git a/lib/services/servicesV2.dart b/lib/services/servicesV2.dart new file mode 100644 index 0000000..d0a58d6 --- /dev/null +++ b/lib/services/servicesV2.dart @@ -0,0 +1,305 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_background_service/flutter_background_service.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:http/http.dart' as http; +import 'package:mobile_crowd_sensing/services/notification_channels.dart'; +import 'package:mobile_crowd_sensing/services/services_controllerV2.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:web3dart/web3dart.dart'; +import '../models/db_capaign_model.dart'; +import 'dart:async'; +import 'dart:ui'; +import 'package:geofence_flutter/geofence_flutter.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_background_service_android/flutter_background_service_android.dart'; + + +class ServicesV2 { + + static Future onIosBackground(ServiceInstance service) async { + WidgetsFlutterBinding.ensureInitialized(); + DartPluginRegistrant.ensureInitialized(); + + SharedPreferences preferences = await SharedPreferences.getInstance(); + await preferences.reload(); + final log = preferences.getStringList('log') ?? []; + log.add(DateTime.now().toIso8601String()); + await preferences.setStringList('log', log); + + return true; + } + + static void checkCloseCampaign(ServiceInstance service) async { + DartPluginRegistrant.ensureInitialized(); + + SharedPreferences preferences = await SharedPreferences.getInstance(); + + if (service is AndroidServiceInstance) { + service.on('setAsForeground').listen((event) { + service.setAsForegroundService(); + }); + + service.on('setAsBackground').listen((event) { + service.setAsBackgroundService(); + }); + } + + service.on('stopService').listen((event) { + service.stopSelf(); + }); + + DbCampaignModel db = DbCampaignModel(); + List res = []; + String accountAddress = preferences.getString('address')!; + + final FlutterLocalNotificationsPlugin notification = + FlutterLocalNotificationsPlugin(); + + await notification + .resolvePlatformSpecificImplementation< + AndroidFlutterLocalNotificationsPlugin>() + ?.createNotificationChannel(NotificationChannel.importantChannel_2); + + Timer.periodic(const Duration(seconds: 60), (timer) async { + ServicesControllerV2.statusCloseCampaignService = true; + res = await db.campaigns(); + if (res.isNotEmpty) { + for (Campaign c in res) { + String address = c.address; + String title = c.title; + + SmartContractModelBs smartContract = SmartContractModelBs( + contractAddress: address, + abiName: 'Campaign', + abiFileRoot: 'assets/abi_campaign.json', + accountAddress: accountAddress); + + List? isClosedRaw = + await smartContract.queryCall('isClosed', []); + + if (isClosedRaw != null) { + String answer = isClosedRaw[0].toString(); + + if (answer == "true") { + // the campaign result closed + if (kDebugMode) { + print('\x1B[31mThe campaign was closed\x1B[0m'); + } + + notification.show( + 999, + 'Campaign Closed', + 'The campaign [$title] \nat address $address \n was closed by crowdsourcer', + NotificationDetails( + android: AndroidNotificationDetails( + NotificationChannel.importantChannel_2.id, + NotificationChannel.importantChannel_2.name, + icon: 'ic_bg_service_small', + ongoing: false, + ), + ), + ); + + await db.deleteCampaign(address); + } else { + if (kDebugMode) { + print( + '\x1B[31m [CLOSED CAMPAIGN SERVICE] The campaign still open: nothing to notify. \x1B[0m'); + } + } + } else { + if (kDebugMode) { + print( + '\x1B[31m [CLOSED CAMPAIGN SERVICE]an error occurred. \x1B[0m'); + } + } + } + } else { + ServicesControllerV2.statusCloseCampaignService = false; + timer.cancel(); + service.invoke('stopService'); + if (kDebugMode) { + print( + '\x1B[31m [CLOSED CAMPAIGN SERVICE] No campaigns to follow. stop the service.\x1B[0m'); + } + } + }); + } + + static void checkGeofence(ServiceInstance service) async { + + DartPluginRegistrant.ensureInitialized(); + + SharedPreferences preferences = await SharedPreferences.getInstance(); + + if (service is AndroidServiceInstance) { + service.on('setAsForeground').listen((event) { + service.setAsForegroundService(); + }); + + service.on('setAsBackground').listen((event) { + service.setAsBackgroundService(); + }); + } + + service.on('stopService').listen((event) { + service.stopSelf(); + }); + + String debugString = "[GEOFENCE ${preferences.getString("title")!}"; + + final FlutterLocalNotificationsPlugin notification = + FlutterLocalNotificationsPlugin(); + + await notification + .resolvePlatformSpecificImplementation< + AndroidFlutterLocalNotificationsPlugin>() + ?.createNotificationChannel(NotificationChannel.importantChannel); + + if (kDebugMode) { + print('\x1B[31m [GEOFENCE SERVICE] geofence open for:' + '\n ${preferences.getString('title')!}' + '\n ${preferences.getString('address')!}' + '\n ${preferences.getString('lat')!} ' + '\n ${preferences.getString('lng')!} \x1B[0m'); + } + + await Geofence.startGeofenceService( + pointedLatitude: preferences.getString('lat')!, + pointedLongitude: preferences.getString('lng')!, + radiusMeter: preferences.getString('radius')!, + eventPeriodInSeconds: 10); + + GeofenceEvent? previous; + + Geofence.getGeofenceStream()?.listen((GeofenceEvent event) { + if (kDebugMode) { + print(event.toString()); + } + + if (previous == null || previous == GeofenceEvent.init) { + switch (event) { + case GeofenceEvent.enter: + previous = event; + break; + case GeofenceEvent.exit: + previous = event; + break; + default: + previous = event; + break; + } + } + + switch (event) { + case GeofenceEvent.init: + if (kDebugMode) { + print('\x1B[31m $debugString status: Init\x1B[0m'); + } + previous = event; + break; + case GeofenceEvent.enter: + if (kDebugMode) { + print('\x1B[31m $debugString status: Enter\x1B[0m'); + } + (previous != event) + ? notification.show( + 888, + 'Entered in Campaign Area', + '[${preferences.getString('title')!}] \nat address: ${preferences.getString('address')!}', + const NotificationDetails( + android: AndroidNotificationDetails( + 'important_channel', + 'MY FOREGROUND SERVICE', + icon: 'ic_bg_service_small', + styleInformation: BigTextStyleInformation( + "

String bigText

sisisisisisisisisi

", + htmlFormatBigText: true, + contentTitle: "

this is title

", + htmlFormatContentTitle: true, + summaryText: "

this is the summary text

", + htmlFormatSummaryText: true, + htmlFormatContent : true, + htmlFormatTitle : true + ), + ongoing: true, + ), + ), + ) + : print('\x1B[31m $debugString status not changed \x1B[0m'); + previous = event; + break; + case GeofenceEvent.exit: + if (kDebugMode) { + print('\x1B[31m $debugString status: Exit\x1B[0m'); + } + (previous != event) + ? notification.show( + 888, + 'Exit from Campaign Area', + '[${preferences.getString('title')!}] \nat address: ${preferences.getString('address')!}', + NotificationDetails( + android: AndroidNotificationDetails( + NotificationChannel.importantChannel.id, + NotificationChannel.importantChannel.name, + icon: 'ic_bg_service_small', + ongoing: true, + ), + )) + : print('\x1B[31m $debugString status not changed \x1B[0m'); + previous = event; + + break; + } + }); + } +} + +class SmartContractModelBs { + SmartContractModelBs( + {required this.accountAddress, + required this.contractAddress, + required this.abiName, + required this.abiFileRoot}); + + final String accountAddress; + final String contractAddress; + final String abiName; + final String abiFileRoot; + late http.Client httpClient; + late Web3Client ethClient; + + Future loadContract(String contractAddress) async { + String abi = await rootBundle.loadString(abiFileRoot); + final contract = DeployedContract(ContractAbi.fromJson(abi, abiName), + EthereumAddress.fromHex(contractAddress)); + return contract; + } + + Future?> queryCall( + String functionName, List args) async { + try { + httpClient = http.Client(); + ethClient = Web3Client( + "https://goerli.infura.io/v3/5074605772bb4bc4b6970d2ce999efca", + httpClient); + + final contract = await loadContract(contractAddress); + final ethFunction = contract.function(functionName); + final result = await ethClient.call( + sender: EthereumAddress.fromHex(accountAddress), + contract: contract, + function: ethFunction, + params: args); + List res = result; + return res; + } catch (e) { + if (kDebugMode) { + print('\x1B[31m$e\x1B[0m'); + } + return null; + } + } +} diff --git a/lib/services/services_controller.dart b/lib/services/services_controller.dart index d32aead..355a37b 100644 --- a/lib/services/services_controller.dart +++ b/lib/services/services_controller.dart @@ -1,9 +1,11 @@ import 'package:flutter_isolate/flutter_isolate.dart'; -import 'package:mobile_crowd_sensing/services/services.dart'; +import 'package:flutter_background_service/flutter_background_service.dart'; +import 'package:mobile_crowd_sensing/services/services.dart'; import '../models/db_capaign_model.dart'; import '../models/session_model.dart'; + class ServicesController{ static bool statusCloseCampaignService = false; diff --git a/lib/services/services_controllerV2.dart b/lib/services/services_controllerV2.dart new file mode 100644 index 0000000..70a7bb5 --- /dev/null +++ b/lib/services/services_controllerV2.dart @@ -0,0 +1,80 @@ +import 'package:flutter_background_service/flutter_background_service.dart'; +import 'package:mobile_crowd_sensing/services/servicesV2.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import '../models/db_capaign_model.dart'; +import 'notification_channels.dart'; + +class ServicesControllerV2 { + static bool statusCloseCampaignService = false; + static bool statusGeofencingService = false; + static List servicesList = []; + static void initializeCloseCampaignService() async { + FlutterBackgroundService s = FlutterBackgroundService(); + + s.configure( + androidConfiguration: AndroidConfiguration( + onStart: ServicesV2.checkCloseCampaign, + autoStart: true, + isForegroundMode: true, + + notificationChannelId: NotificationChannel.importantChannel_2.id, + initialNotificationTitle: NotificationChannel.importantChannel_2.name, + initialNotificationContent: 'closing campaign service', + foregroundServiceNotificationId: 888, + ), + iosConfiguration: IosConfiguration( + autoStart: true, + onForeground: ServicesV2.checkCloseCampaign, + onBackground: ServicesV2.onIosBackground, + ), + ); + servicesList.add(s); + statusCloseCampaignService = true; + } + + static Future initializeGeofencingService() async { + DbCampaignModel db = DbCampaignModel(); + List res = await db.campaigns(); + if (res.isNotEmpty) { + statusGeofencingService = true; + for (Campaign c in res) { + FlutterBackgroundService s = FlutterBackgroundService(); + SharedPreferences shared = await SharedPreferences.getInstance(); + shared.setString('address',c.address); + shared.setString('title', c.title); + shared.setString('lat',c.lat); + shared.setString('lng',c.lng); + shared.setString('radius', c.radius); + s.configure( + androidConfiguration: AndroidConfiguration( + onStart: ServicesV2.checkGeofence, + autoStart: true, + isForegroundMode: true, + + notificationChannelId: NotificationChannel.importantChannel.id, + initialNotificationTitle: NotificationChannel.importantChannel.name, + initialNotificationContent: 'geofence: ${c.title}', + foregroundServiceNotificationId: 999, + ), + iosConfiguration: IosConfiguration( + autoStart: true, + onForeground: ServicesV2.checkGeofence, + onBackground: ServicesV2.onIosBackground, + ), + ); + print('\x1B[31m sono iniziato almeno? ${await s.startService()}\x1B[0m'); + servicesList.add(s); + } + } + } + + static void resetServicies() async { + servicesList.forEach((element) { + element.invoke('stopService'); + }); + statusCloseCampaignService = true; + statusGeofencingService = true; + initializeCloseCampaignService(); + initializeGeofencingService(); + } +} diff --git a/lib/views/campaign_data_photo_view.dart b/lib/views/campaign_data_photo_view.dart index 42dd9be..bc6dfbc 100644 --- a/lib/views/campaign_data_photo_view.dart +++ b/lib/views/campaign_data_photo_view.dart @@ -1,12 +1,9 @@ import 'dart:convert'; -import 'dart:io'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:mobile_crowd_sensing/controllers/campaign_data_photo_controller.dart'; import 'package:mobile_crowd_sensing/utils/styles.dart'; import '../../utils/worker_campaign_data_factory.dart'; -import '../models/validate_model.dart'; -import '../models/verifier_campaign_data_model.dart'; + class CampaignDataPhotoView extends WorkerDataCampaignFactory { const CampaignDataPhotoView({super.key}); @@ -25,9 +22,6 @@ class LightJoinCampaignViewState extends State { parameters = ModalRoute.of(context)!.settings.arguments; jsonParameters = jsonDecode(jsonEncode(parameters)); - print("campaign_data_photo_view"); - - return Scaffold( appBar: AppBar( backgroundColor: CustomColors.blue900(context), diff --git a/lib/views/light_join_campaign_view.dart b/lib/views/light_join_campaign_view.dart index 8ad6d34..e9e31da 100644 --- a/lib/views/light_join_campaign_view.dart +++ b/lib/views/light_join_campaign_view.dart @@ -94,7 +94,7 @@ class LightJoinCampaignViewState extends State { style: CustomTextStyle.merriweatherBold(context), ), Text( - '${campaignSelectedData['range']}', + '${campaignSelectedData['range']} m', style: CustomTextStyle.inconsolata(context), ), ], diff --git a/lib/views/photo_join_campaign_view.dart b/lib/views/photo_join_campaign_view.dart index b28c8d5..f94bb43 100644 --- a/lib/views/photo_join_campaign_view.dart +++ b/lib/views/photo_join_campaign_view.dart @@ -97,7 +97,7 @@ class PhotoJoinCampaignViewState extends State { style: CustomTextStyle.spaceMonoBold(context), ), Text( - '${campaignSelectedData['range']}', + '${campaignSelectedData['range']} m', style: CustomTextStyle.inconsolata(context), ), ], diff --git a/lib/views/sourcer_closed_campaign_view.dart b/lib/views/sourcer_closed_campaign_view.dart index 760de34..cf69cdf 100644 --- a/lib/views/sourcer_closed_campaign_view.dart +++ b/lib/views/sourcer_closed_campaign_view.dart @@ -17,15 +17,18 @@ class _SourcerClosedCampaignViewState extends State { @override Widget build(BuildContext context) { List? contractAddress = widget.contractAddress; + + print("DEBUG sourcer_closed_campaign_view:::: ${contractAddress.toString()}"); + return Scaffold( appBar: AppBar( backgroundColor: CustomColors.blue900(context), title: const Text('Yours Past Campaigns'), centerTitle: true, ), - body: (contractAddress != null) ? + body: (contractAddress != null && contractAddress.isNotEmpty) ? SourcerClosedCampaignController(contractAddress) : - const Center(child: Text('No active campaign at the moment...')) + Center(child: Text('No campaigns at the moment...',style: CustomTextStyle.spaceMono(context),)) ); } } From 5f702fb6c6fb22799e8028781830b4180d4f03d0 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Tue, 7 Feb 2023 16:06:45 +0100 Subject: [PATCH 17/34] geofence notification in background service --- lib/controllers/campaign_list_controller.dart | 4 +- lib/controllers/distance_controller.dart | 5 +- lib/models/db_capaign_model.dart | 1 - lib/models/geofence_model.dart | 192 ++++++ lib/models/login_metamask_model.dart | 7 +- lib/services/notification_channels.dart | 25 +- lib/services/services.dart | 253 ------- lib/services/servicesV2.dart | 179 +---- lib/services/services_controller.dart | 47 -- lib/services/services_controllerV2.dart | 65 +- pubspec.lock | 629 +++++++++++------- pubspec.yaml | 3 +- 12 files changed, 654 insertions(+), 756 deletions(-) create mode 100644 lib/models/geofence_model.dart delete mode 100644 lib/services/services.dart delete mode 100644 lib/services/services_controller.dart diff --git a/lib/controllers/campaign_list_controller.dart b/lib/controllers/campaign_list_controller.dart index f307a2b..440835f 100644 --- a/lib/controllers/campaign_list_controller.dart +++ b/lib/controllers/campaign_list_controller.dart @@ -345,7 +345,7 @@ class _CampaignListControllerState (double.parse(data[1].toString()) / 10000000), (double.parse(data[2].toString()) / 10000000), widget.places.lat, - widget.places.lng); + widget.places.lng)/1000; if (kDebugMode) { print("DEBUG::::::::::::::::: [${double.parse(data[1].toString()) / 10000000},${double.parse(data[2].toString()) / 10000000}] e [${widget.places.lat},${widget.places.lng}] => $distance"); } @@ -357,7 +357,7 @@ class _CampaignListControllerState bool _checkIfDeviceIsInArea(String lat, String lon, String range) { widget.places.updateLocalPosition(); - dynamic distanceInMeters = DistanceController.distanceBetween(widget.places.lat, widget.places.lng, double.parse(lat), double.parse(lon))*1000; + dynamic distanceInMeters = DistanceController.distanceBetween(widget.places.lat, widget.places.lng, double.parse(lat), double.parse(lon)); return (distanceInMeters <= double.parse(range))? true : false; } } diff --git a/lib/controllers/distance_controller.dart b/lib/controllers/distance_controller.dart index 53af011..1c66dcb 100644 --- a/lib/controllers/distance_controller.dart +++ b/lib/controllers/distance_controller.dart @@ -18,8 +18,9 @@ class DistanceController { cos(_toRadians(startLatitude)) * cos(_toRadians(endLatitude)); var c = 2 * asin(sqrt(a)); - - return (earthRadius * c)/1000; + double distance = (earthRadius * c); + print("DISTANCE CALCULATED: $distance"); + return distance; } static _toRadians(double degree) { diff --git a/lib/models/db_capaign_model.dart b/lib/models/db_capaign_model.dart index b4790f4..037103b 100644 --- a/lib/models/db_capaign_model.dart +++ b/lib/models/db_capaign_model.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'package:mobile_crowd_sensing/services/services_controller.dart'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; diff --git a/lib/models/geofence_model.dart b/lib/models/geofence_model.dart new file mode 100644 index 0000000..b5d4857 --- /dev/null +++ b/lib/models/geofence_model.dart @@ -0,0 +1,192 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:geolocator/geolocator.dart'; +import 'package:mobile_crowd_sensing/services/notification_channels.dart'; +import '../controllers/distance_controller.dart'; +import 'dart:async'; +import 'dart:ui'; + +enum GeofenceEvent { init, enter, exit } + +class Geofence { + late String title,address,lat,lng,radius; + + StreamSubscription? _positionStream; + Stream? _geostream; + final StreamController _controller = StreamController(); + + + Geofence(this.title,this.address,this.lat,this.lng,this.radius); + + + Future initialize() async { + DartPluginRegistrant.ensureInitialized(); + + String debugString = "[GEOFENCE $title]"; + + final FlutterLocalNotificationsPlugin notification = + FlutterLocalNotificationsPlugin(); + + if (kDebugMode) { + print('\x1B[31m [GEOFENCE SERVICE] geofence open for:' + '\n $title' + '\n $address' + '\n $lat ' + '\n $lng ' + '\n $radius \x1B[0m'); + } + + await _startGeofenceService( + pointedLatitude: lat, + pointedLongitude: lng, + radiusMeter: radius, // TO CHANGE + eventPeriodInSeconds: 10); + + GeofenceEvent? previous; + + getGeofenceStream()?.listen((GeofenceEvent event) { + if (kDebugMode) { + print(event.toString()); + } + + if (previous == null || previous == GeofenceEvent.init) { + switch (event) { + case GeofenceEvent.enter: + previous = event; + break; + case GeofenceEvent.exit: + previous = event; + break; + default: + previous = event; + break; + } + } + + switch (event) { + case GeofenceEvent.init: + if (kDebugMode) { + print('\x1B[31m $debugString status: Init\x1B[0m'); + } + previous = event; + break; + case GeofenceEvent.enter: + if (kDebugMode) { + print('\x1B[31m $debugString status: Enter\x1B[0m'); + } + (previous != event) + ? notification.show( + 888, + 'Entered in Campaign Area', + '[$title] \nat address: $address', + NotificationDetails( + android: AndroidNotificationDetails( + NotificationChannel.backgroundServiceChannel.id, + NotificationChannel.backgroundServiceChannel.name, + icon: 'ic_bg_service_small', + styleInformation: BigTextStyleInformation( + "

You are entered inside the \"$title\" \n campaign at address: \n$address

", + htmlFormatBigText: true, + contentTitle: "

ENTER INSIDE \"$title\"

", + htmlFormatContentTitle: true, + summaryText: "

you entered in a campaign area

", + htmlFormatSummaryText: true, + htmlFormatContent: true, + htmlFormatTitle: true), + ongoing: false, + ), + ), + ) + : print('\x1B[31m $debugString status not changed \x1B[0m'); + previous = event; + break; + case GeofenceEvent.exit: + if (kDebugMode) { + print('\x1B[31m $debugString status: Exit\x1B[0m'); + } + (previous != event) + ? notification.show( + 888, + 'Exit from Campaign Area', + '[$title] \nat address: $address', + NotificationDetails( + android: AndroidNotificationDetails( + NotificationChannel.backgroundServiceChannel.id, + NotificationChannel.backgroundServiceChannel.name, + icon: 'ic_bg_service_small', + styleInformation: BigTextStyleInformation( + "

You are out of the \"$title\" \n campaign at address: \n$address

", + htmlFormatBigText: true, + contentTitle: "

EXIT FROM \"$title\"

", + htmlFormatContentTitle: true, + summaryText: "

you exit from a campaign area

", + htmlFormatSummaryText: true, + htmlFormatContent: true, + htmlFormatTitle: true), + ongoing: false, + ), + )) + : print('\x1B[31m $debugString status not changed \x1B[0m'); + previous = event; + + break; + } + }); + } + + + + _startGeofenceService( + {required String pointedLatitude, + required String pointedLongitude, + required String radiusMeter, + required int eventPeriodInSeconds}) async { + double latitude = _parser(pointedLatitude); + double longitude = _parser(pointedLongitude); + double radiusInMeter = _parser(radiusMeter); + LocationPermission permission = await Geolocator.checkPermission(); + if (permission == LocationPermission.denied) { + permission = await Geolocator.requestPermission(); + if (permission == LocationPermission.denied) return; + } + if (permission == LocationPermission.deniedForever) return; + if (_positionStream == null) { + _geostream = _controller.stream; + _positionStream = Geolocator.getPositionStream( + locationSettings: + LocationSettings(accuracy: LocationAccuracy.best)) + .listen((Position? position) { + if (position != null) { + double distanceInMeters = DistanceController.distanceBetween( + latitude, longitude, position.latitude, position.longitude); + _checkGeofence(distanceInMeters, radiusInMeter); + _positionStream! + .pause(Future.delayed(Duration(seconds: eventPeriodInSeconds))); + } + }); + _controller.add(GeofenceEvent.init); + } + } + + double _parser(String value) { + return double.parse(value); + } + + Stream? getGeofenceStream() { + return _geostream; + } + + _checkGeofence(double distanceInMeters, double radiusInMeter) { + if (distanceInMeters <= radiusInMeter) { + _controller.add(GeofenceEvent.enter); + } else { + _controller.add(GeofenceEvent.exit); + } + } + + stopGeofenceService() { + if (_positionStream != null) { + _positionStream!.cancel(); + } + } +} diff --git a/lib/models/login_metamask_model.dart b/lib/models/login_metamask_model.dart index 1953f38..13b3a8d 100644 --- a/lib/models/login_metamask_model.dart +++ b/lib/models/login_metamask_model.dart @@ -1,9 +1,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; -import 'package:mobile_crowd_sensing/models/db_capaign_model.dart'; -import 'package:mobile_crowd_sensing/models/search_places_model.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; -import 'package:mobile_crowd_sensing/services/services_controller.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher_string.dart'; @@ -31,12 +28,12 @@ class LoginMetamaskModel { '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n'); } - if(!ServicesControllerV2.statusGeofencingService) { +/* if(!ServicesControllerV2.statusGeofencingService) { print('\x1B[31m [GEOFENCE SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); SearchPlacesModel search = SearchPlacesModel(); await search.getPermissions(); ServicesControllerV2.initializeGeofencingService(); - } + }*/ if(!ServicesControllerV2.statusCloseCampaignService) { print('\x1B[31m [CLOSED CAMPAIGN SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); diff --git a/lib/services/notification_channels.dart b/lib/services/notification_channels.dart index cf97031..a31f3b9 100644 --- a/lib/services/notification_channels.dart +++ b/lib/services/notification_channels.dart @@ -1,30 +1,13 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart'; class NotificationChannel { - static AndroidNotificationChannel importantChannel = + static AndroidNotificationChannel backgroundServiceChannel = const AndroidNotificationChannel( - 'important_channel', // id - 'IMPORTANT NOTIFICATION CHANNEL', // title + 'mcs_background_service', // id + 'MCS BACKGROUND SERVICE', // title description: - 'This channel is used for important notification.', // description + 'This channel is used for closing campaign notification.', // description importance: Importance.max, // importance must be at low or higher level ); - static AndroidNotificationChannel importantChannel_2 = - const AndroidNotificationChannel( - 'important_channel_2', // id - 'IMPORTANT NOTIFICATION CHANNEL 2', // title - description: - 'This channel is used for important notification.', // description - importance: Importance.max, // importance must be at low or higher level - ); - - static AndroidNotificationChannel lowImportantChannel = - const AndroidNotificationChannel( - 'low_important_channel', // id - 'LOW IMPORTANT NOTIFICATION CHANNEL', // title - description: - 'This channel is used for not important notification.', // description - importance: Importance.low, // importance must be at low or higher level - ); } diff --git a/lib/services/services.dart b/lib/services/services.dart deleted file mode 100644 index c2527b6..0000000 --- a/lib/services/services.dart +++ /dev/null @@ -1,253 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_local_notifications/flutter_local_notifications.dart'; -import 'package:http/http.dart' as http; -import 'package:mobile_crowd_sensing/services/notification_channels.dart'; -import 'package:mobile_crowd_sensing/services/services_controller.dart'; -import 'package:mobile_crowd_sensing/services/services_controllerV2.dart'; -import 'package:web3dart/web3dart.dart'; -import '../models/db_capaign_model.dart'; -import 'dart:async'; -import 'dart:ui'; - -import 'package:geofence_flutter/geofence_flutter.dart'; - -class Services { - @pragma('vm:entry-point') - static void checkCloseCampaign(Map args) async { - DartPluginRegistrant.ensureInitialized(); - DbCampaignModel db = DbCampaignModel(); - List res = []; - String accountAddress = args['accountAddress']; - - final FlutterLocalNotificationsPlugin notification = - FlutterLocalNotificationsPlugin(); - - await notification - .resolvePlatformSpecificImplementation< - AndroidFlutterLocalNotificationsPlugin>() - ?.createNotificationChannel(NotificationChannel.importantChannel); - - Timer.periodic(const Duration(seconds: 60), (timer) async { - ServicesControllerV2.statusCloseCampaignService = true; - res = await db.campaigns(); - if (res.isNotEmpty) { - for (Campaign c in res) { - String address = c.address; - String title = c.title; - - SmartContractModelBs smartContract = SmartContractModelBs( - contractAddress: address, - abiName: 'Campaign', - abiFileRoot: 'assets/abi_campaign.json', - accountAddress: accountAddress); - - List? isClosedRaw = - await smartContract.queryCall('isClosed', []); - - if (isClosedRaw != null) { - String answer = isClosedRaw[0].toString(); - - if (answer == "true") { - // the campaign result closed - if (kDebugMode) { - print('\x1B[31mThe campaign was closed\x1B[0m'); - } - - notification.show( - 888, - 'Campaign Closed', - 'The campaign [$title] \nat address $address \n was closed by crowdsourcer', - const NotificationDetails( - android: AndroidNotificationDetails( - 'important_channel', - 'MY FOREGROUND SERVICE', - icon: 'ic_bg_service_small', - ongoing: false, - ), - ), - ); - - await db.deleteCampaign(address); - } else { - if (kDebugMode) { - print( - '\x1B[31m [CLOSED CAMPAIGN SERVICE] The campaign still open: nothing to notify. \x1B[0m'); - } - } - } else { - if (kDebugMode) { - print( - '\x1B[31m [CLOSED CAMPAIGN SERVICE]an error occurred. \x1B[0m'); - } - } - } - } else { - ServicesControllerV2.statusCloseCampaignService = false; - timer.cancel(); - if (kDebugMode) { - print( - '\x1B[31m [CLOSED CAMPAIGN SERVICE] No campaigns to follow. stop the service.\x1B[0m'); - } - } - }); - } - - @pragma('vm:entry-point') - static void checkGeofence(Map args) async { - DartPluginRegistrant.ensureInitialized(); - String debugString = "[GEOFENCE ${args["title"]!}"; - - final FlutterLocalNotificationsPlugin notification = - FlutterLocalNotificationsPlugin(); - - await notification - .resolvePlatformSpecificImplementation< - AndroidFlutterLocalNotificationsPlugin>() - ?.createNotificationChannel(NotificationChannel.importantChannel); - - if (kDebugMode) { - print('\x1B[31m [GEOFENCE SERVICE] geofence open for:' - '\n ${args['title']!}' - '\n ${args['address']!}' - '\n ${args['lat']!} ' - '\n ${args['lng']!} \x1B[0m'); - } - - await Geofence.startGeofenceService( - pointedLatitude: args['lat']!, - pointedLongitude: args['lng']!, - radiusMeter: args['radius']!, - eventPeriodInSeconds: 10); - - GeofenceEvent? previous; - - Geofence.getGeofenceStream()?.listen((GeofenceEvent event) { - if (kDebugMode) { - print(event.toString()); - } - - if (previous == null || previous == GeofenceEvent.init) { - switch (event) { - case GeofenceEvent.enter: - previous = event; - break; - case GeofenceEvent.exit: - previous = event; - break; - default: - previous = event; - break; - } - } - - switch (event) { - case GeofenceEvent.init: - if (kDebugMode) { - print('\x1B[31m $debugString status: Init\x1B[0m'); - } - previous = event; - break; - case GeofenceEvent.enter: - if (kDebugMode) { - print('\x1B[31m $debugString status: Enter\x1B[0m'); - } - (previous != event) - ? notification.show( - 888, - 'Entered in Campaign Area', - '[${args['title']!}] \nat address: ${args['address']!}', - const NotificationDetails( - android: AndroidNotificationDetails( - 'important_channel', - 'MY FOREGROUND SERVICE', - icon: 'ic_bg_service_small', - styleInformation: BigTextStyleInformation( - "

String bigText

sisisisisisisisisi

", - htmlFormatBigText: true, - contentTitle: "

this is title

", - htmlFormatContentTitle: true, - summaryText: "

this is the summary text

", - htmlFormatSummaryText: true, - htmlFormatContent : true, - htmlFormatTitle : true - ), - ongoing: true, - ), - ), - ) - : print('\x1B[31m $debugString status not changed \x1B[0m'); - previous = event; - break; - case GeofenceEvent.exit: - if (kDebugMode) { - print('\x1B[31m $debugString status: Exit\x1B[0m'); - } - (previous != event) - ? notification.show( - 888, - 'Exit from Campaign Area', - '[${args['title']!}] \nat address: ${args['address']!}', - const NotificationDetails( - android: AndroidNotificationDetails( - 'important_channel', - 'MY FOREGROUND SERVICE', - icon: 'ic_bg_service_small', - ongoing: true, - ), - )) - : print('\x1B[31m $debugString status not changed \x1B[0m'); - previous = event; - - break; - } - }); - } -} - -class SmartContractModelBs { - SmartContractModelBs( - {required this.accountAddress, - required this.contractAddress, - required this.abiName, - required this.abiFileRoot}); - - final String accountAddress; - final String contractAddress; - final String abiName; - final String abiFileRoot; - late http.Client httpClient; - late Web3Client ethClient; - - Future loadContract(String contractAddress) async { - String abi = await rootBundle.loadString(abiFileRoot); - final contract = DeployedContract(ContractAbi.fromJson(abi, abiName), - EthereumAddress.fromHex(contractAddress)); - return contract; - } - - Future?> queryCall( - String functionName, List args) async { - try { - httpClient = http.Client(); - ethClient = Web3Client( - "https://goerli.infura.io/v3/5074605772bb4bc4b6970d2ce999efca", - httpClient); - - final contract = await loadContract(contractAddress); - final ethFunction = contract.function(functionName); - final result = await ethClient.call( - sender: EthereumAddress.fromHex(accountAddress), - contract: contract, - function: ethFunction, - params: args); - List res = result; - return res; - } catch (e) { - if (kDebugMode) { - print('\x1B[31m$e\x1B[0m'); - } - return null; - } - } -} diff --git a/lib/services/servicesV2.dart b/lib/services/servicesV2.dart index d0a58d6..12b00bd 100644 --- a/lib/services/servicesV2.dart +++ b/lib/services/servicesV2.dart @@ -11,30 +11,17 @@ import 'package:web3dart/web3dart.dart'; import '../models/db_capaign_model.dart'; import 'dart:async'; import 'dart:ui'; -import 'package:geofence_flutter/geofence_flutter.dart'; import 'package:flutter/material.dart'; import 'package:flutter_background_service_android/flutter_background_service_android.dart'; +import '../models/geofence_model.dart'; class ServicesV2 { - - static Future onIosBackground(ServiceInstance service) async { - WidgetsFlutterBinding.ensureInitialized(); + static void onStart(ServiceInstance service) async { DartPluginRegistrant.ensureInitialized(); SharedPreferences preferences = await SharedPreferences.getInstance(); await preferences.reload(); - final log = preferences.getStringList('log') ?? []; - log.add(DateTime.now().toIso8601String()); - await preferences.setStringList('log', log); - - return true; - } - - static void checkCloseCampaign(ServiceInstance service) async { - DartPluginRegistrant.ensureInitialized(); - - SharedPreferences preferences = await SharedPreferences.getInstance(); if (service is AndroidServiceInstance) { service.on('setAsForeground').listen((event) { @@ -54,15 +41,12 @@ class ServicesV2 { List res = []; String accountAddress = preferences.getString('address')!; - final FlutterLocalNotificationsPlugin notification = - FlutterLocalNotificationsPlugin(); + List geoList = []; - await notification - .resolvePlatformSpecificImplementation< - AndroidFlutterLocalNotificationsPlugin>() - ?.createNotificationChannel(NotificationChannel.importantChannel_2); + final FlutterLocalNotificationsPlugin notification = + FlutterLocalNotificationsPlugin(); - Timer.periodic(const Duration(seconds: 60), (timer) async { + Timer.periodic(const Duration(minutes: 1), (timer) async { ServicesControllerV2.statusCloseCampaignService = true; res = await db.campaigns(); if (res.isNotEmpty) { @@ -77,7 +61,7 @@ class ServicesV2 { accountAddress: accountAddress); List? isClosedRaw = - await smartContract.queryCall('isClosed', []); + await smartContract.queryCall('isClosed', []); if (isClosedRaw != null) { String answer = isClosedRaw[0].toString(); @@ -92,10 +76,10 @@ class ServicesV2 { 999, 'Campaign Closed', 'The campaign [$title] \nat address $address \n was closed by crowdsourcer', - NotificationDetails( + NotificationDetails( android: AndroidNotificationDetails( - NotificationChannel.importantChannel_2.id, - NotificationChannel.importantChannel_2.name, + 'geofence_channel', + NotificationChannel.backgroundServiceChannel.name, icon: 'ic_bg_service_small', ongoing: false, ), @@ -116,10 +100,22 @@ class ServicesV2 { } } } + + //..... + geoList.forEach((element) {element.stopGeofenceService();}); + geoList.clear(); + for (Campaign c in res) { + Geofence g = Geofence(c.title, c.address, c.lat, c.lng, "20");//c.radius); + geoList.add(g); + g.initialize(); + } + print('\x1B[31m [GEOFENCE SERVICE] active geofences: ${geoList.length}. \x1B[0m'); } else { ServicesControllerV2.statusCloseCampaignService = false; timer.cancel(); - service.invoke('stopService'); + geoList.forEach((element) {element.stopGeofenceService();}); + geoList.clear(); + service.stopSelf(); if (kDebugMode) { print( '\x1B[31m [CLOSED CAMPAIGN SERVICE] No campaigns to follow. stop the service.\x1B[0m'); @@ -128,132 +124,17 @@ class ServicesV2 { }); } - static void checkGeofence(ServiceInstance service) async { - + static Future onIosBackground(ServiceInstance service) async { + WidgetsFlutterBinding.ensureInitialized(); DartPluginRegistrant.ensureInitialized(); SharedPreferences preferences = await SharedPreferences.getInstance(); + await preferences.reload(); + final log = preferences.getStringList('log') ?? []; + log.add(DateTime.now().toIso8601String()); + await preferences.setStringList('log', log); - if (service is AndroidServiceInstance) { - service.on('setAsForeground').listen((event) { - service.setAsForegroundService(); - }); - - service.on('setAsBackground').listen((event) { - service.setAsBackgroundService(); - }); - } - - service.on('stopService').listen((event) { - service.stopSelf(); - }); - - String debugString = "[GEOFENCE ${preferences.getString("title")!}"; - - final FlutterLocalNotificationsPlugin notification = - FlutterLocalNotificationsPlugin(); - - await notification - .resolvePlatformSpecificImplementation< - AndroidFlutterLocalNotificationsPlugin>() - ?.createNotificationChannel(NotificationChannel.importantChannel); - - if (kDebugMode) { - print('\x1B[31m [GEOFENCE SERVICE] geofence open for:' - '\n ${preferences.getString('title')!}' - '\n ${preferences.getString('address')!}' - '\n ${preferences.getString('lat')!} ' - '\n ${preferences.getString('lng')!} \x1B[0m'); - } - - await Geofence.startGeofenceService( - pointedLatitude: preferences.getString('lat')!, - pointedLongitude: preferences.getString('lng')!, - radiusMeter: preferences.getString('radius')!, - eventPeriodInSeconds: 10); - - GeofenceEvent? previous; - - Geofence.getGeofenceStream()?.listen((GeofenceEvent event) { - if (kDebugMode) { - print(event.toString()); - } - - if (previous == null || previous == GeofenceEvent.init) { - switch (event) { - case GeofenceEvent.enter: - previous = event; - break; - case GeofenceEvent.exit: - previous = event; - break; - default: - previous = event; - break; - } - } - - switch (event) { - case GeofenceEvent.init: - if (kDebugMode) { - print('\x1B[31m $debugString status: Init\x1B[0m'); - } - previous = event; - break; - case GeofenceEvent.enter: - if (kDebugMode) { - print('\x1B[31m $debugString status: Enter\x1B[0m'); - } - (previous != event) - ? notification.show( - 888, - 'Entered in Campaign Area', - '[${preferences.getString('title')!}] \nat address: ${preferences.getString('address')!}', - const NotificationDetails( - android: AndroidNotificationDetails( - 'important_channel', - 'MY FOREGROUND SERVICE', - icon: 'ic_bg_service_small', - styleInformation: BigTextStyleInformation( - "

String bigText

sisisisisisisisisi

", - htmlFormatBigText: true, - contentTitle: "

this is title

", - htmlFormatContentTitle: true, - summaryText: "

this is the summary text

", - htmlFormatSummaryText: true, - htmlFormatContent : true, - htmlFormatTitle : true - ), - ongoing: true, - ), - ), - ) - : print('\x1B[31m $debugString status not changed \x1B[0m'); - previous = event; - break; - case GeofenceEvent.exit: - if (kDebugMode) { - print('\x1B[31m $debugString status: Exit\x1B[0m'); - } - (previous != event) - ? notification.show( - 888, - 'Exit from Campaign Area', - '[${preferences.getString('title')!}] \nat address: ${preferences.getString('address')!}', - NotificationDetails( - android: AndroidNotificationDetails( - NotificationChannel.importantChannel.id, - NotificationChannel.importantChannel.name, - icon: 'ic_bg_service_small', - ongoing: true, - ), - )) - : print('\x1B[31m $debugString status not changed \x1B[0m'); - previous = event; - - break; - } - }); + return true; } } diff --git a/lib/services/services_controller.dart b/lib/services/services_controller.dart deleted file mode 100644 index 355a37b..0000000 --- a/lib/services/services_controller.dart +++ /dev/null @@ -1,47 +0,0 @@ -import 'package:flutter_isolate/flutter_isolate.dart'; -import 'package:flutter_background_service/flutter_background_service.dart'; - -import 'package:mobile_crowd_sensing/services/services.dart'; -import '../models/db_capaign_model.dart'; -import '../models/session_model.dart'; - - -class ServicesController{ - - static bool statusCloseCampaignService = false; - static bool statusGeofencingService = false; - - static void initializeCloseCampaignService() async { - FlutterIsolate.spawn(Services.checkCloseCampaign, { - 'accountAddress' : SessionModel().getAccountAddress() - }); - statusCloseCampaignService = true; - } - - static Future initializeGeofencingService() async { - - DbCampaignModel db = DbCampaignModel(); - List res = await db.campaigns(); - if(res.isNotEmpty) { - statusGeofencingService = true; - for(Campaign c in res) { - FlutterIsolate.spawn(Services.checkGeofence, { - 'address' : c.address, - 'title' : c.title, - 'lat' : c.lat, - 'lng' : c.lng, - 'radius' : c.radius - }); - } - } - - } - - static void resetServicies() async { - FlutterIsolate.killAll(); - statusCloseCampaignService = true; - statusGeofencingService = true; - initializeCloseCampaignService(); - initializeGeofencingService(); - } -} \ No newline at end of file diff --git a/lib/services/services_controllerV2.dart b/lib/services/services_controllerV2.dart index 70a7bb5..fd02d47 100644 --- a/lib/services/services_controllerV2.dart +++ b/lib/services/services_controllerV2.dart @@ -1,4 +1,5 @@ import 'package:flutter_background_service/flutter_background_service.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:mobile_crowd_sensing/services/servicesV2.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../models/db_capaign_model.dart'; @@ -7,74 +8,40 @@ import 'notification_channels.dart'; class ServicesControllerV2 { static bool statusCloseCampaignService = false; static bool statusGeofencingService = false; - static List servicesList = []; + static void initializeCloseCampaignService() async { FlutterBackgroundService s = FlutterBackgroundService(); + final FlutterLocalNotificationsPlugin notification = + FlutterLocalNotificationsPlugin(); + await notification + .resolvePlatformSpecificImplementation< + AndroidFlutterLocalNotificationsPlugin>() + ?.createNotificationChannel(NotificationChannel.backgroundServiceChannel); + s.configure( androidConfiguration: AndroidConfiguration( - onStart: ServicesV2.checkCloseCampaign, + onStart: ServicesV2.onStart, autoStart: true, isForegroundMode: true, - notificationChannelId: NotificationChannel.importantChannel_2.id, - initialNotificationTitle: NotificationChannel.importantChannel_2.name, - initialNotificationContent: 'closing campaign service', - foregroundServiceNotificationId: 888, + notificationChannelId: NotificationChannel.backgroundServiceChannel.id, + initialNotificationTitle: NotificationChannel.backgroundServiceChannel.name, + initialNotificationContent: 'service initialized', + foregroundServiceNotificationId: 999, ), iosConfiguration: IosConfiguration( autoStart: true, - onForeground: ServicesV2.checkCloseCampaign, + onForeground: ServicesV2.onStart, onBackground: ServicesV2.onIosBackground, ), ); - servicesList.add(s); + s.startService(); statusCloseCampaignService = true; } - static Future initializeGeofencingService() async { - DbCampaignModel db = DbCampaignModel(); - List res = await db.campaigns(); - if (res.isNotEmpty) { - statusGeofencingService = true; - for (Campaign c in res) { - FlutterBackgroundService s = FlutterBackgroundService(); - SharedPreferences shared = await SharedPreferences.getInstance(); - shared.setString('address',c.address); - shared.setString('title', c.title); - shared.setString('lat',c.lat); - shared.setString('lng',c.lng); - shared.setString('radius', c.radius); - s.configure( - androidConfiguration: AndroidConfiguration( - onStart: ServicesV2.checkGeofence, - autoStart: true, - isForegroundMode: true, - - notificationChannelId: NotificationChannel.importantChannel.id, - initialNotificationTitle: NotificationChannel.importantChannel.name, - initialNotificationContent: 'geofence: ${c.title}', - foregroundServiceNotificationId: 999, - ), - iosConfiguration: IosConfiguration( - autoStart: true, - onForeground: ServicesV2.checkGeofence, - onBackground: ServicesV2.onIosBackground, - ), - ); - print('\x1B[31m sono iniziato almeno? ${await s.startService()}\x1B[0m'); - servicesList.add(s); - } - } - } - static void resetServicies() async { - servicesList.forEach((element) { - element.invoke('stopService'); - }); statusCloseCampaignService = true; - statusGeofencingService = true; initializeCloseCampaignService(); - initializeGeofencingService(); } } diff --git a/pubspec.lock b/pubspec.lock index cc0d45d..dcc00dc 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,343 +5,392 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - url: "https://pub.dartlang.org" + sha256: "0c80aeab9bc807ab10022cd3b2f4cf2ecdf231949dc1ddd9442406a003f19201" + url: "https://pub.dev" source: hosted - version: "50.0.0" + version: "52.0.0" analyzer: dependency: transitive description: name: analyzer - url: "https://pub.dartlang.org" + sha256: cd8ee83568a77f3ae6b913a36093a1c9b1264e7cb7f834d9ddd2311dade9c1f4 + url: "https://pub.dev" source: hosted - version: "5.2.0" + version: "5.4.0" archive: dependency: "direct main" description: name: archive - url: "https://pub.dartlang.org" + sha256: d6347d54a2d8028e0437e3c099f66fdb8ae02c4720c1e7534c9f24c10351f85d + url: "https://pub.dev" source: hosted version: "3.3.6" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: "139d809800a412ebb26a3892da228b2d0ba36f0ef5d9a82166e5e52ec8d61611" + url: "https://pub.dev" source: hosted version: "2.3.2" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + url: "https://pub.dev" source: hosted - version: "2.9.0" + version: "2.10.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" build: dependency: transitive description: name: build - url: "https://pub.dartlang.org" + sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" + url: "https://pub.dev" source: hosted version: "2.3.1" build_config: dependency: transitive description: name: build_config - url: "https://pub.dartlang.org" + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" source: hosted version: "1.1.1" build_daemon: dependency: transitive description: name: build_daemon - url: "https://pub.dartlang.org" + sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" + url: "https://pub.dev" source: hosted version: "3.1.0" build_resolvers: dependency: transitive description: name: build_resolvers - url: "https://pub.dartlang.org" + sha256: "7c35a3a7868626257d8aee47b51c26b9dba11eaddf3431117ed2744951416aab" + url: "https://pub.dev" source: hosted version: "2.1.0" build_runner: dependency: "direct main" description: name: build_runner - url: "https://pub.dartlang.org" + sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + url: "https://pub.dev" source: hosted version: "2.3.3" build_runner_core: dependency: transitive description: name: build_runner_core - url: "https://pub.dartlang.org" + sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" + url: "https://pub.dev" source: hosted version: "7.2.7" built_collection: dependency: transitive description: name: built_collection - url: "https://pub.dartlang.org" + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" source: hosted version: "5.1.1" built_value: dependency: transitive description: name: built_value - url: "https://pub.dartlang.org" + sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725" + url: "https://pub.dev" source: hosted version: "8.4.3" cached_network_image: dependency: transitive description: name: cached_network_image - url: "https://pub.dartlang.org" + sha256: fd3d0dc1d451f9a252b32d95d3f0c3c487bc41a75eba2e6097cb0b9c71491b15 + url: "https://pub.dev" source: hosted version: "3.2.3" cached_network_image_platform_interface: dependency: transitive description: name: cached_network_image_platform_interface - url: "https://pub.dartlang.org" + sha256: bb2b8403b4ccdc60ef5f25c70dead1f3d32d24b9d6117cfc087f496b178594a7 + url: "https://pub.dev" source: hosted version: "2.0.0" cached_network_image_web: dependency: transitive description: name: cached_network_image_web - url: "https://pub.dartlang.org" + sha256: b8eb814ebfcb4dea049680f8c1ffb2df399e4d03bf7a352c775e26fa06e02fa0 + url: "https://pub.dev" source: hosted version: "1.0.2" camera: dependency: "direct main" description: name: camera - url: "https://pub.dartlang.org" + sha256: e7ac55af24a890d20276821eb3c95857074d03b7de6f9892b99a205ee30bd179 + url: "https://pub.dev" source: hosted version: "0.10.3" camera_android: dependency: transitive description: name: camera_android - url: "https://pub.dartlang.org" + sha256: e491c836147f60dd8a54cf3895fd2960e13b21b78a9d15b563a1b6c70894f142 + url: "https://pub.dev" source: hosted version: "0.10.4" camera_avfoundation: dependency: transitive description: name: camera_avfoundation - url: "https://pub.dartlang.org" + sha256: "6a68c20593d4cd58974d555f74a48b244f9db28cc9156de57781122d11b8754b" + url: "https://pub.dev" source: hosted version: "0.9.11" camera_platform_interface: dependency: transitive description: name: camera_platform_interface - url: "https://pub.dartlang.org" + sha256: b632be28e61d00a233f67d98ea90fd7041956f27a1c65500188ee459be60e15f + url: "https://pub.dev" source: hosted - version: "2.3.4" + version: "2.4.0" camera_web: dependency: transitive description: name: camera_web - url: "https://pub.dartlang.org" + sha256: "496de93c5d462738ce991dbfe91fb19026f115ed36406700a20a380fb0018299" + url: "https://pub.dev" source: hosted version: "0.3.1+1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + url: "https://pub.dev" source: hosted version: "1.2.1" checked_yaml: dependency: transitive description: name: checked_yaml - url: "https://pub.dartlang.org" + sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" + url: "https://pub.dev" source: hosted version: "2.0.2" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted version: "1.1.1" code_builder: dependency: transitive description: name: code_builder - url: "https://pub.dartlang.org" + sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" + url: "https://pub.dev" source: hosted version: "4.4.0" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" connectivity: dependency: "direct main" description: name: connectivity - url: "https://pub.dartlang.org" + sha256: a8e91263cf3e25fb5cc95e19dfde4999e32a648ac3b9e8a558a28165731678f8 + url: "https://pub.dev" source: hosted version: "3.0.6" connectivity_for_web: dependency: transitive description: name: connectivity_for_web - url: "https://pub.dartlang.org" + sha256: "01a390c1d5adc2ed1fa1f52d120c07fe9fd01166a93f965a832fd6cfc0ea6482" + url: "https://pub.dev" source: hosted version: "0.4.0+1" connectivity_macos: dependency: transitive description: name: connectivity_macos - url: "https://pub.dartlang.org" + sha256: "51ae08d5162eca9669b9d8951ed83ce19c5355a81149f94e4dee2740beb93628" + url: "https://pub.dev" source: hosted version: "0.2.1+2" connectivity_platform_interface: dependency: transitive description: name: connectivity_platform_interface - url: "https://pub.dartlang.org" + sha256: "2d82e942df9d49f29a24bb07fb5ce085d4a53e47818c62364d2b6deb9e0d7a8e" + url: "https://pub.dev" source: hosted version: "2.0.1" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" source: hosted version: "3.1.1" cross_file: dependency: transitive description: name: cross_file - url: "https://pub.dartlang.org" + sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9" + url: "https://pub.dev" source: hosted version: "0.3.3+4" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" source: hosted version: "3.0.2" cryptography: dependency: transitive description: name: cryptography - url: "https://pub.dartlang.org" + sha256: e0e37f79665cd5c86e8897f9abe1accfe813c0cc5299dab22256e22fddc1fef8 + url: "https://pub.dev" source: hosted version: "2.0.5" csslib: dependency: transitive description: name: csslib - url: "https://pub.dartlang.org" + sha256: b36c7f7e24c0bdf1bf9a3da461c837d1de64b9f8beb190c9011d8c72a3dfd745 + url: "https://pub.dev" source: hosted version: "0.17.2" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - url: "https://pub.dartlang.org" + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" source: hosted version: "1.0.5" dart_style: dependency: transitive description: name: dart_style - url: "https://pub.dartlang.org" + sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" + url: "https://pub.dev" source: hosted version: "2.2.4" dbus: dependency: transitive description: name: dbus - url: "https://pub.dartlang.org" + sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263" + url: "https://pub.dev" source: hosted version: "0.7.8" device_info_plus: dependency: "direct main" description: name: device_info_plus - url: "https://pub.dartlang.org" + sha256: "7ff671ed0a6356fa8f2e1ae7d3558d3fb7b6a41e24455e4f8df75b811fb8e4ab" + url: "https://pub.dev" source: hosted version: "8.0.0" device_info_plus_platform_interface: dependency: transitive description: name: device_info_plus_platform_interface - url: "https://pub.dartlang.org" + sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 + url: "https://pub.dev" source: hosted version: "7.0.0" - dio: + eip1559: dependency: transitive description: - name: dio - url: "https://pub.dartlang.org" + name: eip1559 + sha256: de454d6321bd753eb79116e9ec4f8df20895c2e97f9a3839a032f3a728985516 + url: "https://pub.dev" source: hosted - version: "4.0.6" + version: "0.6.1" eip55: dependency: transitive description: name: eip55 - url: "https://pub.dartlang.org" + sha256: "213a9b86add87a5216328e8494b0ab836e401210c4d55eb5e521bd39e39169e1" + url: "https://pub.dev" source: hosted version: "1.0.2" environment_sensors: dependency: "direct main" description: name: environment_sensors - url: "https://pub.dartlang.org" + sha256: "814c78232a2043762cb015bebd90b51cb95a37e6c636a91189f9193eabbddf78" + url: "https://pub.dev" source: hosted version: "0.2.0" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted version: "1.3.1" ffi: dependency: transitive description: name: ffi - url: "https://pub.dartlang.org" + sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + url: "https://pub.dev" source: hosted version: "2.0.1" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" source: hosted version: "6.1.4" fixnum: dependency: transitive description: name: fixnum - url: "https://pub.dartlang.org" + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.1.0" flip_card: dependency: "direct main" description: name: flip_card - url: "https://pub.dartlang.org" + sha256: "5d4aa58f3983cced0782f4ce45826b7eea36e8e464964d9209dcbc7a87b2292f" + url: "https://pub.dev" source: hosted version: "0.7.0" flutter: @@ -353,126 +402,144 @@ packages: dependency: "direct main" description: name: flutter_background_service - url: "https://pub.dartlang.org" + sha256: "7b9f15ab7d1a5784850ecfde722be4ace4dbcf1072a1fe33b7f9cbe871241e53" + url: "https://pub.dev" source: hosted version: "2.4.6" flutter_background_service_android: dependency: transitive description: name: flutter_background_service_android - url: "https://pub.dartlang.org" + sha256: "57fd631d800f7e56ca5bfadcfc00c8903eb721b23506b1a387342039521883ec" + url: "https://pub.dev" source: hosted version: "3.0.3" flutter_background_service_ios: dependency: transitive description: name: flutter_background_service_ios - url: "https://pub.dartlang.org" + sha256: d3f1dc009137c1ac19f5e3d88668836f088a7e078396733547339765d46ff12f + url: "https://pub.dev" source: hosted version: "2.4.0" flutter_background_service_platform_interface: dependency: transitive description: name: flutter_background_service_platform_interface - url: "https://pub.dartlang.org" + sha256: "5f0480ee8378984f718d640abbe09b4d6d024d58a72b2d8b86bdedb3cf095ff8" + url: "https://pub.dev" source: hosted version: "2.2.0" flutter_blurhash: dependency: transitive description: name: flutter_blurhash - url: "https://pub.dartlang.org" + sha256: "05001537bd3fac7644fa6558b09ec8c0a3f2eba78c0765f88912882b1331a5c6" + url: "https://pub.dev" source: hosted version: "0.7.0" flutter_cache_manager: dependency: transitive description: name: flutter_cache_manager - url: "https://pub.dartlang.org" + sha256: "32cd900555219333326a2d0653aaaf8671264c29befa65bbd9856d204a4c9fb3" + url: "https://pub.dev" source: hosted version: "3.3.0" flutter_config: dependency: "direct main" description: name: flutter_config - url: "https://pub.dartlang.org" + sha256: "8e2be2d560a52e06d2ef53a31913a11fc80ef708a442571c96194fd32e29fb1a" + url: "https://pub.dev" source: hosted version: "2.0.0" flutter_foreground_task: dependency: "direct main" description: name: flutter_foreground_task - url: "https://pub.dartlang.org" + sha256: "5eb81adfd98c77f4d4803ae80d7e0573fd35f706fce6aaa7376656a15ba2d1e0" + url: "https://pub.dev" source: hosted version: "3.10.0" flutter_intl: dependency: "direct main" description: name: flutter_intl - url: "https://pub.dartlang.org" + sha256: "17b138fab0477c7d17abd8ba67d294786eef8fe80342e58b6253aef7d0ca2bad" + url: "https://pub.dev" source: hosted version: "0.0.1" flutter_isolate: dependency: "direct main" description: name: flutter_isolate - url: "https://pub.dartlang.org" + sha256: "994ddec596da4ca12ca52154fd59404077584643eb7e3f1008a55fda9fe0b76b" + url: "https://pub.dev" source: hosted version: "2.0.4" flutter_lints: dependency: "direct dev" description: name: flutter_lints - url: "https://pub.dartlang.org" + sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + url: "https://pub.dev" source: hosted version: "2.0.1" flutter_local_notifications: dependency: "direct main" description: name: flutter_local_notifications - url: "https://pub.dartlang.org" + sha256: "293995f94e120c8afce768981bd1fa9c5d6de67c547568e3b42ae2defdcbb4a0" + url: "https://pub.dev" source: hosted version: "13.0.0" flutter_local_notifications_linux: dependency: transitive description: name: flutter_local_notifications_linux - url: "https://pub.dartlang.org" + sha256: "8f6c1611e0c4a88a382691a97bb3c3feb24cc0c0b54152b8b5fb7ffb837f7fbf" + url: "https://pub.dev" source: hosted version: "3.0.0" flutter_local_notifications_platform_interface: dependency: transitive description: name: flutter_local_notifications_platform_interface - url: "https://pub.dartlang.org" + sha256: "5ec1feac5f7f7d9266759488bc5f76416152baba9aa1b26fe572246caa00d1ab" + url: "https://pub.dev" source: hosted version: "6.0.0" flutter_map: dependency: transitive description: name: flutter_map - url: "https://pub.dartlang.org" + sha256: "59dfd14267b691bea55760786b47d3172d47cdcc0d79ff930746a5ad123491b8" + url: "https://pub.dev" source: hosted version: "3.1.0" flutter_native_splash: dependency: "direct main" description: name: flutter_native_splash - url: "https://pub.dartlang.org" + sha256: "048bd1f1dc0e5ea25899f702815934d9a9e916fe23451c320e7dd94d5e3ad933" + url: "https://pub.dev" source: hosted version: "2.2.17" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - url: "https://pub.dartlang.org" + sha256: "60fc7b78455b94e6de2333d2f95196d32cf5c22f4b0b0520a628804cb463503b" + url: "https://pub.dev" source: hosted version: "2.0.7" flutter_spinkit: dependency: "direct main" description: name: flutter_spinkit - url: "https://pub.dartlang.org" + sha256: "77a2117c0517ff909221f3160b8eb20052ab5216107581168af574ac1f05dff8" + url: "https://pub.dev" source: hosted version: "5.1.0" flutter_test: @@ -489,546 +556,608 @@ packages: dependency: transitive description: name: frontend_server_client - url: "https://pub.dartlang.org" + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" source: hosted version: "3.2.0" geocoding: dependency: "direct main" description: name: geocoding - url: "https://pub.dartlang.org" + sha256: "26218460a902d4249b81e6baf9d55ce400fd1ebe6fc0a7e92b2c12b0b8e1e14e" + url: "https://pub.dev" source: hosted version: "2.0.5" geocoding_platform_interface: dependency: transitive description: name: geocoding_platform_interface - url: "https://pub.dartlang.org" + sha256: "8848605d307d844d89937cdb4b8ad7dfa880552078f310fa24d8a460f6dddab4" + url: "https://pub.dev" source: hosted version: "2.0.1" - geofence_flutter: - dependency: "direct main" - description: - name: geofence_flutter - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" geolocator: dependency: "direct main" description: name: geolocator - url: "https://pub.dartlang.org" + sha256: "5c23f3613f50586c0bbb2b8f970240ae66b3bd992088cf60dd5ee2e6f7dde3a8" + url: "https://pub.dev" source: hosted version: "9.0.2" geolocator_android: dependency: transitive description: name: geolocator_android - url: "https://pub.dartlang.org" + sha256: "2ba24690aee0a3e1b6b7bd47c2711a50c874e95e4c758346589d35194adf6d6a" + url: "https://pub.dev" source: hosted version: "4.1.7" geolocator_apple: dependency: transitive description: name: geolocator_apple - url: "https://pub.dartlang.org" + sha256: "22b60ca3b8c0f58e6a9688ff855ee39ab813ca3f0c0609a48d282f6631266f2e" + url: "https://pub.dev" source: hosted version: "2.2.5" geolocator_platform_interface: dependency: transitive description: name: geolocator_platform_interface - url: "https://pub.dartlang.org" + sha256: af4d69231452f9620718588f41acc4cb58312368716bfff2e92e770b46ce6386 + url: "https://pub.dev" source: hosted version: "4.0.7" geolocator_web: dependency: transitive description: name: geolocator_web - url: "https://pub.dartlang.org" + sha256: f68a122da48fcfff68bbc9846bb0b74ef651afe84a1b1f6ec20939de4d6860e1 + url: "https://pub.dev" source: hosted version: "2.1.6" geolocator_windows: dependency: transitive description: name: geolocator_windows - url: "https://pub.dartlang.org" + sha256: f5911c88e23f48b598dd506c7c19eff0e001645bdc03bb6fecb9f4549208354d + url: "https://pub.dev" source: hosted version: "0.1.1" glob: dependency: transitive description: name: glob - url: "https://pub.dartlang.org" + sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" + url: "https://pub.dev" source: hosted version: "2.1.1" google_fonts: dependency: "direct main" description: name: google_fonts - url: "https://pub.dartlang.org" + sha256: "8f099045e2f2a30e4d4d0a35f40c6bc941a8f2ca0e10ad9d214ee9edd3f37483" + url: "https://pub.dev" source: hosted version: "3.0.1" graphs: dependency: transitive description: name: graphs - url: "https://pub.dartlang.org" + sha256: f9e130f3259f52d26f0cfc0e964513796dafed572fa52e45d2f8d6ca14db39b2 + url: "https://pub.dev" source: hosted version: "2.2.0" html: dependency: transitive description: name: html - url: "https://pub.dartlang.org" + sha256: d9793e10dbe0e6c364f4c59bf3e01fb33a9b2a674bc7a1081693dba0614b6269 + url: "https://pub.dev" source: hosted version: "0.15.1" http: dependency: "direct main" description: name: http - url: "https://pub.dartlang.org" + sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + url: "https://pub.dev" source: hosted version: "0.13.5" http_multi_server: dependency: transitive description: name: http_multi_server - url: "https://pub.dartlang.org" + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" source: hosted version: "3.2.1" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" source: hosted version: "4.0.2" image: dependency: transitive description: name: image - url: "https://pub.dartlang.org" + sha256: "3686865febd85c57a632d87a0fb1f0a8a9ef602fdb68d909c3e9aa29ec70fd24" + url: "https://pub.dev" source: hosted version: "4.0.13" infinite_listview: dependency: transitive description: name: infinite_listview - url: "https://pub.dartlang.org" + sha256: f6062c1720eb59be553dfa6b89813d3e8dd2f054538445aaa5edaddfa5195ce6 + url: "https://pub.dev" source: hosted version: "1.1.0" intl: dependency: "direct main" description: name: intl - url: "https://pub.dartlang.org" + sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + url: "https://pub.dev" source: hosted version: "0.17.0" io: dependency: transitive description: name: io - url: "https://pub.dartlang.org" + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" source: hosted version: "1.0.4" - ipfs_client_flutter: - dependency: "direct main" - description: - name: ipfs_client_flutter - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.7" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + url: "https://pub.dev" source: hosted - version: "0.6.4" + version: "0.6.5" json_annotation: dependency: transitive description: name: json_annotation - url: "https://pub.dartlang.org" + sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 + url: "https://pub.dev" source: hosted version: "4.8.0" json_rpc_2: dependency: transitive description: name: json_rpc_2 - url: "https://pub.dartlang.org" + sha256: "5e469bffa23899edacb7b22787780068d650b106a21c76db3c49218ab7ca447e" + url: "https://pub.dev" source: hosted version: "3.0.2" latlong2: dependency: transitive description: name: latlong2 - url: "https://pub.dartlang.org" + sha256: "408993a0e3f46e79ce1f129e4cb0386eef6d48dfa6394939ecacfbd7049154ec" + url: "https://pub.dev" source: hosted version: "0.8.1" lints: dependency: transitive description: name: lints - url: "https://pub.dartlang.org" + sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + url: "https://pub.dev" source: hosted version: "2.0.1" lists: dependency: transitive description: name: lists - url: "https://pub.dartlang.org" + sha256: "4ca5c19ae4350de036a7e996cdd1ee39c93ac0a2b840f4915459b7d0a7d4ab27" + url: "https://pub.dev" source: hosted version: "1.0.1" logging: dependency: transitive description: name: logging - url: "https://pub.dartlang.org" + sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + url: "https://pub.dev" source: hosted version: "1.1.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + url: "https://pub.dev" source: hosted - version: "0.12.12" + version: "0.12.13" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" source: hosted - version: "0.1.5" + version: "0.2.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + url: "https://pub.dev" source: hosted version: "1.8.0" mgrs_dart: dependency: transitive description: name: mgrs_dart - url: "https://pub.dartlang.org" + sha256: fb89ae62f05fa0bb90f70c31fc870bcbcfd516c843fb554452ab3396f78586f7 + url: "https://pub.dev" source: hosted version: "2.0.0" mime: dependency: transitive description: name: mime - url: "https://pub.dartlang.org" + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" source: hosted version: "1.0.4" numberpicker: dependency: "direct main" description: name: numberpicker - url: "https://pub.dartlang.org" + sha256: "73723bd13c940ebcd9e5f0ed56b4874588c1748a9a6a38254f97ad627715142e" + url: "https://pub.dev" source: hosted version: "2.1.1" octo_image: dependency: transitive description: name: octo_image - url: "https://pub.dartlang.org" + sha256: "107f3ed1330006a3bea63615e81cf637433f5135a52466c7caa0e7152bca9143" + url: "https://pub.dev" source: hosted version: "1.0.2" open_street_map_search_and_pick: dependency: "direct main" description: name: open_street_map_search_and_pick - url: "https://pub.dartlang.org" + sha256: "806c24b042b01658be0d083f34e9b43563ab6c0a49f4583b10e6b36b41f59167" + url: "https://pub.dev" source: hosted version: "0.0.15" package_config: dependency: transitive description: name: package_config - url: "https://pub.dartlang.org" + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" source: hosted version: "2.1.0" path: dependency: "direct main" description: name: path - url: "https://pub.dartlang.org" + sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + url: "https://pub.dev" source: hosted version: "1.8.2" path_provider: dependency: "direct main" description: name: path_provider - url: "https://pub.dartlang.org" + sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + url: "https://pub.dev" source: hosted version: "2.0.12" path_provider_android: dependency: transitive description: name: path_provider_android - url: "https://pub.dartlang.org" + sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + url: "https://pub.dev" source: hosted version: "2.0.22" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - url: "https://pub.dartlang.org" + sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + url: "https://pub.dev" source: hosted version: "2.1.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - url: "https://pub.dartlang.org" + sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + url: "https://pub.dev" source: hosted version: "2.1.7" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - url: "https://pub.dartlang.org" + sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + url: "https://pub.dev" source: hosted version: "2.0.5" path_provider_windows: dependency: transitive description: name: path_provider_windows - url: "https://pub.dartlang.org" + sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c + url: "https://pub.dev" source: hosted version: "2.1.3" pedantic: dependency: transitive description: name: pedantic - url: "https://pub.dartlang.org" + sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602" + url: "https://pub.dev" source: hosted version: "1.11.1" permission_handler: dependency: "direct main" description: name: permission_handler - url: "https://pub.dartlang.org" + sha256: "33c6a1253d1f95fd06fa74b65b7ba907ae9811f9d5c1d3150e51417d04b8d6a8" + url: "https://pub.dev" source: hosted version: "10.2.0" permission_handler_android: dependency: transitive description: name: permission_handler_android - url: "https://pub.dartlang.org" + sha256: "8028362b40c4a45298f1cbfccd227c8dd6caf0e27088a69f2ba2ab15464159e2" + url: "https://pub.dev" source: hosted version: "10.2.0" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - url: "https://pub.dartlang.org" + sha256: "9c370ef6a18b1c4b2f7f35944d644a56aa23576f23abee654cf73968de93f163" + url: "https://pub.dev" source: hosted version: "9.0.7" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - url: "https://pub.dartlang.org" + sha256: "68abbc472002b5e6dfce47fe9898c6b7d8328d58b5d2524f75e277c07a97eb84" + url: "https://pub.dev" source: hosted version: "3.9.0" permission_handler_windows: dependency: transitive description: name: permission_handler_windows - url: "https://pub.dartlang.org" + sha256: f67cab14b4328574938ecea2db3475dad7af7ead6afab6338772c5f88963e38b + url: "https://pub.dev" source: hosted version: "0.1.2" petitparser: dependency: transitive description: name: petitparser - url: "https://pub.dartlang.org" + sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" + url: "https://pub.dev" source: hosted version: "5.1.0" platform: dependency: transitive description: name: platform - url: "https://pub.dartlang.org" + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" source: hosted version: "3.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a + url: "https://pub.dev" source: hosted version: "2.1.3" pointycastle: dependency: transitive description: name: pointycastle - url: "https://pub.dartlang.org" + sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346 + url: "https://pub.dev" source: hosted version: "3.6.2" polylabel: dependency: transitive description: name: polylabel - url: "https://pub.dartlang.org" + sha256: "41b9099afb2aa6c1730bdd8a0fab1400d287694ec7615dd8516935fa3144214b" + url: "https://pub.dev" source: hosted version: "1.0.1" pool: dependency: transitive description: name: pool - url: "https://pub.dartlang.org" + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" source: hosted version: "1.5.1" positioned_tap_detector_2: dependency: transitive description: name: positioned_tap_detector_2 - url: "https://pub.dartlang.org" + sha256: "52e06863ad3e1f82b058fd05054fc8c9caeeb3b47d5cea7a24bd9320746059c1" + url: "https://pub.dev" source: hosted version: "1.0.4" process: dependency: transitive description: name: process - url: "https://pub.dartlang.org" + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" source: hosted version: "4.2.4" proj4dart: dependency: transitive description: name: proj4dart - url: "https://pub.dartlang.org" + sha256: c8a659ac9b6864aa47c171e78d41bbe6f5e1d7bd790a5814249e6b68bc44324e + url: "https://pub.dev" source: hosted version: "2.1.0" pub_semver: dependency: transitive description: name: pub_semver - url: "https://pub.dartlang.org" + sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" + url: "https://pub.dev" source: hosted version: "2.1.3" pubspec_parse: dependency: transitive description: name: pubspec_parse - url: "https://pub.dartlang.org" + sha256: "75f6614d6dde2dc68948dffbaa4fe5dae32cd700eb9fb763fe11dfb45a3c4d0a" + url: "https://pub.dev" source: hosted version: "1.2.1" qr: dependency: transitive description: name: qr - url: "https://pub.dartlang.org" + sha256: "5c4208b4dc0d55c3184d10d83ee0ded6212dc2b5e2ba17c5a0c0aab279128d21" + url: "https://pub.dev" source: hosted version: "2.1.0" qr_flutter: dependency: transitive description: name: qr_flutter - url: "https://pub.dartlang.org" + sha256: c5c121c54cb6dd837b9b9d57eb7bc7ec6df4aee741032060c8833a678c80b87e + url: "https://pub.dev" source: hosted version: "4.0.0" quiver: dependency: transitive description: name: quiver - url: "https://pub.dartlang.org" + sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 + url: "https://pub.dev" source: hosted version: "3.2.1" rxdart: dependency: transitive description: name: rxdart - url: "https://pub.dartlang.org" + sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" + url: "https://pub.dev" source: hosted version: "0.27.7" sec: dependency: transitive description: name: sec - url: "https://pub.dartlang.org" + sha256: "78e2ed80b8782fe03496ff3c626d5f6139efbe00c577327c613ad8540ea4b14a" + url: "https://pub.dev" source: hosted version: "1.0.1" shared_preferences: dependency: "direct main" description: name: shared_preferences - url: "https://pub.dartlang.org" + sha256: "5949029e70abe87f75cfe59d17bf5c397619c4b74a099b10116baeb34786fad9" + url: "https://pub.dev" source: hosted version: "2.0.17" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - url: "https://pub.dartlang.org" + sha256: "955e9736a12ba776bdd261cf030232b30eadfcd9c79b32a3250dd4a494e8c8f7" + url: "https://pub.dev" source: hosted version: "2.0.15" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - url: "https://pub.dartlang.org" + sha256: "2b55c18636a4edc529fa5cd44c03d3f3100c00513f518c5127c951978efcccd0" + url: "https://pub.dev" source: hosted version: "2.1.3" shared_preferences_ios: dependency: transitive description: name: shared_preferences_ios - url: "https://pub.dartlang.org" + sha256: "585a14cefec7da8c9c2fb8cd283a3bb726b4155c0952afe6a0caaa7b2272de34" + url: "https://pub.dev" source: hosted version: "2.1.1" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - url: "https://pub.dartlang.org" + sha256: f8ea038aa6da37090093974ebdcf4397010605fd2ff65c37a66f9d28394cb874 + url: "https://pub.dev" source: hosted version: "2.1.3" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - url: "https://pub.dartlang.org" + sha256: da9431745ede5ece47bc26d5d73a9d3c6936ef6945c101a5aca46f62e52c1cf3 + url: "https://pub.dev" source: hosted version: "2.1.0" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - url: "https://pub.dartlang.org" + sha256: a4b5bc37fe1b368bbc81f953197d55e12f49d0296e7e412dfe2d2d77d6929958 + url: "https://pub.dev" source: hosted version: "2.0.4" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - url: "https://pub.dartlang.org" + sha256: "5eaf05ae77658d3521d0e993ede1af962d4b326cd2153d312df716dc250f00c9" + url: "https://pub.dev" source: hosted version: "2.1.3" shelf: dependency: transitive description: name: shelf - url: "https://pub.dartlang.org" + sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c + url: "https://pub.dev" source: hosted version: "1.4.0" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - url: "https://pub.dartlang.org" + sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 + url: "https://pub.dev" source: hosted version: "1.0.3" shimmer: dependency: transitive description: name: shimmer - url: "https://pub.dartlang.org" + sha256: "1f1009b5845a1f88f1c5630212279540486f97409e9fc3f63883e71070d107bf" + url: "https://pub.dev" source: hosted version: "2.0.0" sky_engine: @@ -1040,296 +1169,346 @@ packages: dependency: "direct main" description: name: slider_button - url: "https://pub.dartlang.org" + sha256: "9e23a806af48fa615b0891a18be87bb751ae3b6ca8dd5a299ecaafdf351623ef" + url: "https://pub.dev" source: hosted version: "2.0.0" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" sqflite: dependency: "direct main" description: name: sqflite - url: "https://pub.dartlang.org" + sha256: "78324387dc81df14f78df06019175a86a2ee0437624166c382e145d0a7fd9a4f" + url: "https://pub.dev" source: hosted version: "2.2.4+1" sqflite_common: dependency: transitive description: name: sqflite_common - url: "https://pub.dartlang.org" + sha256: bfd6973aaeeb93475bc0d875ac9aefddf7965ef22ce09790eb963992ffc5183f + url: "https://pub.dev" source: hosted version: "2.4.2+2" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" stream_transform: dependency: transitive description: name: stream_transform - url: "https://pub.dartlang.org" + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" source: hosted version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" syncfusion_flutter_charts: dependency: "direct main" description: name: syncfusion_flutter_charts - url: "https://pub.dartlang.org" + sha256: "400fa4c57a22f17b78fac6d086e39ecc7b7ece760fdf2041f235951f05640976" + url: "https://pub.dev" source: hosted - version: "20.4.48" + version: "20.4.49" syncfusion_flutter_core: dependency: transitive description: name: syncfusion_flutter_core - url: "https://pub.dartlang.org" + sha256: b5cb2525beb38fae36a363f72f8a2db92ed3995d6f0695968412cc6836e3a7b7 + url: "https://pub.dev" source: hosted - version: "20.4.48" + version: "20.4.49" synchronized: dependency: transitive description: name: synchronized - url: "https://pub.dartlang.org" + sha256: "33b31b6beb98100bf9add464a36a8dd03eb10c7a8cf15aeec535e9b054aaf04b" + url: "https://pub.dev" source: hosted version: "3.0.1" tar: dependency: "direct main" description: name: tar - url: "https://pub.dartlang.org" + sha256: "85ffd53e277f2bac8afa2885e6b195e26937e9c402424c3d88d92fd920b56de9" + url: "https://pub.dev" source: hosted version: "0.5.6" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + url: "https://pub.dev" source: hosted - version: "0.4.12" + version: "0.4.16" timezone: dependency: transitive description: name: timezone - url: "https://pub.dartlang.org" + sha256: "24c8fcdd49a805d95777a39064862133ff816ebfffe0ceff110fb5960e557964" + url: "https://pub.dev" source: hosted version: "0.9.1" timing: dependency: transitive description: name: timing - url: "https://pub.dartlang.org" + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" source: hosted version: "1.0.1" tuple: dependency: transitive description: name: tuple - url: "https://pub.dartlang.org" + sha256: "0ea99cd2f9352b2586583ab2ce6489d1f95a5f6de6fb9492faaf97ae2060f0aa" + url: "https://pub.dev" source: hosted version: "2.0.1" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" source: hosted version: "1.3.1" unicode: dependency: transitive description: name: unicode - url: "https://pub.dartlang.org" + sha256: "0f69e46593d65245774d4f17125c6084d2c20b4e473a983f6e21b7d7762218f1" + url: "https://pub.dev" source: hosted version: "0.3.1" universal_io: dependency: transitive description: name: universal_io - url: "https://pub.dartlang.org" + sha256: "79f78ddad839ee3aae3ec7c01eb4575faf0d5c860f8e5223bc9f9c17f7f03cef" + url: "https://pub.dev" source: hosted version: "2.0.4" url_launcher: dependency: "direct main" description: name: url_launcher - url: "https://pub.dartlang.org" + sha256: e8f2efc804810c0f2f5b485f49e7942179f56eabcfe81dce3387fec4bb55876b + url: "https://pub.dev" source: hosted - version: "6.1.8" + version: "6.1.9" url_launcher_android: dependency: transitive description: name: url_launcher_android - url: "https://pub.dartlang.org" + sha256: "3e2f6dfd2c7d9cd123296cab8ef66cfc2c1a13f5845f42c7a0f365690a8a7dd1" + url: "https://pub.dev" source: hosted version: "6.0.23" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - url: "https://pub.dartlang.org" + sha256: "0a5af0aefdd8cf820dd739886efb1637f1f24489900204f50984634c07a54815" + url: "https://pub.dev" source: hosted - version: "6.0.18" + version: "6.1.0" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - url: "https://pub.dartlang.org" + sha256: "318c42cba924e18180c029be69caf0a1a710191b9ec49bb42b5998fdcccee3cc" + url: "https://pub.dev" source: hosted version: "3.0.2" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - url: "https://pub.dartlang.org" + sha256: "41988b55570df53b3dd2a7fc90c76756a963de6a8c5f8e113330cb35992e2094" + url: "https://pub.dev" source: hosted version: "3.0.2" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - url: "https://pub.dartlang.org" + sha256: "4eae912628763eb48fc214522e58e942fd16ce195407dbf45638239523c759a6" + url: "https://pub.dev" source: hosted version: "2.1.1" url_launcher_web: dependency: transitive description: name: url_launcher_web - url: "https://pub.dartlang.org" + sha256: "44d79408ce9f07052095ef1f9a693c258d6373dc3944249374e30eff7219ccb0" + url: "https://pub.dev" source: hosted version: "2.0.14" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - url: "https://pub.dartlang.org" + sha256: b6217370f8eb1fd85c8890c539f5a639a01ab209a36db82c921ebeacefc7a615 + url: "https://pub.dev" source: hosted version: "3.0.3" uuid: dependency: transitive description: name: uuid - url: "https://pub.dartlang.org" + sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + url: "https://pub.dev" source: hosted version: "3.0.7" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" vibration: dependency: transitive description: name: vibration - url: "https://pub.dartlang.org" + sha256: "1dc9d1a0d62b12f1276eb7146b21585db5fe01771b8ca0234fefdf74ba51f963" + url: "https://pub.dev" source: hosted version: "1.7.6" + wallet: + dependency: transitive + description: + name: wallet + sha256: "2cabf10d4543b95773219fc401b184f8cbb0bba9359883f5ee5b9f2c46b85de3" + url: "https://pub.dev" + source: hosted + version: "0.0.7" walletconnect_dart: dependency: "direct main" description: name: walletconnect_dart - url: "https://pub.dartlang.org" + sha256: "6d69d3f7ed43b4a111458da0ba078f4ea291ff11328068c9cbf5cab3bd86593f" + url: "https://pub.dev" source: hosted version: "0.0.11" walletconnect_qrcode_modal_dart: dependency: "direct main" description: name: walletconnect_qrcode_modal_dart - url: "https://pub.dartlang.org" + sha256: "3ae5ff25e33b3c647fc5ec03d5c943d21e145371e9577e340f4be07e9f97a73c" + url: "https://pub.dev" source: hosted version: "0.0.6" watcher: dependency: transitive description: name: watcher - url: "https://pub.dartlang.org" + sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + url: "https://pub.dev" source: hosted version: "1.0.2" web3dart: dependency: "direct main" description: name: web3dart - url: "https://pub.dartlang.org" + sha256: "0b96223a6b284e3146e65dc842ded139eca68a85c4ab79c5ba1a73284927d3cd" + url: "https://pub.dev" source: hosted - version: "2.5.1" + version: "2.6.1" web_socket_channel: dependency: transitive description: name: web_socket_channel - url: "https://pub.dartlang.org" + sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b + url: "https://pub.dev" source: hosted version: "2.3.0" win32: dependency: transitive description: name: win32 - url: "https://pub.dartlang.org" + sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 + url: "https://pub.dev" source: hosted version: "3.1.3" wkt_parser: dependency: transitive description: name: wkt_parser - url: "https://pub.dartlang.org" + sha256: "8a555fc60de3116c00aad67891bcab20f81a958e4219cc106e3c037aa3937f13" + url: "https://pub.dev" source: hosted version: "2.0.0" workmanager: dependency: "direct main" description: name: workmanager - url: "https://pub.dartlang.org" + sha256: e0be7e35d644643f164ee45d2ce14414f0e0fdde19456aa66065f35a0b1d2ea1 + url: "https://pub.dev" source: hosted version: "0.5.1" xdg_directories: dependency: transitive description: name: xdg_directories - url: "https://pub.dartlang.org" + sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 + url: "https://pub.dev" source: hosted version: "0.2.0+3" xml: dependency: transitive description: name: xml - url: "https://pub.dartlang.org" + sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" + url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "6.2.2" yaml: dependency: transitive description: name: yaml - url: "https://pub.dartlang.org" + sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + url: "https://pub.dev" source: hosted version: "3.1.1" sdks: - dart: ">=2.18.1 <3.0.0" + dart: ">=2.19.0 <3.0.0" flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index 323ee95..0bbdc51 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -48,7 +48,7 @@ dependencies: path_provider: ^2.0.11 path: ^1.8.2 environment_sensors: ^0.2.0 - ipfs_client_flutter: ^1.0.7 + #ipfs_client_flutter: ^1.0.7 walletconnect_qrcode_modal_dart: ^0.0.5 build_runner: ^2.1.2 syncfusion_flutter_charts: ^20.3.60 @@ -69,7 +69,6 @@ dependencies: flip_card: ^0.7.0 connectivity: ^3.0.6 flutter_isolate: ^2.0.4 - geofence_flutter: ^2.0.0 dev_dependencies: flutter_test: From 87cb76d269be07c66b233079b6773a3f8d5de29e Mon Sep 17 00:00:00 2001 From: Giacomo Date: Tue, 7 Feb 2023 18:51:31 +0100 Subject: [PATCH 18/34] bug fix map iteraction --- lib/controllers/claim_campaign_controller.dart | 9 +++++---- .../create_campaign_form_controller.dart | 4 ++-- lib/controllers/search_places_controller.dart | 9 +++++---- lib/models/campaign_data_light_model.dart | 3 ++- lib/models/geofence_model.dart | 4 ++-- lib/models/smart_contract_model.dart | 14 +++++++++----- lib/services/servicesV2.dart | 15 ++++++++++++--- 7 files changed, 37 insertions(+), 21 deletions(-) diff --git a/lib/controllers/claim_campaign_controller.dart b/lib/controllers/claim_campaign_controller.dart index 6b8f808..9d7a7e8 100644 --- a/lib/controllers/claim_campaign_controller.dart +++ b/lib/controllers/claim_campaign_controller.dart @@ -12,6 +12,8 @@ class ClaimCampaignController extends StatefulWidget { } class _ClaimCampaignControllerState extends State { + SessionModel session = SessionModel(); + @override Widget build(BuildContext context) { return FutureBuilder( @@ -40,16 +42,15 @@ class _ClaimCampaignControllerState extends State { } Future> _getClaimData() async { + SmartContractModel smartContractViewModel = SmartContractModel( contractAddress: FlutterConfig.get('MCSfactory_CONTRACT_ADDRESS'), abiName: 'MCSfactory', abiFileRoot: 'assets/abi.json', - provider: SessionModel().getProvider()); + provider: session.getProvider()); List? res = await smartContractViewModel.queryCall('getCampaignsToClaim', []); - print("DEBUG::::::: res : ${res.toString()}"); if (res != null) { - print("DEBUGG---- " + res[0].toString()); return res[0]; } return []; @@ -88,7 +89,7 @@ class _ClaimCampaignControllerState extends State { contractAddress: address, abiName: 'Campaign', abiFileRoot: 'assets/abi_campaign.json', - provider: SessionModel().getProvider()); + provider: session.getProvider()); dynamic res = await smartContractViewModel.queryTransaction("withdrawCredits", [], null); print("DEBUG::::::: res : ${res.toString()}"); if (res.toString() != "null" && diff --git a/lib/controllers/create_campaign_form_controller.dart b/lib/controllers/create_campaign_form_controller.dart index 0806ba8..0a9449e 100644 --- a/lib/controllers/create_campaign_form_controller.dart +++ b/lib/controllers/create_campaign_form_controller.dart @@ -133,8 +133,8 @@ class _CreateCampaignFormControllerState style: CustomTextStyle.spaceMono(context), ), Slider( - min: 1000, - max: 10000000, + min: 0, + max: 1000000000, divisions: 100, label: "${_howMuch.toInt()} wei", activeColor: CustomColors.blue900(context), diff --git a/lib/controllers/search_places_controller.dart b/lib/controllers/search_places_controller.dart index e681c2e..e5ca0fd 100644 --- a/lib/controllers/search_places_controller.dart +++ b/lib/controllers/search_places_controller.dart @@ -15,6 +15,7 @@ class SearchPlacesController extends StatefulWidget { class _SearchPlacesControllerState extends State { final searchPlacesViewScaffoldKey = GlobalKey(); SearchPlacesModel searchPlacesData = SearchPlacesModel(); + Widget _buildPage() { return Stack(children: [ OpenStreetMapSearchAndPick( @@ -23,9 +24,9 @@ class _SearchPlacesControllerState extends State { buttonText: 'Set Current Location', onPicked: (pickedData) { if (kDebugMode) { - print(pickedData.latLong.latitude); - print(pickedData.latLong.longitude); - print(pickedData.address); + searchPlacesData.lat = pickedData.latLong.latitude; + searchPlacesData.lng = pickedData.latLong.longitude; + searchPlacesData.address = pickedData.address; } }) ]); @@ -38,7 +39,7 @@ class _SearchPlacesControllerState extends State { Navigator.pop(context, searchPlacesData); ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text( - 'Data position taken', + 'Data position taken:\n ${searchPlacesData.address}', style: CustomTextStyle.spaceMonoWhite(context), ))); return false; diff --git a/lib/models/campaign_data_light_model.dart b/lib/models/campaign_data_light_model.dart index 1dc8e09..3938584 100644 --- a/lib/models/campaign_data_light_model.dart +++ b/lib/models/campaign_data_light_model.dart @@ -7,11 +7,12 @@ class CampaignDataLightModel { static Future> preparePage(String campaignAddress) async { List contents = []; + SessionModel session = SessionModel(); late SmartContractModel smartContract = SmartContractModel( contractAddress: campaignAddress, abiName: 'Campaign', abiFileRoot: 'assets/abi_campaign.json', - provider: SessionModel().getProvider()); + provider: session.getProvider()); List? allfilesPathRes = await smartContract.queryCall('getValidFiles', []); diff --git a/lib/models/geofence_model.dart b/lib/models/geofence_model.dart index b5d4857..10d48d3 100644 --- a/lib/models/geofence_model.dart +++ b/lib/models/geofence_model.dart @@ -93,7 +93,7 @@ class Geofence { htmlFormatSummaryText: true, htmlFormatContent: true, htmlFormatTitle: true), - ongoing: false, + ongoing: true, ), ), ) @@ -123,7 +123,7 @@ class Geofence { htmlFormatSummaryText: true, htmlFormatContent: true, htmlFormatTitle: true), - ongoing: false, + ongoing: true, ), )) : print('\x1B[31m $debugString status not changed \x1B[0m'); diff --git a/lib/models/smart_contract_model.dart b/lib/models/smart_contract_model.dart index f6ab85f..7c3b130 100644 --- a/lib/models/smart_contract_model.dart +++ b/lib/models/smart_contract_model.dart @@ -24,9 +24,10 @@ class SmartContractModel extends CustomTransactionSender{ } Future queryTransaction(String functionName, List args, BigInt? value) async { + SessionModel session = SessionModel(); try { //SessionModel().checkConnection(); - int nonce = await SessionModel().ethClient.getTransactionCount(EthereumAddress.fromHex(SessionModel().getAccountAddress())); + int nonce = await SessionModel().ethClient.getTransactionCount(EthereumAddress.fromHex(session.getAccountAddress())); final contract = await loadContract(contractAddress); final ethFunction = contract.function(functionName); Transaction transaction = Transaction.callContract( @@ -38,7 +39,7 @@ class SmartContractModel extends CustomTransactionSender{ ); print('\x1B[31m nonce: $nonce gasPrice: ${transaction.gasPrice} maxGas: ${transaction.maxGas} \x1B[0m'); - launchUrlString(SessionModel().uri, mode: LaunchMode.externalApplication); + launchUrlString(session.uri, mode: LaunchMode.externalApplication); final txBytes = await sendTransaction(transaction); return txBytes; } catch (e) { @@ -51,9 +52,11 @@ class SmartContractModel extends CustomTransactionSender{ @override Future sendTransaction(Transaction transaction) async { + SessionModel session = SessionModel(); + try { final hash = await provider.sendTransaction( - from: SessionModel().getAccountAddress(), + from: session.getAccountAddress(), to: transaction.to?.hex, data: transaction.data, gas: transaction.maxGas, @@ -71,11 +74,12 @@ class SmartContractModel extends CustomTransactionSender{ } Future?> queryCall(String functionName, List args) async { + SessionModel session = SessionModel(); try { final contract = await loadContract(contractAddress); final ethFunction = contract.function(functionName); - final result = await SessionModel().ethClient.call( - sender: EthereumAddress.fromHex(SessionModel().getAccountAddress()), + final result = await session.ethClient.call( + sender: EthereumAddress.fromHex(session.getAccountAddress()), contract: contract, function: ethFunction, params: args); diff --git a/lib/services/servicesV2.dart b/lib/services/servicesV2.dart index 12b00bd..b051c97 100644 --- a/lib/services/servicesV2.dart +++ b/lib/services/servicesV2.dart @@ -78,10 +78,19 @@ class ServicesV2 { 'The campaign [$title] \nat address $address \n was closed by crowdsourcer', NotificationDetails( android: AndroidNotificationDetails( - 'geofence_channel', + NotificationChannel.backgroundServiceChannel.id, NotificationChannel.backgroundServiceChannel.name, icon: 'ic_bg_service_small', - ongoing: false, + styleInformation: BigTextStyleInformation( + "

The campaign \"$title\" \n campaign at address: \n$address \n was closed by the crowdsoucer

", + htmlFormatBigText: true, + contentTitle: "

CLOSED \"$title\"

", + htmlFormatContentTitle: true, + summaryText: "

this campaign is now closed

", + htmlFormatSummaryText: true, + htmlFormatContent: true, + htmlFormatTitle: true), + ongoing: true, ), ), ); @@ -105,7 +114,7 @@ class ServicesV2 { geoList.forEach((element) {element.stopGeofenceService();}); geoList.clear(); for (Campaign c in res) { - Geofence g = Geofence(c.title, c.address, c.lat, c.lng, "20");//c.radius); + Geofence g = Geofence(c.title, c.address, c.lat, c.lng, c.radius); geoList.add(g); g.initialize(); } From d232cbfbdcc082e3e4910bd65d3b4eecc198cf24 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Tue, 7 Feb 2023 19:41:22 +0100 Subject: [PATCH 19/34] Update sourcer_campaign_controller.dart --- lib/controllers/sourcer_campaign_controller.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/controllers/sourcer_campaign_controller.dart b/lib/controllers/sourcer_campaign_controller.dart index 0bdc789..84b003d 100644 --- a/lib/controllers/sourcer_campaign_controller.dart +++ b/lib/controllers/sourcer_campaign_controller.dart @@ -137,7 +137,7 @@ class _SourcerCampaignControllerState extends State { Flexible( flex: 5, child: Text( - "Sourcing Status:\nuploaded $fileCount files\nchecked $fileChecked of $fileCount\nwhit the contribution of $workersCount workers", + "Sourcing Status:\nuploaded $fileCount files\nchecked $fileChecked of $fileCount\nwith the contribution of $workersCount workers", style: CustomTextStyle.spaceMono(context), )), const SizedBox( From eb7d3a058874a2248f99cdb213bc6a7f0287a1c6 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Wed, 8 Feb 2023 00:20:57 +0100 Subject: [PATCH 20/34] session persistance added database for session and managing of uptates/connect callbacks --- .../claim_campaign_controller.dart | 2 + lib/controllers/login_controller.dart | 95 ++++++++++------ .../validate_light_controller.dart | 2 +- lib/controllers/wallet_controller.dart | 1 + lib/models/db_session_model.dart | 104 ++++++++++++++++++ lib/models/login_metamask_model.dart | 12 +- lib/models/session_model.dart | 42 ++++++- lib/models/smart_contract_model.dart | 2 +- lib/views/home_view.dart | 6 + lib/views/wallet_view.dart | 8 ++ 10 files changed, 236 insertions(+), 38 deletions(-) create mode 100644 lib/models/db_session_model.dart diff --git a/lib/controllers/claim_campaign_controller.dart b/lib/controllers/claim_campaign_controller.dart index 9d7a7e8..444a27c 100644 --- a/lib/controllers/claim_campaign_controller.dart +++ b/lib/controllers/claim_campaign_controller.dart @@ -3,6 +3,7 @@ import 'package:flutter_config/flutter_config.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; import '../models/smart_contract_model.dart'; import '../utils/styles.dart'; +import '../views/login_view.dart'; class ClaimCampaignController extends StatefulWidget { const ClaimCampaignController({Key? key}) : super(key: key); @@ -16,6 +17,7 @@ class _ClaimCampaignControllerState extends State { @override Widget build(BuildContext context) { + return FutureBuilder( future: _getClaimData(), builder: (BuildContext context, diff --git a/lib/controllers/login_controller.dart b/lib/controllers/login_controller.dart index be426d3..462e67d 100644 --- a/lib/controllers/login_controller.dart +++ b/lib/controllers/login_controller.dart @@ -1,6 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:mobile_crowd_sensing/models/db_session_model.dart'; import 'package:slider_button/slider_button.dart'; +import 'package:url_launcher/url_launcher_string.dart'; +import 'package:walletconnect_dart/walletconnect_dart.dart'; import '../utils/internet_connection.dart'; +import '../utils/spalsh_screens.dart'; import 'login_metamask_controller.dart'; import '../utils/styles.dart'; import '../models/session_model.dart'; @@ -23,20 +27,49 @@ class _LoginControllerState extends State { InternetConnection.checkInternetConnectivity(); super.initState(); } + + + Future tryToReconnect() async{ + sessionData = SessionModel(); + DbSessionModel dbSession = DbSessionModel(); + List res = await dbSession.sessions(); + if(res.isNotEmpty) { + List lis = [res[0].account]; + await sessionData.connector.approveSession(accounts: lis, chainId: res[0].chainId); + print("Debugg::::::: ${sessionData.getAccountAddress()}"); + } + } + @override Widget build(BuildContext context) { - sessionData = SessionModel(); - sessionData.checkConnection(); + + return FutureBuilder( + future: tryToReconnect(), + builder: (BuildContext context, AsyncSnapshot snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.none: + return const Center(child: Text('Sorry something goes wrong...')); + case ConnectionState.waiting: + return CustomSplashScreen.fadingCubeBlueBg(context); + default: + return _buildPage(); + } + } + ); + } + + + Widget _buildPage() { return SingleChildScrollView( child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - 'assets/images/main_page_image.png', - fit: BoxFit.fitHeight, - ), - (sessionData.connector.connected)? - Container( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/main_page_image.png', + fit: BoxFit.fitHeight, + ), + (sessionData.connector.connected)? + Container( padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -64,29 +97,29 @@ class _LoginControllerState extends State { const SizedBox(height: 20), (sessionData.connector.session.chainId != 5) ? Row(children: const [ - Icon(Icons.warning, - color: Colors.redAccent, size: 15), - Text('Network not supported. Switch to '), - Text( - 'Goreli Testnet', - style: TextStyle(fontWeight: FontWeight.bold), - ) - ]) + Icon(Icons.warning, + color: Colors.redAccent, size: 15), + Text('Network not supported. Switch to '), + Text( + 'Goreli Testnet', + style: TextStyle(fontWeight: FontWeight.bold), + ) + ]) : const SizedBox(height: 20), Center( child: SliderButton( - action: () async { - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (context) => const HomeView())); - }, - label: const Text('Slide to login'), - icon: Icon(Icons.arrow_forward_ios_rounded, - color: CustomColors.blue900(context)), - )) + action: () async { + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (context) => const HomeView())); + }, + label: const Text('Slide to login'), + icon: Icon(Icons.arrow_forward_ios_rounded, + color: CustomColors.blue900(context)), + )) ])) - : ElevatedButton( + : ElevatedButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.all( CustomColors.blue900(context))), @@ -95,7 +128,7 @@ class _LoginControllerState extends State { MaterialPageRoute( builder: (context) => const LoginMetamaskController())), child: const Text("Connect with Metamask")), - ], - )); + ], + )); } } diff --git a/lib/controllers/validate_light_controller.dart b/lib/controllers/validate_light_controller.dart index dfbbd0c..bb3f9a0 100644 --- a/lib/controllers/validate_light_controller.dart +++ b/lib/controllers/validate_light_controller.dart @@ -22,7 +22,7 @@ class ValidateLightControllerState extends State { bool activeSensor = false, sensorGate = false, downloadGate = false; double sum = 0, averageRelevation = 0; - late String? hash, time, relevation; + late String? hash = "Loading...", time = "Loading...", relevation = "Loading..."; late List? data; List lights = []; diff --git a/lib/controllers/wallet_controller.dart b/lib/controllers/wallet_controller.dart index fce0f6c..6a19882 100644 --- a/lib/controllers/wallet_controller.dart +++ b/lib/controllers/wallet_controller.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter_config/flutter_config.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; +import 'package:mobile_crowd_sensing/views/login_view.dart'; import '../models/smart_contract_model.dart'; import '../models/wallet_model.dart'; import '../utils/styles.dart'; diff --git a/lib/models/db_session_model.dart b/lib/models/db_session_model.dart new file mode 100644 index 0000000..d342c94 --- /dev/null +++ b/lib/models/db_session_model.dart @@ -0,0 +1,104 @@ +import 'dart:async'; +import 'package:path/path.dart'; +import 'package:sqflite/sqflite.dart'; + +class DbSessionModel { + + static final DbSessionModel _instance = DbSessionModel._internal(); + + Database? _db; + + DbSessionModel._internal() { + _initDb(); + } + + factory DbSessionModel() { + return _instance; + } + + Future _initDb() async { + _db ??= await openDatabase(join(await getDatabasesPath(), 'session.db'), + onCreate: (db, version) { + return db.execute( + 'CREATE TABLE session(' + 'account TEXT PRIMARY KEY,' + ' chainId INTEGER' + ')', + ); + }, + version: 1, + ); + return _db!; + } + + Future insertSession(Session cmp) async { + final db = await _initDb(); + // `conflictAlgorithm` to use in case the same campaign is inserted twice. + await db.insert( + 'session', + cmp.toMap(), + conflictAlgorithm: ConflictAlgorithm.replace, + ); + } + + Future> sessions() async { + final db = await _initDb(); + final List> maps = await db.query('session'); + + return List.generate(maps.length, (i) { + return Session( + account: maps[i]['account'], + chainId: maps[i]['chainId'], + ); + }); + } + + Future updateSession(Session cmp) async { + final db = await _initDb(); + await db.update( + 'session', + cmp.toMap(), + where: 'account = ?', + whereArgs: [cmp.account], + ); + } + + Future deleteSession(String account) async { + final db = await _initDb(); + await db.delete( + 'session', + where: 'account = ?', + whereArgs: [account], + ); + } + + Future deleteAll() async { + final db = await _initDb(); + await db.delete('session'); + } +} + +class Session { + final String account; + final int chainId; + + const Session( + { + required this.account, + required this.chainId, + } + ); + + Map toMap() { + return { + 'account': account, + 'chainId': chainId, + }; + } + + @override + String toString() { + return 'Session{account: $account, chainId: $chainId}'; + } + +} \ No newline at end of file diff --git a/lib/models/login_metamask_model.dart b/lib/models/login_metamask_model.dart index 13b3a8d..51d34ac 100644 --- a/lib/models/login_metamask_model.dart +++ b/lib/models/login_metamask_model.dart @@ -3,21 +3,29 @@ import 'package:flutter/foundation.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher_string.dart'; +import 'package:walletconnect_dart/walletconnect_dart.dart'; import '../services/services_controllerV2.dart'; +import 'db_session_model.dart'; class LoginMetamaskModel { static Future loginUsingMetamask(BuildContext context) async { SessionModel sessionData = SessionModel(); - sessionData.checkConnection(); + if (!sessionData.connector.connected) { try { - await sessionData.connector.createSession( + SessionStatus newSession = await sessionData.connector.createSession( onDisplayUri: (uri) async { sessionData.uri = uri; await launchUrlString(uri, mode: LaunchMode.externalApplication); + }); + + DbSessionModel sessionDb = DbSessionModel(); + await sessionDb.deleteAll(); + await sessionDb.insertSession(Session(account: newSession.accounts[0], chainId: newSession.chainId)); + SharedPreferences shared = await SharedPreferences.getInstance(); shared.setString('address', sessionData.getAccountAddress()); if (kDebugMode) { diff --git a/lib/models/session_model.dart b/lib/models/session_model.dart index a2e3aaa..bf01bb8 100644 --- a/lib/models/session_model.dart +++ b/lib/models/session_model.dart @@ -3,6 +3,8 @@ import 'package:web3dart/web3dart.dart'; import 'package:flutter_config/flutter_config.dart'; import 'package:http/http.dart' as http; +import 'db_session_model.dart'; + class SessionModel { static final SessionModel _instance = SessionModel._internal(); @@ -12,6 +14,7 @@ class SessionModel { late http.Client httpClient; late Web3Client ethClient; late EthereumWalletConnectProvider provider; + final DbSessionModel dbSession = DbSessionModel(); factory SessionModel() { return _instance; @@ -32,6 +35,39 @@ class SessionModel { ) ); provider = EthereumWalletConnectProvider(connector); + + connector.on('connect', (session) => { + print('\x1B[31m[checkConnection ON]\x1B[0m:connect'), + reconnect() + }); + connector.on('session_update', (WCSessionUpdateResponse payload) async => { + print('\x1B[31m[checkConnection ON]\x1B[0m:session_update'), + connector.updateSession(SessionStatus(chainId: payload.chainId, accounts: payload.accounts)), + await dbSession.updateSession(Session(account: payload.accounts[0], chainId: payload.chainId)) + }); + connector.on('disconnect', (payload) => { + print('\x1B[31m[checkConnection ON]\x1B[0m:disconnect'), + closeConnection() + }); + + + connector.registerListeners( + onConnect: (SessionStatus payload) { + print('\x1B[31m[checkConnection]\x1B[0m:connect'); + connector.session.accounts = payload.accounts; + connector.session.chainId = payload.chainId; + }, + onSessionUpdate: (WCSessionUpdateResponse res) async { + print('\x1B[31m[checkConnection]\x1B[0m:session_update'); + connector.session.chainId = res.chainId; + connector.session.accounts = res.accounts; + await dbSession.updateSession(Session(account: res.accounts[0], chainId: res.chainId)); + }, + onDisconnect: () async { + print('\x1B[31m[checkConnection]\x1B[0m:disconnect'); + await dbSession.deleteAll(); + } + ); return provider; } @@ -47,7 +83,7 @@ class SessionModel { return connector.session.accounts[0]; } - Future checkConnection() async { + /* Future checkConnection() async { connector.on('connect', (session) => { print('\x1B[31m[checkConnection]\x1B[0m:connect'), reconnect() @@ -55,13 +91,13 @@ class SessionModel { connector.on('session_update', (WCSessionUpdateResponse payload) async => { print('\x1B[31m[checkConnection]\x1B[0m:session_update'), connector.updateSession(SessionStatus(chainId: payload.chainId, accounts: payload.accounts)), - print("\n DEBUG DEL PAYLOAD: ${payload.toString()}"), + await dbSession.updateSession(Session(account: payload.accounts[0], chainId: payload.chainId)) }); connector.on('disconnect', (payload) => { print('\x1B[31m[checkConnection]\x1B[0m:disconnect'), closeConnection() }); - } + }*/ void reconnect(){ print('\x1B[31m[Connection reconnected]\x1B[0m:connect'); diff --git a/lib/models/smart_contract_model.dart b/lib/models/smart_contract_model.dart index 7c3b130..37786ab 100644 --- a/lib/models/smart_contract_model.dart +++ b/lib/models/smart_contract_model.dart @@ -27,7 +27,7 @@ class SmartContractModel extends CustomTransactionSender{ SessionModel session = SessionModel(); try { //SessionModel().checkConnection(); - int nonce = await SessionModel().ethClient.getTransactionCount(EthereumAddress.fromHex(session.getAccountAddress())); + int nonce = await session.ethClient.getTransactionCount(EthereumAddress.fromHex(session.getAccountAddress())); final contract = await loadContract(contractAddress); final ethFunction = contract.function(functionName); Transaction transaction = Transaction.callContract( diff --git a/lib/views/home_view.dart b/lib/views/home_view.dart index 844a3f1..3ceff92 100644 --- a/lib/views/home_view.dart +++ b/lib/views/home_view.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:geolocator/geolocator.dart'; import 'package:mobile_crowd_sensing/views/sourcer_view.dart'; import 'package:mobile_crowd_sensing/views/wallet_view.dart'; +import '../models/search_places_model.dart'; import '../utils/styles.dart'; import 'all_campaign_view.dart'; @@ -21,12 +23,16 @@ class _HomeViewState extends State { } Widget _renderThis() { + SearchPlacesModel p = SearchPlacesModel(); + switch (_selectedIndex){ case 1: return const SourcerView(); case 2: + p.getPermissions(); return const AllCampaignView(cameFrom: 'worker'); case 3: + p.getPermissions(); return const AllCampaignView(cameFrom: 'verifier'); default: return const WalletView(); diff --git a/lib/views/wallet_view.dart b/lib/views/wallet_view.dart index 6344e79..c7d9060 100644 --- a/lib/views/wallet_view.dart +++ b/lib/views/wallet_view.dart @@ -1,14 +1,22 @@ import 'package:flutter/material.dart'; +import 'package:mobile_crowd_sensing/models/session_model.dart'; import 'package:mobile_crowd_sensing/utils/styles.dart'; import '../controllers/claim_campaign_controller.dart'; import '../controllers/wallet_controller.dart'; +import 'login_view.dart'; class WalletView extends StatelessWidget { const WalletView({Key? key}) : super(key: key); @override Widget build(BuildContext context) { + SessionModel session = SessionModel(); + if(!session.provider.connector.connected) { + WidgetsBinding.instance!.addPostFrameCallback((_) { + Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => LoginView())); + });} + return Scaffold( appBar: AppBar( title: const Text("HOME"), From 5d40d9b7fd8ffe88b88e8bdfdcb1dcfef6626aff Mon Sep 17 00:00:00 2001 From: Giacomo Date: Fri, 10 Feb 2023 00:44:09 +0100 Subject: [PATCH 21/34] fix session recover now is possible to use just one instance of wallet connect session in order to initialize the application. separated Widgets for login in order to manage setState in separated way Fixed Campaign Contract for claim campaigns --- contracts/Campaign.sol | 17 +- .../campaign_data_photo_controller.dart | 1 + lib/controllers/campaign_list_controller.dart | 3 - .../login_check_connection_controller.dart | 82 ++++ lib/controllers/login_controller.dart | 89 +---- .../verifier_campaign_data_controller.dart | 367 +++++++++--------- lib/main.dart | 45 ++- lib/models/db_capaign_model.dart | 1 - lib/models/db_session_model.dart | 9 +- lib/models/login_metamask_model.dart | 31 +- lib/models/session_model.dart | 122 +++--- lib/models/smart_contract_model.dart | 15 +- lib/services/servicesV2.dart | 24 +- lib/services/services_controllerV2.dart | 1 - lib/views/all_campaign_view.dart | 23 +- lib/views/home_view.dart | 3 - lib/views/light_join_campaign_view.dart | 12 +- .../verifier_campaign_data_light_view.dart | 1 + pubspec.lock | 138 +++---- pubspec.yaml | 4 +- 20 files changed, 516 insertions(+), 472 deletions(-) create mode 100644 lib/controllers/login_check_connection_controller.dart diff --git a/contracts/Campaign.sol b/contracts/Campaign.sol index 628f3a9..28736ae 100644 --- a/contracts/Campaign.sol +++ b/contracts/Campaign.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.17; import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "./MCSfactory.sol"; - +import "@openzeppelin/contracts/security/PullPayment.sol" contract Campaign is Ownable, Initializable { string internal name; @@ -15,6 +15,7 @@ contract Campaign is Ownable, Initializable { address public addressCrowdSourcer; uint256 public fileCount = 0; uint256 public checkedFiles = 0; + uint256 public validFiles = 0; uint256 public numberOfActiveWorkers = 0; uint256 public numberOfActiveVerifiers = 0; bool public isClosed; @@ -101,6 +102,7 @@ contract Campaign is Ownable, Initializable { files[hash].status = true; files[hash].verifier = msg.sender; checkedFiles++; + validFiles++; numberOfActiveVerifiers++; } @@ -126,16 +128,19 @@ contract Campaign is Ownable, Initializable { function closeCampaignAndPay() public payable { require(msg.sender == addressCrowdSourcer,'you are not the owner'); isClosed = factoryContractAddress.closeCampaign(); + uint256 balance = getCampaignBalance(); + uint256 verifiesTotalReward = (balance * 50 / 100); + uint256 workerReward = (balance - verifiesTotalReward) / validFiles; + uint256 verifierReward = verifiesTotalReward / numberOfActiveVerifiers; + uint256 refound = balance - (workerReward + verifierReward); + if(refound > 0) { + factoryContractAddress.putCampaignToClaim(addressCrowdSourcer,address(this), "refound", refound); + } for(uint i; i? res = await ValidateModel.downloadPhotosFiles(i[4].toString()); + print("DEBUG DI CIRCOSTANZA :::::::::: ${res.toString()}"); if (res != null) { res.forEach((element) async { File f = File(element.path); diff --git a/lib/controllers/campaign_list_controller.dart b/lib/controllers/campaign_list_controller.dart index 440835f..e07fae9 100644 --- a/lib/controllers/campaign_list_controller.dart +++ b/lib/controllers/campaign_list_controller.dart @@ -346,9 +346,6 @@ class _CampaignListControllerState (double.parse(data[2].toString()) / 10000000), widget.places.lat, widget.places.lng)/1000; - if (kDebugMode) { - print("DEBUG::::::::::::::::: [${double.parse(data[1].toString()) / 10000000},${double.parse(data[2].toString()) / 10000000}] e [${widget.places.lat},${widget.places.lng}] => $distance"); - } return (distance <= (_currentIntValue)) ? true : false; default: return true; diff --git a/lib/controllers/login_check_connection_controller.dart b/lib/controllers/login_check_connection_controller.dart new file mode 100644 index 0000000..9d03ad6 --- /dev/null +++ b/lib/controllers/login_check_connection_controller.dart @@ -0,0 +1,82 @@ +import 'package:flutter/material.dart'; +import 'package:mobile_crowd_sensing/models/session_model.dart'; +import 'package:slider_button/slider_button.dart'; + +import '../utils/styles.dart'; +import '../views/home_view.dart'; +import 'login_metamask_controller.dart'; + +class LoginCheckConnectionController extends StatefulWidget { + const LoginCheckConnectionController({Key? key}) : super(key: key); + + @override + State createState() => + _LoginCheckConnectionControllerState(); +} + +class _LoginCheckConnectionControllerState extends State { + + SessionModel sessionData = SessionModel(); + + @override + Widget build(BuildContext context) { + return (sessionData.connector.connected) + ? Container( + padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), + child: + Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text( + 'Account', + style: CustomTextStyle.merriweatherBold(context), + ), + Text( + '${sessionData.getAccountAddress()}', + style: CustomTextStyle.inconsolata(context), + ), + const SizedBox(height: 20), + Row(children: [ + Text( + 'Chain: ', + style: CustomTextStyle.inconsolata(context), + ), + Text( + sessionData + .getNetworkName(sessionData.connector.session.chainId), + style: CustomTextStyle.inconsolata(context), + ), + ]), + const SizedBox(height: 20), + (sessionData.connector.session.chainId != 5) + ? Row(children: const [ + Icon(Icons.warning, color: Colors.redAccent, size: 15), + Text('Network not supported. Switch to '), + Text( + 'Goreli Testnet', + style: TextStyle(fontWeight: FontWeight.bold), + ) + ]) + : const SizedBox(height: 20), + Center( + child: SliderButton( + action: () async { + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (context) => const HomeView())); + }, + label: const Text('Slide to login'), + icon: Icon(Icons.arrow_forward_ios_rounded, + color: CustomColors.blue900(context)), + )) + ])) + : ElevatedButton( + style: ButtonStyle( + backgroundColor: + MaterialStateProperty.all(CustomColors.blue900(context))), + onPressed: () => Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (context) => const LoginMetamaskController())), + child: const Text("Connect with Metamask")); + } +} diff --git a/lib/controllers/login_controller.dart b/lib/controllers/login_controller.dart index 462e67d..01f58fb 100644 --- a/lib/controllers/login_controller.dart +++ b/lib/controllers/login_controller.dart @@ -1,14 +1,10 @@ import 'package:flutter/material.dart'; import 'package:mobile_crowd_sensing/models/db_session_model.dart'; -import 'package:slider_button/slider_button.dart'; -import 'package:url_launcher/url_launcher_string.dart'; import 'package:walletconnect_dart/walletconnect_dart.dart'; import '../utils/internet_connection.dart'; import '../utils/spalsh_screens.dart'; -import 'login_metamask_controller.dart'; -import '../utils/styles.dart'; +import 'login_check_connection_controller.dart'; import '../models/session_model.dart'; -import '../views/home_view.dart'; class LoginController extends StatefulWidget { const LoginController({Key? key}) : super(key: key); @@ -19,8 +15,8 @@ class LoginController extends StatefulWidget { class _LoginControllerState extends State { bool isRunning = false; - late SessionModel sessionData; - + late SessionModel sessionData = SessionModel(); + bool gate = false; @override void initState() { @@ -28,23 +24,10 @@ class _LoginControllerState extends State { super.initState(); } - - Future tryToReconnect() async{ - sessionData = SessionModel(); - DbSessionModel dbSession = DbSessionModel(); - List res = await dbSession.sessions(); - if(res.isNotEmpty) { - List lis = [res[0].account]; - await sessionData.connector.approveSession(accounts: lis, chainId: res[0].chainId); - print("Debugg::::::: ${sessionData.getAccountAddress()}"); - } - } - @override Widget build(BuildContext context) { - return FutureBuilder( - future: tryToReconnect(), + future: sessionData.instantiateConnector(), builder: (BuildContext context, AsyncSnapshot snapshot) { switch (snapshot.connectionState) { case ConnectionState.none: @@ -68,67 +51,7 @@ class _LoginControllerState extends State { 'assets/images/main_page_image.png', fit: BoxFit.fitHeight, ), - (sessionData.connector.connected)? - Container( - padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Account', - style: CustomTextStyle.merriweatherBold(context), - ), - Text( - '${sessionData.getAccountAddress()}', - style: CustomTextStyle.inconsolata(context), - ), - const SizedBox(height: 20), - Row(children: [ - Text( - 'Chain: ', - style: CustomTextStyle.inconsolata(context), - ), - Text( - sessionData - .getNetworkName(sessionData.connector.session.chainId), - style: CustomTextStyle.inconsolata(context), - ), - ]), - const SizedBox(height: 20), - (sessionData.connector.session.chainId != 5) - ? Row(children: const [ - Icon(Icons.warning, - color: Colors.redAccent, size: 15), - Text('Network not supported. Switch to '), - Text( - 'Goreli Testnet', - style: TextStyle(fontWeight: FontWeight.bold), - ) - ]) - : const SizedBox(height: 20), - Center( - child: SliderButton( - action: () async { - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (context) => const HomeView())); - }, - label: const Text('Slide to login'), - icon: Icon(Icons.arrow_forward_ios_rounded, - color: CustomColors.blue900(context)), - )) - ])) - : ElevatedButton( - style: ButtonStyle( - backgroundColor: MaterialStateProperty.all( - CustomColors.blue900(context))), - onPressed: () => Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (context) => const LoginMetamaskController())), - child: const Text("Connect with Metamask")), - ], - )); + const LoginCheckConnectionController() + ])); } } diff --git a/lib/controllers/verifier_campaign_data_controller.dart b/lib/controllers/verifier_campaign_data_controller.dart index 75b86ca..136a6b0 100644 --- a/lib/controllers/verifier_campaign_data_controller.dart +++ b/lib/controllers/verifier_campaign_data_controller.dart @@ -6,7 +6,8 @@ import '../models/verifier_campaign_data_model.dart'; class VerifierCampaignDataController extends StatefulWidget { final String goTo; - const VerifierCampaignDataController({Key? key, required this.goTo}) : super(key: key); + const VerifierCampaignDataController({Key? key, required this.goTo}) + : super(key: key); @override State createState() => @@ -65,45 +66,55 @@ class _VerifierCampaignDataPhotoController return Container( padding: const EdgeInsets.fromLTRB(10, 30, 10, 0), width: double.maxFinite, - child: - Column(children: [ - Column(children: [ - Text("contractAddress:", - style: CustomTextStyle.spaceMonoBold(context)), - FittedBox( - fit: BoxFit.fitWidth, - child: Text(contractAddress, - style: CustomTextStyle.spaceMono(context))), - ]), - Column(children: [ - Text("Crowdsourcer:", style: CustomTextStyle.spaceMonoBold(context)), - FittedBox( - fit: BoxFit.fitWidth, - child: Text(crowdsourcer, - style: CustomTextStyle.spaceMono(context))), - ]), - Column(children: [ - Text("Location:", style: CustomTextStyle.spaceMonoBold(context)), - Text(readebleLocation, style: CustomTextStyle.spaceMono(context)), - ]), - Row(children: [ - Text( - "Range: ", - style: CustomTextStyle.spaceMonoBold(context), - ), - Text( - "$range m", - style: CustomTextStyle.spaceMono(context), - ), - Text( - "Type: ", - style: CustomTextStyle.spaceMonoBold(context), - ), - Text( - type, - style: CustomTextStyle.spaceMono(context), - ), - ]), + child: Column(children: [ + SizedBox( + height: DeviceDimension.deviceHeight(context) / 4, + child: + Column(children: [ + Column(children: [ + Text("contractAddress:", + style: CustomTextStyle.spaceMonoBold(context)), + FittedBox( + fit: BoxFit.fitWidth, + child: Text(contractAddress, + style: CustomTextStyle.spaceMono(context))), + ]), + Column(children: [ + Text("Crowdsourcer:", + style: CustomTextStyle.spaceMonoBold(context)), + FittedBox( + fit: BoxFit.fitWidth, + child: Text(crowdsourcer, + style: CustomTextStyle.spaceMono(context))), + ]), + Column(children: [ + Text("Location:", + style: CustomTextStyle.spaceMonoBold(context)), + Text(readebleLocation, + style: CustomTextStyle.spaceMono(context)), + ]), + Row(children: [ + Text( + "Range: ", + style: CustomTextStyle.spaceMonoBold(context), + ), + Text( + "$range m", + style: CustomTextStyle.spaceMono(context), + ), + Text( + "Type: ", + style: CustomTextStyle.spaceMonoBold(context), + ), + Text( + type, + style: CustomTextStyle.spaceMono(context), + ), + ]), + //const SizedBox(height: 20,), + //Text("uploaded $fileCount files\nchecked $fileChecked of $fileCount", style: CustomTextStyle.spaceMonoBold(context),), + ]) + ), FutureBuilder( future: _formatData(), builder: (BuildContext context, AsyncSnapshot snapshot) { @@ -111,13 +122,12 @@ class _VerifierCampaignDataPhotoController case ConnectionState.none: return const Expanded( flex: 1, - child:Center( - child: Text('Sorry something goes wrong...'))); + child: + Center(child: Text('Sorry something goes wrong...'))); case ConnectionState.waiting: return const Expanded( flex: 1, - child: Center( - child: CircularProgressIndicator()), + child: Center(child: CircularProgressIndicator()), ); default: return _bottomWidget(); @@ -128,152 +138,143 @@ class _VerifierCampaignDataPhotoController } Widget _bottomWidget() { - return Expanded( - flex: 1, - child: Column(children: [ - Text( - "uploaded $fileCount files\nchecked $fileChecked of $fileCount", - style: CustomTextStyle.spaceMonoBold(context), - ), - ListView.builder( - //scrollDirection: Axis.vertical, - shrinkWrap: true, - itemCount: (filesInfo != null) ? filesInfo!.length : 0, - itemBuilder: (context, index) { - List current = filesInfo![index]; + return Flexible( + child: + ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: (filesInfo != null) ? filesInfo!.length : 0, + itemBuilder: (context, index) { + List current = filesInfo![index]; - String status = current[0].toString(); - String validity = current[1].toString(); - String uploader = current[2].toString(); - String ipfsHash = current[4].toString(); - if (status == 'false') { - return GestureDetector( - onTap: () { - if(SessionModel().getAccountAddress().toLowerCase() != uploader.toLowerCase()) { - Navigator.pushNamed(context, widget.goTo, - arguments: { - "name": name, - "ipfsHash": ipfsHash, - "uploader": uploader, - "contractAddress": contractAddress - }); - } else { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar( - content: Text( - "You can't verify your own Uploads", - style: CustomTextStyle.spaceMonoWhite(context), - ))); - } - }, - child: Card( - shadowColor: CustomColors.blue600(context), - color: CustomColors.customWhite(context), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20.0), - ), - child: Padding( - padding: const EdgeInsets.all(20), - child: Stack(children: [ - Align( - alignment: Alignment.topLeft, - child: Column( - children: [ - FittedBox( - fit: BoxFit.fitWidth, - child: Column(children: [ - Text( - "Uploader: ", - style: CustomTextStyle.spaceMonoBold( - context), - ), - Text( - uploader, - style: CustomTextStyle.spaceMono( - context), - ) - ])), - FittedBox( - fit: BoxFit.fitWidth, - child: Column(children: [ - Text( - "Ipfs hash: ", - style: CustomTextStyle.spaceMonoBold( - context), - ), - Text( - ipfsHash, - style: CustomTextStyle.spaceMono( - context), - ) - ])), - ], - ), - ), - ])), - ), - ); - } else { - return Card( - shadowColor: (validity == 'true') - ? CustomColors.green600(context) - : CustomColors.red600(context), + String status = current[0].toString(); + String validity = current[1].toString(); + String uploader = current[2].toString(); + String ipfsHash = current[4].toString(); + if (status == 'false') { + return GestureDetector( + onTap: () { + if (SessionModel().getAccountAddress().toLowerCase() != + uploader.toLowerCase()) { + Navigator.pushNamed(context, widget.goTo, arguments: { + "name": name, + "ipfsHash": ipfsHash, + "uploader": uploader, + "contractAddress": contractAddress + }); + } else { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text( + "You can't verify your own Uploads", + style: CustomTextStyle.spaceMonoWhite(context), + ))); + } + }, + child: Card( + shadowColor: CustomColors.blue600(context), color: CustomColors.customWhite(context), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20.0), ), child: Padding( - padding: const EdgeInsets.all(20), - child: Align( - alignment: Alignment.topLeft, - child: Column( - children: [ - FittedBox( - fit: BoxFit.fitWidth, - child: Column(children: [ - Text( - "Uploader: ", - style: - CustomTextStyle.spaceMonoBold(context), - ), - Text( - uploader, - style: CustomTextStyle.spaceMono(context), - ) - ])), - FittedBox( - fit: BoxFit.fitWidth, - child: Column(children: [ - Text( - "Ipfs hash: ", - style: - CustomTextStyle.spaceMonoBold(context), - ), - Text( - ipfsHash, - style: CustomTextStyle.spaceMono(context), - ) - ])), - FittedBox( - fit: BoxFit.fitWidth, - child: Row(children: [ - Text( - "validity: ", - style: - CustomTextStyle.spaceMonoBold(context), - ), - Text( - validity, - style: CustomTextStyle.spaceMono(context), - ) - ])), - ], - ), + padding: const EdgeInsets.all(20), + child: Stack(children: [ + Align( + alignment: Alignment.topLeft, + child: Column( + children: [ + FittedBox( + fit: BoxFit.fitWidth, + child: Column(children: [ + Text( + "Uploader: ", + style: CustomTextStyle.spaceMonoBold( + context), + ), + Text( + uploader, + style: + CustomTextStyle.spaceMono(context), + ) + ])), + FittedBox( + fit: BoxFit.fitWidth, + child: Column(children: [ + Text( + "Ipfs hash: ", + style: CustomTextStyle.spaceMonoBold( + context), + ), + Text( + ipfsHash, + style: + CustomTextStyle.spaceMono(context), + ) + ])), + ], + ), + ), + ])), + ), + ); + } else { + return Card( + shadowColor: (validity == 'true') + ? CustomColors.green600(context) + : CustomColors.red600(context), + color: CustomColors.customWhite(context), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20.0), + ), + child: Padding( + padding: const EdgeInsets.all(20), + child: Align( + alignment: Alignment.topLeft, + child: Column( + children: [ + FittedBox( + fit: BoxFit.fitWidth, + child: Column(children: [ + Text( + "Uploader: ", + style: CustomTextStyle.spaceMonoBold(context), + ), + Text( + uploader, + style: CustomTextStyle.spaceMono(context), + ) + ])), + FittedBox( + fit: BoxFit.fitWidth, + child: Column(children: [ + Text( + "Ipfs hash: ", + style: CustomTextStyle.spaceMonoBold(context), + ), + Text( + ipfsHash, + style: CustomTextStyle.spaceMono(context), + ) + ])), + FittedBox( + fit: BoxFit.fitWidth, + child: Row(children: [ + Text( + "validity: ", + style: CustomTextStyle.spaceMonoBold(context), + ), + Text( + validity, + style: CustomTextStyle.spaceMono(context), + ) + ])), + ], ), ), - ); - } - }) - ])); + ), + ); + } + }) + ); } } diff --git a/lib/main.dart b/lib/main.dart index aec028b..64bacd0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,6 +2,8 @@ import 'dart:io'; import 'package:flip_card/flip_card.dart'; import 'package:flutter/material.dart'; import 'package:flutter_config/flutter_config.dart'; +import 'package:mobile_crowd_sensing/models/db_session_model.dart'; +import 'package:mobile_crowd_sensing/models/session_model.dart'; import 'package:mobile_crowd_sensing/utils/internet_connection.dart'; import 'package:mobile_crowd_sensing/utils/styles.dart'; import 'package:mobile_crowd_sensing/utils/verifier_campaign_data_factory.dart'; @@ -22,16 +24,57 @@ import 'package:mobile_crowd_sensing/views/validate_photo_view.dart'; import 'package:mobile_crowd_sensing/views/wallet_view.dart'; import 'dart:async'; import 'package:connectivity/connectivity.dart'; +import 'package:flutter/widgets.dart'; + +class LifecycleWatcher extends StatefulWidget { + @override + _LifecycleWatcherState createState() => _LifecycleWatcherState(); +} + +class _LifecycleWatcherState extends State with WidgetsBindingObserver { + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addObserver(this); + } + + @override + void dispose() { + WidgetsBinding.instance.removeObserver(this); + super.dispose(); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + + if(state == AppLifecycleState.detached) { + print('\x1B[31m[STATUS APP] : ${state.toString()}\x1B[0m'); + SessionModel sessionModel = SessionModel(); + sessionModel.connector.killSession(); + } + } + + @override + Widget build(BuildContext context) { + return const MyApp(); + } +} + + Future main(List args) async { WidgetsFlutterBinding.ensureInitialized(); await FlutterConfig.loadEnvVariables(); ConnectivityResult initialStateInternet = await Connectivity().checkConnectivity(); + if (initialStateInternet == ConnectivityResult.none) { runApp(const NoConnection()); } else { - runApp(const MyApp()); + return runApp(Center(child: LifecycleWatcher())); } + } class NoConnection extends StatelessWidget { diff --git a/lib/models/db_capaign_model.dart b/lib/models/db_capaign_model.dart index 037103b..0a6b4bf 100644 --- a/lib/models/db_capaign_model.dart +++ b/lib/models/db_capaign_model.dart @@ -37,7 +37,6 @@ class DbCampaignModel { Future insertCampaign(Campaign cmp) async { final db = await _initDb(); - // `conflictAlgorithm` to use in case the same campaign is inserted twice. await db.insert( 'campaign', cmp.toMap(), diff --git a/lib/models/db_session_model.dart b/lib/models/db_session_model.dart index d342c94..452526b 100644 --- a/lib/models/db_session_model.dart +++ b/lib/models/db_session_model.dart @@ -22,7 +22,8 @@ class DbSessionModel { return db.execute( 'CREATE TABLE session(' 'account TEXT PRIMARY KEY,' - ' chainId INTEGER' + ' chainId INTEGER,' + ' uri TEXT' ')', ); }, @@ -49,6 +50,7 @@ class DbSessionModel { return Session( account: maps[i]['account'], chainId: maps[i]['chainId'], + uri: maps[i]['uri'], ); }); } @@ -81,11 +83,13 @@ class DbSessionModel { class Session { final String account; final int chainId; + final String uri; const Session( { required this.account, required this.chainId, + required this.uri, } ); @@ -93,12 +97,13 @@ class Session { return { 'account': account, 'chainId': chainId, + 'uri': uri, }; } @override String toString() { - return 'Session{account: $account, chainId: $chainId}'; + return 'Session{account: $account, chainId: $chainId, uri: $uri}'; } } \ No newline at end of file diff --git a/lib/models/login_metamask_model.dart b/lib/models/login_metamask_model.dart index 51d34ac..48c6d90 100644 --- a/lib/models/login_metamask_model.dart +++ b/lib/models/login_metamask_model.dart @@ -1,7 +1,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; -import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher_string.dart'; import 'package:walletconnect_dart/walletconnect_dart.dart'; @@ -14,34 +13,32 @@ class LoginMetamaskModel { SessionModel sessionData = SessionModel(); if (!sessionData.connector.connected) { + DbSessionModel sessionDb = DbSessionModel(); try { SessionStatus newSession = await sessionData.connector.createSession( onDisplayUri: (uri) async { + print('\x1B[31m[LOGIN METAMASK] uri: ${uri}\x1B[0m'); sessionData.uri = uri; await launchUrlString(uri, mode: LaunchMode.externalApplication); }); - DbSessionModel sessionDb = DbSessionModel(); - await sessionDb.deleteAll(); - await sessionDb.insertSession(Session(account: newSession.accounts[0], chainId: newSession.chainId)); - - SharedPreferences shared = await SharedPreferences.getInstance(); - shared.setString('address', sessionData.getAccountAddress()); if (kDebugMode) { - print('\x1B[31m[Filled shared preferences]\x1B[0m'); - print('\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++\n' - '+ sessionData indirizzo account: ${sessionData.getAccountAddress()} +\n' + print('\x1B[31m\n[SESSION CREATION]\n' + '\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++\n' + '\n[SESSION DATA]\n' + '+ sessionData indirizzo accounts: ${sessionData.getAccountAddress()} +\n' + '\n[CONNECTOR]\n' '+ Connector è connesso?: ${sessionData.connector.connected} +\n' - '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n'); + '\n[NEW SESSION]\n' + 'accounts: ${newSession.accounts.toString()}' + '\n[SESSION STORAGE]\n' + 'accounts: ${(await sessionData.sessionStorage.getSession())?.accounts.length}\n' + '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\x1B[0m'); } -/* if(!ServicesControllerV2.statusGeofencingService) { - print('\x1B[31m [GEOFENCE SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); - SearchPlacesModel search = SearchPlacesModel(); - await search.getPermissions(); - ServicesControllerV2.initializeGeofencingService(); - }*/ + await sessionDb.deleteAll(); + await sessionDb.insertSession(Session(account: newSession.accounts[0], chainId: newSession.chainId, uri: sessionData.uri)); if(!ServicesControllerV2.statusCloseCampaignService) { print('\x1B[31m [CLOSED CAMPAIGN SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); diff --git a/lib/models/session_model.dart b/lib/models/session_model.dart index bf01bb8..8609abd 100644 --- a/lib/models/session_model.dart +++ b/lib/models/session_model.dart @@ -1,8 +1,10 @@ import 'package:walletconnect_dart/walletconnect_dart.dart'; +import 'package:walletconnect_secure_storage/walletconnect_secure_storage.dart'; import 'package:web3dart/web3dart.dart'; import 'package:flutter_config/flutter_config.dart'; import 'package:http/http.dart' as http; +import '../services/services_controllerV2.dart'; import 'db_session_model.dart'; class SessionModel { @@ -15,16 +17,44 @@ class SessionModel { late Web3Client ethClient; late EthereumWalletConnectProvider provider; final DbSessionModel dbSession = DbSessionModel(); + late WalletConnectSecureStorage sessionStorage; factory SessionModel() { return _instance; } - Future _initSession() async { + _initSession() { + sessionStorage = WalletConnectSecureStorage(); httpClient = http.Client(); ethClient = Web3Client(FlutterConfig.get('ADDRESS_BLOCK_CHAIN'), httpClient); - connector = WalletConnect( + + instantiateConnector(); + //return provider; + } + + Future instantiateConnector() async { + WalletConnectSession? session = await sessionStorage.getSession(); + if(session == null) { + print('\x1B[31m[SESSION MODEL] session null:${session.toString()} \x1B[0m'); + connector = WalletConnect( + bridge: 'https://bridge.walletconnect.org', + sessionStorage: sessionStorage, + clientMeta: const PeerMeta( + name: 'Mobile Crowd Sensing App', + description: 'An app for collect data with crowds', + url: 'https://walletconnect.org', + icons: [ + 'https://files.gitbook.com/v0/b/gitbook-legacy-files/o/spaces%2F-LJJeCjcLrr53DcT1Ml7%2Favatar.png?alt=media' + ] + ), + ); + } else { + print('\x1B[31m[SESSION MODEL] session:${session.toString()} \x1B[0m'); + await sessionStorage.store(session); + connector = WalletConnect( bridge: 'https://bridge.walletconnect.org', + session: session, + sessionStorage: sessionStorage, clientMeta: const PeerMeta( name: 'Mobile Crowd Sensing App', description: 'An app for collect data with crowds', @@ -32,49 +62,47 @@ class SessionModel { icons: [ 'https://files.gitbook.com/v0/b/gitbook-legacy-files/o/spaces%2F-LJJeCjcLrr53DcT1Ml7%2Favatar.png?alt=media' ] - ) - ); + ), + ); + await connector.connect( + onDisplayUri: (Exuri) async { + uri = Exuri; + }); + } + + await dbSession.deleteAll(); + await dbSession.insertSession(Session(account: connector.session.accounts[0], chainId: connector.session.chainId, uri: uri)); + if(!ServicesControllerV2.statusCloseCampaignService) { + print('\x1B[31m [CLOSED CAMPAIGN SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); + ServicesControllerV2.initializeCloseCampaignService(); + } + provider = EthereumWalletConnectProvider(connector); - connector.on('connect', (session) => { - print('\x1B[31m[checkConnection ON]\x1B[0m:connect'), - reconnect() + connector.on('connect', (SessionStatus session) => { + print('\x1B[31m[EVENT CONNECT] session:${session.toString()} \x1B[0m'), + connector.session.accounts = session.accounts, + connector.session.chainId = session.chainId, }); connector.on('session_update', (WCSessionUpdateResponse payload) async => { - print('\x1B[31m[checkConnection ON]\x1B[0m:session_update'), - connector.updateSession(SessionStatus(chainId: payload.chainId, accounts: payload.accounts)), - await dbSession.updateSession(Session(account: payload.accounts[0], chainId: payload.chainId)) + print('\x1B[31m[EVENT UPDATE] payload:${payload.toString()} \x1B[0m'), + connector.session.chainId = payload.chainId, + connector.session.accounts = payload.accounts, + await dbSession.updateSession(Session(account: payload.accounts[0], chainId: payload.chainId, uri: uri)) }); - connector.on('disconnect', (payload) => { - print('\x1B[31m[checkConnection ON]\x1B[0m:disconnect'), - closeConnection() + connector.on('disconnect', (Object? payload) async => { + print('\x1B[31m[EVENT DISCONNECT] ${payload.toString()}\x1B[0m'), + connector.killSession(), + ethClient.dispose(), }); - - - connector.registerListeners( - onConnect: (SessionStatus payload) { - print('\x1B[31m[checkConnection]\x1B[0m:connect'); - connector.session.accounts = payload.accounts; - connector.session.chainId = payload.chainId; - }, - onSessionUpdate: (WCSessionUpdateResponse res) async { - print('\x1B[31m[checkConnection]\x1B[0m:session_update'); - connector.session.chainId = res.chainId; - connector.session.accounts = res.accounts; - await dbSession.updateSession(Session(account: res.accounts[0], chainId: res.chainId)); - }, - onDisconnect: () async { - print('\x1B[31m[checkConnection]\x1B[0m:disconnect'); - await dbSession.deleteAll(); - } - ); - return provider; } + SessionModel._internal() { _initSession(); } + EthereumWalletConnectProvider getProvider(){ return provider; } @@ -83,34 +111,6 @@ class SessionModel { return connector.session.accounts[0]; } - /* Future checkConnection() async { - connector.on('connect', (session) => { - print('\x1B[31m[checkConnection]\x1B[0m:connect'), - reconnect() - }); - connector.on('session_update', (WCSessionUpdateResponse payload) async => { - print('\x1B[31m[checkConnection]\x1B[0m:session_update'), - connector.updateSession(SessionStatus(chainId: payload.chainId, accounts: payload.accounts)), - await dbSession.updateSession(Session(account: payload.accounts[0], chainId: payload.chainId)) - }); - connector.on('disconnect', (payload) => { - print('\x1B[31m[checkConnection]\x1B[0m:disconnect'), - closeConnection() - }); - }*/ - - void reconnect(){ - print('\x1B[31m[Connection reconnected]\x1B[0m:connect'); - connector.reconnect(); - } - void closeConnection() { - print('\x1B[31m[Reconnect]\x1B[0m:connect'); - connector.close(); - } - void killConnection(){ - print('\x1B[31m[Connection Killed]\x1B[0m:connect'); - connector.killSession(); - } getNetworkName(chainId) { switch (chainId) { case 1: diff --git a/lib/models/smart_contract_model.dart b/lib/models/smart_contract_model.dart index 37786ab..0e2efbf 100644 --- a/lib/models/smart_contract_model.dart +++ b/lib/models/smart_contract_model.dart @@ -26,7 +26,6 @@ class SmartContractModel extends CustomTransactionSender{ Future queryTransaction(String functionName, List args, BigInt? value) async { SessionModel session = SessionModel(); try { - //SessionModel().checkConnection(); int nonce = await session.ethClient.getTransactionCount(EthereumAddress.fromHex(session.getAccountAddress())); final contract = await loadContract(contractAddress); final ethFunction = contract.function(functionName); @@ -37,10 +36,11 @@ class SmartContractModel extends CustomTransactionSender{ nonce: nonce, value: (value != null) ? EtherAmount.inWei(value) : null ); - print('\x1B[31m nonce: $nonce gasPrice: ${transaction.gasPrice} maxGas: ${transaction.maxGas} \x1B[0m'); + print('\x1B[31m nonce: $nonce gasPrice: ${transaction.gasPrice} maxGas: ${transaction.maxGas} uri: ${session.uri} \x1B[0m'); launchUrlString(session.uri, mode: LaunchMode.externalApplication); final txBytes = await sendTransaction(transaction); + print('\x1B[31m [SENDED TRANSACTION] $txBytes \x1B[0m'); return txBytes; } catch (e) { if (kDebugMode) { @@ -53,7 +53,18 @@ class SmartContractModel extends CustomTransactionSender{ @override Future sendTransaction(Transaction transaction) async { SessionModel session = SessionModel(); + /* print( + '\x1B[31m BIG providerDEBUG-[sendTransaction] ' + '\nRPC URL (di solito vuoto): ${provider.connector.session.rpcUrl}' + '\naccounts: ${provider.connector.session.accounts.toString()}' + '\nKey: ${provider.connector.session.key}' + '\n PEER META: ${provider.connector.session.peerMeta?.toJson()}' + '\n Bridge: ${provider.connector.session.bridge}' + '\n PROTOCOL: ${provider.connector.session.protocol}' + '\n TO URI: ${provider.connector.session.toUri()}' + '\n\n\n TOJSON: ${provider.connector.session.toJson()}' + '\x1B[0m');*/ try { final hash = await provider.sendTransaction( from: session.getAccountAddress(), diff --git a/lib/services/servicesV2.dart b/lib/services/servicesV2.dart index b051c97..3820f4f 100644 --- a/lib/services/servicesV2.dart +++ b/lib/services/servicesV2.dart @@ -1,17 +1,15 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_background_service/flutter_background_service.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:http/http.dart' as http; +import 'package:mobile_crowd_sensing/models/db_session_model.dart'; import 'package:mobile_crowd_sensing/services/notification_channels.dart'; import 'package:mobile_crowd_sensing/services/services_controllerV2.dart'; -import 'package:shared_preferences/shared_preferences.dart'; import 'package:web3dart/web3dart.dart'; import '../models/db_capaign_model.dart'; import 'dart:async'; import 'dart:ui'; -import 'package:flutter/material.dart'; import 'package:flutter_background_service_android/flutter_background_service_android.dart'; import '../models/geofence_model.dart'; @@ -20,8 +18,6 @@ class ServicesV2 { static void onStart(ServiceInstance service) async { DartPluginRegistrant.ensureInitialized(); - SharedPreferences preferences = await SharedPreferences.getInstance(); - await preferences.reload(); if (service is AndroidServiceInstance) { service.on('setAsForeground').listen((event) { @@ -38,9 +34,9 @@ class ServicesV2 { }); DbCampaignModel db = DbCampaignModel(); + DbSessionModel dbSession = DbSessionModel(); List res = []; - String accountAddress = preferences.getString('address')!; - + List sessionRes = []; List geoList = []; final FlutterLocalNotificationsPlugin notification = @@ -48,6 +44,8 @@ class ServicesV2 { Timer.periodic(const Duration(minutes: 1), (timer) async { ServicesControllerV2.statusCloseCampaignService = true; + sessionRes = await dbSession.sessions(); + String accountAddress = sessionRes[0].account; res = await db.campaigns(); if (res.isNotEmpty) { for (Campaign c in res) { @@ -133,18 +131,6 @@ class ServicesV2 { }); } - static Future onIosBackground(ServiceInstance service) async { - WidgetsFlutterBinding.ensureInitialized(); - DartPluginRegistrant.ensureInitialized(); - - SharedPreferences preferences = await SharedPreferences.getInstance(); - await preferences.reload(); - final log = preferences.getStringList('log') ?? []; - log.add(DateTime.now().toIso8601String()); - await preferences.setStringList('log', log); - - return true; - } } class SmartContractModelBs { diff --git a/lib/services/services_controllerV2.dart b/lib/services/services_controllerV2.dart index fd02d47..ddccc17 100644 --- a/lib/services/services_controllerV2.dart +++ b/lib/services/services_controllerV2.dart @@ -33,7 +33,6 @@ class ServicesControllerV2 { iosConfiguration: IosConfiguration( autoStart: true, onForeground: ServicesV2.onStart, - onBackground: ServicesV2.onIosBackground, ), ); s.startService(); diff --git a/lib/views/all_campaign_view.dart b/lib/views/all_campaign_view.dart index 5e3e615..66d34be 100644 --- a/lib/views/all_campaign_view.dart +++ b/lib/views/all_campaign_view.dart @@ -1,13 +1,34 @@ import 'package:flutter/material.dart'; import '../controllers/all_campaign_controller.dart'; +import '../models/search_places_model.dart'; +import '../utils/spalsh_screens.dart'; class AllCampaignView extends StatelessWidget { final String cameFrom; const AllCampaignView({required this.cameFrom, super.key}); + Future _getPermission() async { + SearchPlacesModel p = SearchPlacesModel(); + return await p.getPermissions(); + } + @override Widget build(BuildContext context) { - return AllCampaignController(cameFrom: cameFrom,); + + return FutureBuilder( + future: _getPermission(), + builder: (BuildContext context, AsyncSnapshot snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.none: + return const Center(child: Text('Sorry something goes wrong...')); + case ConnectionState.waiting: + return CustomSplashScreen.fadingCubeBlueBg(context); + default: + return (snapshot.data == true)? AllCampaignController(cameFrom: cameFrom,) : const Center(child: Text('Position permission denied.')); + } + } + ); + } } diff --git a/lib/views/home_view.dart b/lib/views/home_view.dart index 3ceff92..fa8d6fa 100644 --- a/lib/views/home_view.dart +++ b/lib/views/home_view.dart @@ -23,16 +23,13 @@ class _HomeViewState extends State { } Widget _renderThis() { - SearchPlacesModel p = SearchPlacesModel(); switch (_selectedIndex){ case 1: return const SourcerView(); case 2: - p.getPermissions(); return const AllCampaignView(cameFrom: 'worker'); case 3: - p.getPermissions(); return const AllCampaignView(cameFrom: 'verifier'); default: return const WalletView(); diff --git a/lib/views/light_join_campaign_view.dart b/lib/views/light_join_campaign_view.dart index e9e31da..745aac7 100644 --- a/lib/views/light_join_campaign_view.dart +++ b/lib/views/light_join_campaign_view.dart @@ -22,6 +22,7 @@ class LightJoinCampaignViewState extends State { EnvironmentSensors environmentSensors = EnvironmentSensors(); bool activeSensor = false; + bool activeUpload = false; double sum = 0; List lights = []; @@ -147,6 +148,7 @@ class LightJoinCampaignViewState extends State { style: CustomTextStyle.inconsolata( context)) ]), + (!activeUpload)? FloatingActionButton( onPressed: () async { String? res = @@ -197,7 +199,15 @@ class LightJoinCampaignViewState extends State { }, backgroundColor: CustomColors.blue900(context), child: - const Icon(Icons.file_upload_sharp)), + const Icon(Icons.file_upload_sharp)) + : Expanded(child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + CircularProgressIndicator() + ], + ),), ]); } }) diff --git a/lib/views/verifier_campaign_data_light_view.dart b/lib/views/verifier_campaign_data_light_view.dart index a3e4029..54406e3 100644 --- a/lib/views/verifier_campaign_data_light_view.dart +++ b/lib/views/verifier_campaign_data_light_view.dart @@ -30,6 +30,7 @@ class _VerifierCampaignDataLightViewState extends State Date: Fri, 10 Feb 2023 01:18:17 +0100 Subject: [PATCH 22/34] removed warnings --- lib/controllers/all_campaign_controller.dart | 2 - lib/controllers/campaign_list_controller.dart | 1 - .../claim_campaign_controller.dart | 6 +- lib/controllers/distance_controller.dart | 6 +- .../login_check_connection_controller.dart | 1 - lib/controllers/login_controller.dart | 2 - .../validate_light_controller.dart | 2 - lib/controllers/wallet_controller.dart | 3 - lib/main.dart | 7 +- lib/models/db_capaign_model.dart | 4 +- lib/models/geofence_model.dart | 108 +++++++++--------- lib/models/ipfs_client_model.dart | 8 +- lib/models/login_metamask_model.dart | 9 +- lib/models/search_places_model.dart | 2 +- lib/models/session_model.dart | 20 ++-- lib/models/smart_contract_model.dart | 49 ++++---- lib/models/validate_model.dart | 4 +- lib/services/servicesV2.dart | 9 +- lib/services/services_controllerV2.dart | 4 +- lib/utils/internet_connection.dart | 4 +- lib/utils/nonce_manager.dart | 6 +- lib/utils/spalsh_screens.dart | 1 - lib/views/home_view.dart | 2 - lib/views/sourcer_closed_campaign_view.dart | 2 - lib/views/wallet_view.dart | 4 +- 25 files changed, 138 insertions(+), 128 deletions(-) diff --git a/lib/controllers/all_campaign_controller.dart b/lib/controllers/all_campaign_controller.dart index b405a1a..01299a7 100644 --- a/lib/controllers/all_campaign_controller.dart +++ b/lib/controllers/all_campaign_controller.dart @@ -1,8 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:mobile_crowd_sensing/controllers/search_places_controller.dart'; import 'package:mobile_crowd_sensing/utils/spalsh_screens.dart'; import '../models/all_campaign_model.dart'; -import '../models/search_places_model.dart'; import '../views/dialog_view.dart'; import '../views/verifier_campaign_view.dart'; import '../views/worker_campaign_view.dart'; diff --git a/lib/controllers/campaign_list_controller.dart b/lib/controllers/campaign_list_controller.dart index e07fae9..388741b 100644 --- a/lib/controllers/campaign_list_controller.dart +++ b/lib/controllers/campaign_list_controller.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:mobile_crowd_sensing/models/campaign_list_model.dart'; import 'package:numberpicker/numberpicker.dart'; diff --git a/lib/controllers/claim_campaign_controller.dart b/lib/controllers/claim_campaign_controller.dart index 444a27c..e8cb827 100644 --- a/lib/controllers/claim_campaign_controller.dart +++ b/lib/controllers/claim_campaign_controller.dart @@ -3,7 +3,6 @@ import 'package:flutter_config/flutter_config.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; import '../models/smart_contract_model.dart'; import '../utils/styles.dart'; -import '../views/login_view.dart'; class ClaimCampaignController extends StatefulWidget { const ClaimCampaignController({Key? key}) : super(key: key); @@ -93,10 +92,10 @@ class _ClaimCampaignControllerState extends State { abiFileRoot: 'assets/abi_campaign.json', provider: session.getProvider()); dynamic res = await smartContractViewModel.queryTransaction("withdrawCredits", [], null); - print("DEBUG::::::: res : ${res.toString()}"); if (res.toString() != "null" && res.toString() != "0x0000000000000000000000000000000000000000" && !res.startsWith('JSON-RPC error')) { + if(!mounted) return; ScaffoldMessenger.of(context) .showSnackBar(SnackBar( content: Text( @@ -105,6 +104,8 @@ class _ClaimCampaignControllerState extends State { .spaceMonoWhite(context), ))); }else if (res.startsWith('JSON-RPC error -32000:')){ + if(!mounted) return; + ScaffoldMessenger.of(context) .showSnackBar(SnackBar( content: Text( @@ -114,6 +115,7 @@ class _ClaimCampaignControllerState extends State { ))); } else { + if(!mounted) return; ScaffoldMessenger.of(context) .showSnackBar(SnackBar( content: Text( diff --git a/lib/controllers/distance_controller.dart b/lib/controllers/distance_controller.dart index 1c66dcb..bbe661c 100644 --- a/lib/controllers/distance_controller.dart +++ b/lib/controllers/distance_controller.dart @@ -1,5 +1,7 @@ import 'dart:math'; +import 'package:flutter/foundation.dart'; + class DistanceController { static double distanceBetween( @@ -19,7 +21,9 @@ class DistanceController { cos(_toRadians(endLatitude)); var c = 2 * asin(sqrt(a)); double distance = (earthRadius * c); - print("DISTANCE CALCULATED: $distance"); + if (kDebugMode) { + print("DISTANCE CALCULATED: $distance"); + } return distance; } diff --git a/lib/controllers/login_check_connection_controller.dart b/lib/controllers/login_check_connection_controller.dart index 9d03ad6..8a6a185 100644 --- a/lib/controllers/login_check_connection_controller.dart +++ b/lib/controllers/login_check_connection_controller.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; import 'package:slider_button/slider_button.dart'; - import '../utils/styles.dart'; import '../views/home_view.dart'; import 'login_metamask_controller.dart'; diff --git a/lib/controllers/login_controller.dart b/lib/controllers/login_controller.dart index 01f58fb..6970571 100644 --- a/lib/controllers/login_controller.dart +++ b/lib/controllers/login_controller.dart @@ -1,6 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:mobile_crowd_sensing/models/db_session_model.dart'; -import 'package:walletconnect_dart/walletconnect_dart.dart'; import '../utils/internet_connection.dart'; import '../utils/spalsh_screens.dart'; import 'login_check_connection_controller.dart'; diff --git a/lib/controllers/validate_light_controller.dart b/lib/controllers/validate_light_controller.dart index bb3f9a0..8e44fd5 100644 --- a/lib/controllers/validate_light_controller.dart +++ b/lib/controllers/validate_light_controller.dart @@ -35,8 +35,6 @@ class ValidateLightControllerState extends State { @override Widget build(BuildContext context) { - print("validate_light_controller"); - parameters = ModalRoute.of(context)!.settings.arguments; campaignSelectedData = jsonDecode(jsonEncode(parameters)); hash = campaignSelectedData['ipfsHash']; diff --git a/lib/controllers/wallet_controller.dart b/lib/controllers/wallet_controller.dart index 6a19882..0e8b1ee 100644 --- a/lib/controllers/wallet_controller.dart +++ b/lib/controllers/wallet_controller.dart @@ -1,10 +1,7 @@ import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; -import 'package:flutter_config/flutter_config.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; -import 'package:mobile_crowd_sensing/views/login_view.dart'; -import '../models/smart_contract_model.dart'; import '../models/wallet_model.dart'; import '../utils/styles.dart'; import 'package:flip_card/flip_card.dart'; diff --git a/lib/main.dart b/lib/main.dart index 64bacd0..1c1fd30 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,7 +2,6 @@ import 'dart:io'; import 'package:flip_card/flip_card.dart'; import 'package:flutter/material.dart'; import 'package:flutter_config/flutter_config.dart'; -import 'package:mobile_crowd_sensing/models/db_session_model.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; import 'package:mobile_crowd_sensing/utils/internet_connection.dart'; import 'package:mobile_crowd_sensing/utils/styles.dart'; @@ -24,9 +23,10 @@ import 'package:mobile_crowd_sensing/views/validate_photo_view.dart'; import 'package:mobile_crowd_sensing/views/wallet_view.dart'; import 'dart:async'; import 'package:connectivity/connectivity.dart'; -import 'package:flutter/widgets.dart'; class LifecycleWatcher extends StatefulWidget { + const LifecycleWatcher({super.key}); + @override _LifecycleWatcherState createState() => _LifecycleWatcherState(); } @@ -50,7 +50,6 @@ class _LifecycleWatcherState extends State with WidgetsBinding super.didChangeAppLifecycleState(state); if(state == AppLifecycleState.detached) { - print('\x1B[31m[STATUS APP] : ${state.toString()}\x1B[0m'); SessionModel sessionModel = SessionModel(); sessionModel.connector.killSession(); } @@ -72,7 +71,7 @@ Future main(List args) async { if (initialStateInternet == ConnectivityResult.none) { runApp(const NoConnection()); } else { - return runApp(Center(child: LifecycleWatcher())); + return runApp(const Center(child: LifecycleWatcher())); } } diff --git a/lib/models/db_capaign_model.dart b/lib/models/db_capaign_model.dart index 0a6b4bf..ab781cd 100644 --- a/lib/models/db_capaign_model.dart +++ b/lib/models/db_capaign_model.dart @@ -42,7 +42,7 @@ class DbCampaignModel { cmp.toMap(), conflictAlgorithm: ConflictAlgorithm.replace, ); - ServicesControllerV2.resetServicies(); + ServicesControllerV2.resetService(); } Future> campaigns() async { @@ -77,7 +77,7 @@ class DbCampaignModel { where: 'address = ?', whereArgs: [address], ); - ServicesControllerV2.resetServicies(); + ServicesControllerV2.resetService(); } } diff --git a/lib/models/geofence_model.dart b/lib/models/geofence_model.dart index 10d48d3..9c8ad55 100644 --- a/lib/models/geofence_model.dart +++ b/lib/models/geofence_model.dart @@ -9,15 +9,14 @@ import 'dart:ui'; enum GeofenceEvent { init, enter, exit } class Geofence { - late String title,address,lat,lng,radius; + late String title, address, lat, lng, radius; StreamSubscription? _positionStream; Stream? _geostream; - final StreamController _controller = StreamController(); - - - Geofence(this.title,this.address,this.lat,this.lng,this.radius); + final StreamController _controller = + StreamController(); + Geofence(this.title, this.address, this.lat, this.lng, this.radius); Future initialize() async { DartPluginRegistrant.ensureInitialized(); @@ -25,7 +24,7 @@ class Geofence { String debugString = "[GEOFENCE $title]"; final FlutterLocalNotificationsPlugin notification = - FlutterLocalNotificationsPlugin(); + FlutterLocalNotificationsPlugin(); if (kDebugMode) { print('\x1B[31m [GEOFENCE SERVICE] geofence open for:' @@ -74,40 +73,10 @@ class Geofence { if (kDebugMode) { print('\x1B[31m $debugString status: Enter\x1B[0m'); } - (previous != event) - ? notification.show( - 888, - 'Entered in Campaign Area', - '[$title] \nat address: $address', - NotificationDetails( - android: AndroidNotificationDetails( - NotificationChannel.backgroundServiceChannel.id, - NotificationChannel.backgroundServiceChannel.name, - icon: 'ic_bg_service_small', - styleInformation: BigTextStyleInformation( - "

You are entered inside the \"$title\" \n campaign at address: \n$address

", - htmlFormatBigText: true, - contentTitle: "

ENTER INSIDE \"$title\"

", - htmlFormatContentTitle: true, - summaryText: "

you entered in a campaign area

", - htmlFormatSummaryText: true, - htmlFormatContent: true, - htmlFormatTitle: true), - ongoing: true, - ), - ), - ) - : print('\x1B[31m $debugString status not changed \x1B[0m'); - previous = event; - break; - case GeofenceEvent.exit: - if (kDebugMode) { - print('\x1B[31m $debugString status: Exit\x1B[0m'); - } - (previous != event) - ? notification.show( + if (previous != event) { + notification.show( 888, - 'Exit from Campaign Area', + 'Entered in Campaign Area', '[$title] \nat address: $address', NotificationDetails( android: AndroidNotificationDetails( @@ -115,32 +84,67 @@ class Geofence { NotificationChannel.backgroundServiceChannel.name, icon: 'ic_bg_service_small', styleInformation: BigTextStyleInformation( - "

You are out of the \"$title\" \n campaign at address: \n$address

", + "

You are entered inside the \"$title\" \n campaign at address: \n$address

", htmlFormatBigText: true, - contentTitle: "

EXIT FROM \"$title\"

", + contentTitle: "

ENTER INSIDE \"$title\"

", htmlFormatContentTitle: true, - summaryText: "

you exit from a campaign area

", + summaryText: "

you entered in a campaign area

", htmlFormatSummaryText: true, htmlFormatContent: true, htmlFormatTitle: true), ongoing: true, ), - )) - : print('\x1B[31m $debugString status not changed \x1B[0m'); + ), + ); + } else { + if (kDebugMode) { + print('\x1B[31m $debugString status not changed \x1B[0m'); + } + } + previous = event; + break; + case GeofenceEvent.exit: + if (kDebugMode) { + print('\x1B[31m $debugString status: Exit\x1B[0m'); + } + if (previous != event) { + notification.show( + 888, + 'Exit from Campaign Area', + '[$title] \nat address: $address', + NotificationDetails( + android: AndroidNotificationDetails( + NotificationChannel.backgroundServiceChannel.id, + NotificationChannel.backgroundServiceChannel.name, + icon: 'ic_bg_service_small', + styleInformation: BigTextStyleInformation( + "

You are out of the \"$title\" \n campaign at address: \n$address

", + htmlFormatBigText: true, + contentTitle: "

EXIT FROM \"$title\"

", + htmlFormatContentTitle: true, + summaryText: "

you exit from a campaign area

", + htmlFormatSummaryText: true, + htmlFormatContent: true, + htmlFormatTitle: true), + ongoing: true, + ), + )); + } else { + if (kDebugMode) { + print('\x1B[31m $debugString status not changed \x1B[0m'); + } + } previous = event; - break; } }); } - - _startGeofenceService( {required String pointedLatitude, - required String pointedLongitude, - required String radiusMeter, - required int eventPeriodInSeconds}) async { + required String pointedLongitude, + required String radiusMeter, + required int eventPeriodInSeconds}) async { double latitude = _parser(pointedLatitude); double longitude = _parser(pointedLongitude); double radiusInMeter = _parser(radiusMeter); @@ -153,8 +157,8 @@ class Geofence { if (_positionStream == null) { _geostream = _controller.stream; _positionStream = Geolocator.getPositionStream( - locationSettings: - LocationSettings(accuracy: LocationAccuracy.best)) + locationSettings: + const LocationSettings(accuracy: LocationAccuracy.best)) .listen((Position? position) { if (position != null) { double distanceInMeters = DistanceController.distanceBetween( diff --git a/lib/models/ipfs_client_model.dart b/lib/models/ipfs_client_model.dart index 5d4e324..5c4d90e 100644 --- a/lib/models/ipfs_client_model.dart +++ b/lib/models/ipfs_client_model.dart @@ -139,7 +139,9 @@ class IpfsClientModel { StreamedResponse response = await request.send(); var result = await http.Response.fromStream(response); if (result.statusCode == 200) { - print('\x1B[31m${result.statusCode.toString()}\x1B[0m'); + if (kDebugMode) { + print('\x1B[31m${result.statusCode.toString()}\x1B[0m'); + } File compressedFile = await File("$tmpPath/$localFolder/$name").writeAsBytes(result.bodyBytes); Directory dir = Directory("$tmpPath/$localFolder/out"); await extractFileToDisk(compressedFile.path, dir.path); @@ -148,7 +150,9 @@ class IpfsClientModel { Directory out = Directory(entity.path); return out.list(); } - print('\x1B[31m${result.toString()}\x1B[0m'); + if (kDebugMode) { + print('\x1B[31m${result.toString()}\x1B[0m'); + } return null; } diff --git a/lib/models/login_metamask_model.dart b/lib/models/login_metamask_model.dart index 48c6d90..54ddae0 100644 --- a/lib/models/login_metamask_model.dart +++ b/lib/models/login_metamask_model.dart @@ -3,7 +3,6 @@ import 'package:flutter/foundation.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; import 'package:url_launcher/url_launcher_string.dart'; import 'package:walletconnect_dart/walletconnect_dart.dart'; - import '../services/services_controllerV2.dart'; import 'db_session_model.dart'; @@ -17,7 +16,9 @@ class LoginMetamaskModel { try { SessionStatus newSession = await sessionData.connector.createSession( onDisplayUri: (uri) async { - print('\x1B[31m[LOGIN METAMASK] uri: ${uri}\x1B[0m'); + if (kDebugMode) { + print('\x1B[31m[LOGIN METAMASK] uri: $uri\x1B[0m'); + } sessionData.uri = uri; await launchUrlString(uri, mode: LaunchMode.externalApplication); @@ -41,7 +42,9 @@ class LoginMetamaskModel { await sessionDb.insertSession(Session(account: newSession.accounts[0], chainId: newSession.chainId, uri: sessionData.uri)); if(!ServicesControllerV2.statusCloseCampaignService) { - print('\x1B[31m [CLOSED CAMPAIGN SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); + if (kDebugMode) { + print('\x1B[31m [CLOSED CAMPAIGN SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); + } ServicesControllerV2.initializeCloseCampaignService(); } diff --git a/lib/models/search_places_model.dart b/lib/models/search_places_model.dart index 5cb6ec2..320d466 100644 --- a/lib/models/search_places_model.dart +++ b/lib/models/search_places_model.dart @@ -13,7 +13,7 @@ class SearchPlacesModel { late LocationPermission permission; Future updateLocalPosition() async { - await Future.delayed(Duration(seconds: 1)); + await Future.delayed(const Duration(seconds: 1)); position = await _getGeoLocationPosition(); lng = position.longitude; lat = position.latitude; diff --git a/lib/models/session_model.dart b/lib/models/session_model.dart index 8609abd..423ba47 100644 --- a/lib/models/session_model.dart +++ b/lib/models/session_model.dart @@ -1,9 +1,9 @@ +import 'package:flutter/foundation.dart'; import 'package:walletconnect_dart/walletconnect_dart.dart'; import 'package:walletconnect_secure_storage/walletconnect_secure_storage.dart'; import 'package:web3dart/web3dart.dart'; import 'package:flutter_config/flutter_config.dart'; import 'package:http/http.dart' as http; - import '../services/services_controllerV2.dart'; import 'db_session_model.dart'; @@ -35,7 +35,9 @@ class SessionModel { Future instantiateConnector() async { WalletConnectSession? session = await sessionStorage.getSession(); if(session == null) { - print('\x1B[31m[SESSION MODEL] session null:${session.toString()} \x1B[0m'); + if (kDebugMode) { + print('\x1B[31m[SESSION MODEL] session null:${session.toString()} \x1B[0m'); + } connector = WalletConnect( bridge: 'https://bridge.walletconnect.org', sessionStorage: sessionStorage, @@ -49,7 +51,9 @@ class SessionModel { ), ); } else { - print('\x1B[31m[SESSION MODEL] session:${session.toString()} \x1B[0m'); + if (kDebugMode) { + print('\x1B[31m[SESSION MODEL] session:${session.toString()} \x1B[0m'); + } await sessionStorage.store(session); connector = WalletConnect( bridge: 'https://bridge.walletconnect.org', @@ -65,18 +69,20 @@ class SessionModel { ), ); await connector.connect( - onDisplayUri: (Exuri) async { - uri = Exuri; + onDisplayUri: (newUri) async { + uri = newUri; }); } await dbSession.deleteAll(); await dbSession.insertSession(Session(account: connector.session.accounts[0], chainId: connector.session.chainId, uri: uri)); if(!ServicesControllerV2.statusCloseCampaignService) { - print('\x1B[31m [CLOSED CAMPAIGN SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); + if (kDebugMode) { + print('\x1B[31m [CLOSED CAMPAIGN SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); + } ServicesControllerV2.initializeCloseCampaignService(); } - + provider = EthereumWalletConnectProvider(connector); connector.on('connect', (SessionStatus session) => { diff --git a/lib/models/smart_contract_model.dart b/lib/models/smart_contract_model.dart index 0e2efbf..8bd16e0 100644 --- a/lib/models/smart_contract_model.dart +++ b/lib/models/smart_contract_model.dart @@ -6,10 +6,12 @@ import 'package:walletconnect_dart/walletconnect_dart.dart'; import 'package:web3dart/src/crypto/secp256k1.dart'; import 'package:web3dart/web3dart.dart'; -import '../utils/nonce_manager.dart'; - -class SmartContractModel extends CustomTransactionSender{ - SmartContractModel({required this.contractAddress, required this.abiName, required this.abiFileRoot, required this.provider}); +class SmartContractModel extends CustomTransactionSender { + SmartContractModel( + {required this.contractAddress, + required this.abiName, + required this.abiFileRoot, + required this.provider}); final EthereumWalletConnectProvider provider; final String contractAddress; @@ -23,10 +25,12 @@ class SmartContractModel extends CustomTransactionSender{ return contract; } - Future queryTransaction(String functionName, List args, BigInt? value) async { + Future queryTransaction( + String functionName, List args, BigInt? value) async { SessionModel session = SessionModel(); try { - int nonce = await session.ethClient.getTransactionCount(EthereumAddress.fromHex(session.getAccountAddress())); + int nonce = await session.ethClient.getTransactionCount( + EthereumAddress.fromHex(session.getAccountAddress())); final contract = await loadContract(contractAddress); final ethFunction = contract.function(functionName); Transaction transaction = Transaction.callContract( @@ -34,13 +38,17 @@ class SmartContractModel extends CustomTransactionSender{ function: ethFunction, parameters: args, nonce: nonce, - value: (value != null) ? EtherAmount.inWei(value) : null - ); - print('\x1B[31m nonce: $nonce gasPrice: ${transaction.gasPrice} maxGas: ${transaction.maxGas} uri: ${session.uri} \x1B[0m'); + value: (value != null) ? EtherAmount.inWei(value) : null); + if (kDebugMode) { + print( + '\x1B[31m nonce: $nonce gasPrice: ${transaction.gasPrice} maxGas: ${transaction.maxGas} uri: ${session.uri} \x1B[0m'); + } launchUrlString(session.uri, mode: LaunchMode.externalApplication); final txBytes = await sendTransaction(transaction); - print('\x1B[31m [SENDED TRANSACTION] $txBytes \x1B[0m'); + if (kDebugMode) { + print('\x1B[31m [SENDED TRANSACTION] $txBytes \x1B[0m'); + } return txBytes; } catch (e) { if (kDebugMode) { @@ -53,18 +61,6 @@ class SmartContractModel extends CustomTransactionSender{ @override Future sendTransaction(Transaction transaction) async { SessionModel session = SessionModel(); - /* print( - '\x1B[31m BIG providerDEBUG-[sendTransaction] ' - '\nRPC URL (di solito vuoto): ${provider.connector.session.rpcUrl}' - '\naccounts: ${provider.connector.session.accounts.toString()}' - '\nKey: ${provider.connector.session.key}' - '\n PEER META: ${provider.connector.session.peerMeta?.toJson()}' - '\n Bridge: ${provider.connector.session.bridge}' - '\n PROTOCOL: ${provider.connector.session.protocol}' - '\n TO URI: ${provider.connector.session.toUri()}' - - '\n\n\n TOJSON: ${provider.connector.session.toJson()}' - '\x1B[0m');*/ try { final hash = await provider.sendTransaction( from: session.getAccountAddress(), @@ -84,7 +80,8 @@ class SmartContractModel extends CustomTransactionSender{ } } - Future?> queryCall(String functionName, List args) async { + Future?> queryCall( + String functionName, List args) async { SessionModel session = SessionModel(); try { final contract = await loadContract(contractAddress); @@ -115,13 +112,15 @@ class SmartContractModel extends CustomTransactionSender{ } @override - MsgSignature signToEcSignature(Uint8List payload, {int? chainId, bool isEIP1559 = false}) { + MsgSignature signToEcSignature(Uint8List payload, + {int? chainId, bool isEIP1559 = false}) { // TODO: implement signToEcSignature throw UnimplementedError(); } @override - Future signToSignature(Uint8List payload, {int? chainId, bool isEIP1559 = false}) { + Future signToSignature(Uint8List payload, + {int? chainId, bool isEIP1559 = false}) { // TODO: implement signToSignature throw UnimplementedError(); } diff --git a/lib/models/validate_model.dart b/lib/models/validate_model.dart index 8de162d..06a8bdf 100644 --- a/lib/models/validate_model.dart +++ b/lib/models/validate_model.dart @@ -40,7 +40,9 @@ class ValidateModel { if (res != null) { out = res; - print("DEB: ${res.toString()}"); + if (kDebugMode) { + print("DEB: ${res.toString()}"); + } out.add( (await searchPlacesViewModel.getReadebleLocationFromLatLng( (double.parse(res[5].toString())) / 10000000, diff --git a/lib/services/servicesV2.dart b/lib/services/servicesV2.dart index 3820f4f..6fe2fa6 100644 --- a/lib/services/servicesV2.dart +++ b/lib/services/servicesV2.dart @@ -11,7 +11,6 @@ import '../models/db_capaign_model.dart'; import 'dart:async'; import 'dart:ui'; import 'package:flutter_background_service_android/flutter_background_service_android.dart'; - import '../models/geofence_model.dart'; class ServicesV2 { @@ -109,18 +108,20 @@ class ServicesV2 { } //..... - geoList.forEach((element) {element.stopGeofenceService();}); + for (var element in geoList) {element.stopGeofenceService();} geoList.clear(); for (Campaign c in res) { Geofence g = Geofence(c.title, c.address, c.lat, c.lng, c.radius); geoList.add(g); g.initialize(); } - print('\x1B[31m [GEOFENCE SERVICE] active geofences: ${geoList.length}. \x1B[0m'); + if (kDebugMode) { + print('\x1B[31m [GEOFENCE SERVICE] active geofences: ${geoList.length}. \x1B[0m'); + } } else { ServicesControllerV2.statusCloseCampaignService = false; timer.cancel(); - geoList.forEach((element) {element.stopGeofenceService();}); + for (var element in geoList) {element.stopGeofenceService();} geoList.clear(); service.stopSelf(); if (kDebugMode) { diff --git a/lib/services/services_controllerV2.dart b/lib/services/services_controllerV2.dart index ddccc17..523da41 100644 --- a/lib/services/services_controllerV2.dart +++ b/lib/services/services_controllerV2.dart @@ -1,8 +1,6 @@ import 'package:flutter_background_service/flutter_background_service.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:mobile_crowd_sensing/services/servicesV2.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import '../models/db_capaign_model.dart'; import 'notification_channels.dart'; class ServicesControllerV2 { @@ -39,7 +37,7 @@ class ServicesControllerV2 { statusCloseCampaignService = true; } - static void resetServicies() async { + static void resetService() async { statusCloseCampaignService = true; initializeCloseCampaignService(); } diff --git a/lib/utils/internet_connection.dart b/lib/utils/internet_connection.dart index b31ef62..f4796a7 100644 --- a/lib/utils/internet_connection.dart +++ b/lib/utils/internet_connection.dart @@ -4,7 +4,7 @@ import 'package:connectivity/connectivity.dart'; import '../main.dart'; class InternetConnection { - static var connectionStatus; + static late ConnectivityResult connectionStatus; static Future checkInternetConnectivity() async { connectionStatus = await Connectivity().checkConnectivity(); @@ -12,7 +12,7 @@ class InternetConnection { PageRouteBuilder( pageBuilder: (_, __, ___) => MaterialApp(home: Builder( - builder: (_) => MyApp())), + builder: (_) => const MyApp())), transitionDuration: Duration.zero,); } } diff --git a/lib/utils/nonce_manager.dart b/lib/utils/nonce_manager.dart index d4576d0..fb1f115 100644 --- a/lib/utils/nonce_manager.dart +++ b/lib/utils/nonce_manager.dart @@ -1,3 +1,5 @@ +import 'package:flutter/foundation.dart'; + class NonceManager { static int nonce = 1; @@ -5,7 +7,9 @@ class NonceManager { try { return nonce; } finally { - print("assigned nonce: $nonce"); + if (kDebugMode) { + print("assigned nonce: $nonce"); + } nonce ++; } } diff --git a/lib/utils/spalsh_screens.dart b/lib/utils/spalsh_screens.dart index d4e8a46..7a20ee8 100644 --- a/lib/utils/spalsh_screens.dart +++ b/lib/utils/spalsh_screens.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:mobile_crowd_sensing/utils/styles.dart'; diff --git a/lib/views/home_view.dart b/lib/views/home_view.dart index fa8d6fa..eee0a72 100644 --- a/lib/views/home_view.dart +++ b/lib/views/home_view.dart @@ -1,8 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:geolocator/geolocator.dart'; import 'package:mobile_crowd_sensing/views/sourcer_view.dart'; import 'package:mobile_crowd_sensing/views/wallet_view.dart'; -import '../models/search_places_model.dart'; import '../utils/styles.dart'; import 'all_campaign_view.dart'; diff --git a/lib/views/sourcer_closed_campaign_view.dart b/lib/views/sourcer_closed_campaign_view.dart index cf69cdf..c9eef8c 100644 --- a/lib/views/sourcer_closed_campaign_view.dart +++ b/lib/views/sourcer_closed_campaign_view.dart @@ -18,8 +18,6 @@ class _SourcerClosedCampaignViewState extends State { Widget build(BuildContext context) { List? contractAddress = widget.contractAddress; - print("DEBUG sourcer_closed_campaign_view:::: ${contractAddress.toString()}"); - return Scaffold( appBar: AppBar( backgroundColor: CustomColors.blue900(context), diff --git a/lib/views/wallet_view.dart b/lib/views/wallet_view.dart index c7d9060..2ba6af8 100644 --- a/lib/views/wallet_view.dart +++ b/lib/views/wallet_view.dart @@ -13,8 +13,8 @@ class WalletView extends StatelessWidget { Widget build(BuildContext context) { SessionModel session = SessionModel(); if(!session.provider.connector.connected) { - WidgetsBinding.instance!.addPostFrameCallback((_) { - Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => LoginView())); + WidgetsBinding.instance.addPostFrameCallback((_) { + Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => const LoginView())); });} return Scaffold( From bfcb04dac5b493eb7d56187275b47698d7b5b685 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Sat, 11 Feb 2023 11:45:52 +0100 Subject: [PATCH 23/34] refactor + warnings --- .../login_check_connection_controller.dart | 6 +- lib/main.dart | 14 +- lib/models/db_capaign_model.dart | 6 +- lib/models/login_metamask_model.dart | 21 +- lib/models/session_model.dart | 66 +++--- lib/services/services.dart | 199 ++++++++++++++++++ lib/services/servicesV2.dart | 182 ---------------- ...rollerV2.dart => services_controller.dart} | 19 +- lib/views/error_view.dart | 39 ++++ 9 files changed, 317 insertions(+), 235 deletions(-) create mode 100644 lib/services/services.dart delete mode 100644 lib/services/servicesV2.dart rename lib/services/{services_controllerV2.dart => services_controller.dart} (71%) create mode 100644 lib/views/error_view.dart diff --git a/lib/controllers/login_check_connection_controller.dart b/lib/controllers/login_check_connection_controller.dart index 8a6a185..81f214e 100644 --- a/lib/controllers/login_check_connection_controller.dart +++ b/lib/controllers/login_check_connection_controller.dart @@ -19,7 +19,7 @@ class _LoginCheckConnectionControllerState extends State with WidgetsBinding if(state == AppLifecycleState.detached) { SessionModel sessionModel = SessionModel(); - sessionModel.connector.killSession(); + sessionModel.connector!.killSession(); } } @@ -171,6 +176,13 @@ class _MyAppState extends State { @override Widget build(BuildContext context) { return MaterialApp( + builder: (context,widget) { + ErrorWidget.builder = (FlutterErrorDetails errorDetails) { + return Column(children:[CustomError(errorDetails: errorDetails)]); + }; + return widget!; + }, + title: "MOBILE CROWD SENSING", initialRoute: '/login', routes: { '/home': (context) => const HomeView(), diff --git a/lib/models/db_capaign_model.dart b/lib/models/db_capaign_model.dart index ab781cd..1661236 100644 --- a/lib/models/db_capaign_model.dart +++ b/lib/models/db_capaign_model.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; -import '../services/services_controllerV2.dart'; +import '../services/services_controller.dart'; class DbCampaignModel { @@ -42,7 +42,7 @@ class DbCampaignModel { cmp.toMap(), conflictAlgorithm: ConflictAlgorithm.replace, ); - ServicesControllerV2.resetService(); + ServicesController.resetService(); } Future> campaigns() async { @@ -77,7 +77,7 @@ class DbCampaignModel { where: 'address = ?', whereArgs: [address], ); - ServicesControllerV2.resetService(); + ServicesController.resetService(); } } diff --git a/lib/models/login_metamask_model.dart b/lib/models/login_metamask_model.dart index 54ddae0..c8c88d6 100644 --- a/lib/models/login_metamask_model.dart +++ b/lib/models/login_metamask_model.dart @@ -1,9 +1,10 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; +import 'package:mobile_crowd_sensing/models/db_capaign_model.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; import 'package:url_launcher/url_launcher_string.dart'; import 'package:walletconnect_dart/walletconnect_dart.dart'; -import '../services/services_controllerV2.dart'; +import '../services/services_controller.dart'; import 'db_session_model.dart'; class LoginMetamaskModel { @@ -11,10 +12,9 @@ class LoginMetamaskModel { static Future loginUsingMetamask(BuildContext context) async { SessionModel sessionData = SessionModel(); - if (!sessionData.connector.connected) { - DbSessionModel sessionDb = DbSessionModel(); + if (!sessionData.connector!.connected) { try { - SessionStatus newSession = await sessionData.connector.createSession( + SessionStatus newSession = await sessionData.connector!.createSession( onDisplayUri: (uri) async { if (kDebugMode) { print('\x1B[31m[LOGIN METAMASK] uri: $uri\x1B[0m'); @@ -30,7 +30,7 @@ class LoginMetamaskModel { '\n[SESSION DATA]\n' '+ sessionData indirizzo accounts: ${sessionData.getAccountAddress()} +\n' '\n[CONNECTOR]\n' - '+ Connector è connesso?: ${sessionData.connector.connected} +\n' + '+ Connector è connesso?: ${sessionData.connector!.connected} +\n' '\n[NEW SESSION]\n' 'accounts: ${newSession.accounts.toString()}' '\n[SESSION STORAGE]\n' @@ -38,14 +38,15 @@ class LoginMetamaskModel { '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\x1B[0m'); } - await sessionDb.deleteAll(); - await sessionDb.insertSession(Session(account: newSession.accounts[0], chainId: newSession.chainId, uri: sessionData.uri)); - - if(!ServicesControllerV2.statusCloseCampaignService) { + await sessionData.dbSession.deleteAll(); + await sessionData.dbSession.insertSession(Session(account: newSession.accounts[0], chainId: newSession.chainId, uri: sessionData.uri)); + DbCampaignModel dbCampaign = DbCampaignModel(); + List listCamapigns = await dbCampaign.campaigns(); + if(listCamapigns.isNotEmpty) { if (kDebugMode) { print('\x1B[31m [CLOSED CAMPAIGN SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); } - ServicesControllerV2.initializeCloseCampaignService(); + ServicesController.initializeBackgroundService(); } } catch (exp) { diff --git a/lib/models/session_model.dart b/lib/models/session_model.dart index 423ba47..a976727 100644 --- a/lib/models/session_model.dart +++ b/lib/models/session_model.dart @@ -4,7 +4,8 @@ import 'package:walletconnect_secure_storage/walletconnect_secure_storage.dart'; import 'package:web3dart/web3dart.dart'; import 'package:flutter_config/flutter_config.dart'; import 'package:http/http.dart' as http; -import '../services/services_controllerV2.dart'; +import '../services/services_controller.dart'; +import 'db_capaign_model.dart'; import 'db_session_model.dart'; class SessionModel { @@ -12,7 +13,7 @@ class SessionModel { static final SessionModel _instance = SessionModel._internal(); late dynamic uri, signature; - late WalletConnect connector; + late WalletConnect? connector; late http.Client httpClient; late Web3Client ethClient; late EthereumWalletConnectProvider provider; @@ -29,7 +30,6 @@ class SessionModel { ethClient = Web3Client(FlutterConfig.get('ADDRESS_BLOCK_CHAIN'), httpClient); instantiateConnector(); - //return provider; } Future instantiateConnector() async { @@ -68,39 +68,50 @@ class SessionModel { ] ), ); - await connector.connect( + await connector!.connect( onDisplayUri: (newUri) async { uri = newUri; }); } await dbSession.deleteAll(); - await dbSession.insertSession(Session(account: connector.session.accounts[0], chainId: connector.session.chainId, uri: uri)); - if(!ServicesControllerV2.statusCloseCampaignService) { + await dbSession.insertSession(Session(account: connector!.session.accounts[0], chainId: connector!.session.chainId, uri: uri)); + DbCampaignModel dbCampaign = DbCampaignModel(); + List listCamapigns = await dbCampaign.campaigns(); + if(listCamapigns.isNotEmpty) { if (kDebugMode) { print('\x1B[31m [CLOSED CAMPAIGN SERVICE] INITIALIZE AFTER LOGIN\x1B[0m'); } - ServicesControllerV2.initializeCloseCampaignService(); + ServicesController.initializeBackgroundService(); } - provider = EthereumWalletConnectProvider(connector); - - connector.on('connect', (SessionStatus session) => { - print('\x1B[31m[EVENT CONNECT] session:${session.toString()} \x1B[0m'), - connector.session.accounts = session.accounts, - connector.session.chainId = session.chainId, - }); - connector.on('session_update', (WCSessionUpdateResponse payload) async => { - print('\x1B[31m[EVENT UPDATE] payload:${payload.toString()} \x1B[0m'), - connector.session.chainId = payload.chainId, - connector.session.accounts = payload.accounts, - await dbSession.updateSession(Session(account: payload.accounts[0], chainId: payload.chainId, uri: uri)) - }); - connector.on('disconnect', (Object? payload) async => { - print('\x1B[31m[EVENT DISCONNECT] ${payload.toString()}\x1B[0m'), - connector.killSession(), - ethClient.dispose(), - }); + provider = EthereumWalletConnectProvider(connector!); + + connector!.registerListeners( + onDisconnect: () { + if (kDebugMode) { + print('\x1B[31m[EVENT DISCONNECT] \x1B[0m'); + } + connector!.killSession(); + connector = null; + ethClient.dispose(); + }, + onConnect: (SessionStatus session){ + if (kDebugMode) { + print('\x1B[31m[EVENT CONNECT] session:${session.toString()} \x1B[0m'); + } + connector!.session.accounts = session.accounts; + connector!.session.chainId = session.chainId; + }, + onSessionUpdate: (WCSessionUpdateResponse payload) async { + if (kDebugMode) { + print('\x1B[31m[EVENT UPDATE] payload:${payload.toString()} \x1B[0m'); + } + connector!.session.chainId = payload.chainId; + connector!.session.accounts = payload.accounts; + await dbSession.updateSession(Session(account: payload.accounts[0], chainId: payload.chainId, uri: uri)); + } + ); } @@ -114,7 +125,10 @@ class SessionModel { } dynamic getAccountAddress() { - return connector.session.accounts[0]; + if (connector == null) { + instantiateConnector(); + } + return connector!.session.accounts[0]; } getNetworkName(chainId) { diff --git a/lib/services/services.dart b/lib/services/services.dart new file mode 100644 index 0000000..f1ea2fd --- /dev/null +++ b/lib/services/services.dart @@ -0,0 +1,199 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_background_service/flutter_background_service.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:http/http.dart' as http; +import 'package:mobile_crowd_sensing/models/db_session_model.dart'; +import 'package:mobile_crowd_sensing/services/notification_channels.dart'; +import 'package:mobile_crowd_sensing/services/services_controller.dart'; +import 'package:web3dart/web3dart.dart'; +import '../models/db_capaign_model.dart'; +import 'dart:async'; +import 'dart:ui'; +import 'package:flutter_background_service_android/flutter_background_service_android.dart'; +import '../models/geofence_model.dart'; + +class Services { + static void onStart(ServiceInstance service) async { + DartPluginRegistrant.ensureInitialized(); + + if (service is AndroidServiceInstance) { + service.on('setAsForeground').listen((event) { + service.setAsForegroundService(); + }); + + service.on('setAsBackground').listen((event) { + service.setAsBackgroundService(); + }); + } + + service.on('stopService').listen((event) { + service.stopSelf(); + }); + + DbCampaignModel db = DbCampaignModel(); + DbSessionModel dbSession = DbSessionModel(); + List res = []; + List sessionRes = []; + List geoList = []; + + final FlutterLocalNotificationsPlugin notification = + FlutterLocalNotificationsPlugin(); + + Timer.periodic(const Duration(minutes: 1), (timer) async { + try { + ServicesController.statusBackgroundService = true; + sessionRes = await dbSession.sessions(); + String accountAddress = sessionRes[0].account; + res = await db.campaigns(); + if (res.isNotEmpty) { + for (Campaign c in res) { + String address = c.address; + String title = c.title; + + SmartContractModelBs smartContract = SmartContractModelBs( + contractAddress: address, + abiName: 'Campaign', + abiFileRoot: 'assets/abi_campaign.json', + accountAddress: accountAddress); + + List? isClosedRaw = + await smartContract.queryCall('isClosed', []); + + if (isClosedRaw != null) { + String answer = isClosedRaw[0].toString(); + + if (answer == "true") { + // the campaign result closed + if (kDebugMode) { + print('\x1B[31mThe campaign was closed\x1B[0m'); + } + + notification.show( + 999, + 'Campaign Closed', + 'The campaign [$title] \nat address $address \n was closed by crowdsourcer', + NotificationDetails( + android: AndroidNotificationDetails( + NotificationChannel.backgroundServiceChannel.id, + NotificationChannel.backgroundServiceChannel.name, + icon: 'ic_bg_service_small', + styleInformation: BigTextStyleInformation( + "

The campaign \"$title\" \n campaign at address: \n$address \n was closed by the crowdsoucer

", + htmlFormatBigText: true, + contentTitle: "

CLOSED \"$title\"

", + htmlFormatContentTitle: true, + summaryText: "

this campaign is now closed

", + htmlFormatSummaryText: true, + htmlFormatContent: true, + htmlFormatTitle: true), + ongoing: true, + ), + ), + ); + + await db.deleteCampaign(address); + } else { + if (kDebugMode) { + print( + '\x1B[31m [CLOSED CAMPAIGN SERVICE] The campaign still open: nothing to notify. \x1B[0m'); + } + } + } else { + if (kDebugMode) { + print( + '\x1B[31m [CLOSED CAMPAIGN SERVICE]an error occurred. \x1B[0m'); + } + } + } + + //..... + for (var element in geoList) { + element.stopGeofenceService(); + } + geoList.clear(); + for (Campaign c in res) { + Geofence g = Geofence(c.title, c.address, c.lat, c.lng, c.radius); + geoList.add(g); + g.initialize(); + } + if (kDebugMode) { + print( + '\x1B[31m [GEOFENCE SERVICE] active geofences: ${geoList.length}. \x1B[0m'); + } + } else { + ServicesController.statusBackgroundService = false; + timer.cancel(); + for (var element in geoList) { + element.stopGeofenceService(); + } + geoList.clear(); + service.stopSelf(); + if (kDebugMode) { + print( + '\x1B[31m [CLOSED SERVICE] No campaigns to follow. stop the service.\x1B[0m'); + } + } + } catch (e) { + ServicesController.statusBackgroundService = false; + timer.cancel(); + for (var element in geoList) { + element.stopGeofenceService(); + } + geoList.clear(); + service.stopSelf(); + + if (kDebugMode) { + print('\x1B[31m [CLOSED SERVICE] ERROR: \n ${e.toString()}.\x1B[0m'); + } + } + }); + } +} + +class SmartContractModelBs { + SmartContractModelBs( + {required this.accountAddress, + required this.contractAddress, + required this.abiName, + required this.abiFileRoot}); + + final String accountAddress; + final String contractAddress; + final String abiName; + final String abiFileRoot; + late http.Client httpClient; + late Web3Client ethClient; + + Future loadContract(String contractAddress) async { + String abi = await rootBundle.loadString(abiFileRoot); + final contract = DeployedContract(ContractAbi.fromJson(abi, abiName), + EthereumAddress.fromHex(contractAddress)); + return contract; + } + + Future?> queryCall( + String functionName, List args) async { + try { + httpClient = http.Client(); + ethClient = Web3Client( + "https://goerli.infura.io/v3/5074605772bb4bc4b6970d2ce999efca", + httpClient); + + final contract = await loadContract(contractAddress); + final ethFunction = contract.function(functionName); + final result = await ethClient.call( + sender: EthereumAddress.fromHex(accountAddress), + contract: contract, + function: ethFunction, + params: args); + List res = result; + return res; + } catch (e) { + if (kDebugMode) { + print('\x1B[31m$e\x1B[0m'); + } + return null; + } + } +} diff --git a/lib/services/servicesV2.dart b/lib/services/servicesV2.dart deleted file mode 100644 index 6fe2fa6..0000000 --- a/lib/services/servicesV2.dart +++ /dev/null @@ -1,182 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_background_service/flutter_background_service.dart'; -import 'package:flutter_local_notifications/flutter_local_notifications.dart'; -import 'package:http/http.dart' as http; -import 'package:mobile_crowd_sensing/models/db_session_model.dart'; -import 'package:mobile_crowd_sensing/services/notification_channels.dart'; -import 'package:mobile_crowd_sensing/services/services_controllerV2.dart'; -import 'package:web3dart/web3dart.dart'; -import '../models/db_capaign_model.dart'; -import 'dart:async'; -import 'dart:ui'; -import 'package:flutter_background_service_android/flutter_background_service_android.dart'; -import '../models/geofence_model.dart'; - -class ServicesV2 { - static void onStart(ServiceInstance service) async { - DartPluginRegistrant.ensureInitialized(); - - - if (service is AndroidServiceInstance) { - service.on('setAsForeground').listen((event) { - service.setAsForegroundService(); - }); - - service.on('setAsBackground').listen((event) { - service.setAsBackgroundService(); - }); - } - - service.on('stopService').listen((event) { - service.stopSelf(); - }); - - DbCampaignModel db = DbCampaignModel(); - DbSessionModel dbSession = DbSessionModel(); - List res = []; - List sessionRes = []; - List geoList = []; - - final FlutterLocalNotificationsPlugin notification = - FlutterLocalNotificationsPlugin(); - - Timer.periodic(const Duration(minutes: 1), (timer) async { - ServicesControllerV2.statusCloseCampaignService = true; - sessionRes = await dbSession.sessions(); - String accountAddress = sessionRes[0].account; - res = await db.campaigns(); - if (res.isNotEmpty) { - for (Campaign c in res) { - String address = c.address; - String title = c.title; - - SmartContractModelBs smartContract = SmartContractModelBs( - contractAddress: address, - abiName: 'Campaign', - abiFileRoot: 'assets/abi_campaign.json', - accountAddress: accountAddress); - - List? isClosedRaw = - await smartContract.queryCall('isClosed', []); - - if (isClosedRaw != null) { - String answer = isClosedRaw[0].toString(); - - if (answer == "true") { - // the campaign result closed - if (kDebugMode) { - print('\x1B[31mThe campaign was closed\x1B[0m'); - } - - notification.show( - 999, - 'Campaign Closed', - 'The campaign [$title] \nat address $address \n was closed by crowdsourcer', - NotificationDetails( - android: AndroidNotificationDetails( - NotificationChannel.backgroundServiceChannel.id, - NotificationChannel.backgroundServiceChannel.name, - icon: 'ic_bg_service_small', - styleInformation: BigTextStyleInformation( - "

The campaign \"$title\" \n campaign at address: \n$address \n was closed by the crowdsoucer

", - htmlFormatBigText: true, - contentTitle: "

CLOSED \"$title\"

", - htmlFormatContentTitle: true, - summaryText: "

this campaign is now closed

", - htmlFormatSummaryText: true, - htmlFormatContent: true, - htmlFormatTitle: true), - ongoing: true, - ), - ), - ); - - await db.deleteCampaign(address); - } else { - if (kDebugMode) { - print( - '\x1B[31m [CLOSED CAMPAIGN SERVICE] The campaign still open: nothing to notify. \x1B[0m'); - } - } - } else { - if (kDebugMode) { - print( - '\x1B[31m [CLOSED CAMPAIGN SERVICE]an error occurred. \x1B[0m'); - } - } - } - - //..... - for (var element in geoList) {element.stopGeofenceService();} - geoList.clear(); - for (Campaign c in res) { - Geofence g = Geofence(c.title, c.address, c.lat, c.lng, c.radius); - geoList.add(g); - g.initialize(); - } - if (kDebugMode) { - print('\x1B[31m [GEOFENCE SERVICE] active geofences: ${geoList.length}. \x1B[0m'); - } - } else { - ServicesControllerV2.statusCloseCampaignService = false; - timer.cancel(); - for (var element in geoList) {element.stopGeofenceService();} - geoList.clear(); - service.stopSelf(); - if (kDebugMode) { - print( - '\x1B[31m [CLOSED CAMPAIGN SERVICE] No campaigns to follow. stop the service.\x1B[0m'); - } - } - }); - } - -} - -class SmartContractModelBs { - SmartContractModelBs( - {required this.accountAddress, - required this.contractAddress, - required this.abiName, - required this.abiFileRoot}); - - final String accountAddress; - final String contractAddress; - final String abiName; - final String abiFileRoot; - late http.Client httpClient; - late Web3Client ethClient; - - Future loadContract(String contractAddress) async { - String abi = await rootBundle.loadString(abiFileRoot); - final contract = DeployedContract(ContractAbi.fromJson(abi, abiName), - EthereumAddress.fromHex(contractAddress)); - return contract; - } - - Future?> queryCall( - String functionName, List args) async { - try { - httpClient = http.Client(); - ethClient = Web3Client( - "https://goerli.infura.io/v3/5074605772bb4bc4b6970d2ce999efca", - httpClient); - - final contract = await loadContract(contractAddress); - final ethFunction = contract.function(functionName); - final result = await ethClient.call( - sender: EthereumAddress.fromHex(accountAddress), - contract: contract, - function: ethFunction, - params: args); - List res = result; - return res; - } catch (e) { - if (kDebugMode) { - print('\x1B[31m$e\x1B[0m'); - } - return null; - } - } -} diff --git a/lib/services/services_controllerV2.dart b/lib/services/services_controller.dart similarity index 71% rename from lib/services/services_controllerV2.dart rename to lib/services/services_controller.dart index 523da41..874e11f 100644 --- a/lib/services/services_controllerV2.dart +++ b/lib/services/services_controller.dart @@ -1,13 +1,12 @@ import 'package:flutter_background_service/flutter_background_service.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; -import 'package:mobile_crowd_sensing/services/servicesV2.dart'; +import 'package:mobile_crowd_sensing/services/services.dart'; import 'notification_channels.dart'; -class ServicesControllerV2 { - static bool statusCloseCampaignService = false; - static bool statusGeofencingService = false; +class ServicesController { + static bool statusBackgroundService = false; - static void initializeCloseCampaignService() async { + static void initializeBackgroundService() async { FlutterBackgroundService s = FlutterBackgroundService(); final FlutterLocalNotificationsPlugin notification = @@ -19,7 +18,7 @@ class ServicesControllerV2 { s.configure( androidConfiguration: AndroidConfiguration( - onStart: ServicesV2.onStart, + onStart: Services.onStart, autoStart: true, isForegroundMode: true, @@ -30,15 +29,15 @@ class ServicesControllerV2 { ), iosConfiguration: IosConfiguration( autoStart: true, - onForeground: ServicesV2.onStart, + onForeground: Services.onStart, ), ); s.startService(); - statusCloseCampaignService = true; + statusBackgroundService = true; } static void resetService() async { - statusCloseCampaignService = true; - initializeCloseCampaignService(); + statusBackgroundService = true; + initializeBackgroundService(); } } diff --git a/lib/views/error_view.dart b/lib/views/error_view.dart new file mode 100644 index 0000000..21a8a0c --- /dev/null +++ b/lib/views/error_view.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:mobile_crowd_sensing/utils/styles.dart'; + +class CustomError extends StatelessWidget { + final FlutterErrorDetails errorDetails; + const CustomError({ + Key? key, + required this.errorDetails, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Card( + color: Colors.red, + margin: EdgeInsets.zero, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column(children: [ + Text( + "Session Killed From Wallet!", + style: CustomTextStyle.spaceMonoBold(context), + ), + TextButton.icon( + onPressed: () { + Navigator.of(context).pushNamedAndRemoveUntil( + '/login', (Route route) => false); + }, + icon: const Icon(Icons.signal_wifi_connected_no_internet_4_outlined), + label: Text( + "Back to Login.", + style: CustomTextStyle.spaceMono(context), + ), + + ), + + ]), + )); + } +} From 13fd9232604a253feca80430ea6349d9443d71ef Mon Sep 17 00:00:00 2001 From: Giacomo Date: Sun, 12 Feb 2023 12:53:24 +0100 Subject: [PATCH 24/34] fixed reward removed IOS fixed reward --- assets/abi_campaign.json | 13 + contracts/Campaign.sol | 51 +- ios/.gitignore | 34 -- ios/Flutter/AppFrameworkInfo.plist | 26 - ios/Flutter/Debug.xcconfig | 1 - ios/Flutter/Release.xcconfig | 1 - ios/Runner.xcodeproj/project.pbxproj | 481 ------------------ .../contents.xcworkspacedata | 7 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../xcshareddata/WorkspaceSettings.xcsettings | 8 - .../xcshareddata/xcschemes/Runner.xcscheme | 87 ---- .../contents.xcworkspacedata | 7 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../xcshareddata/WorkspaceSettings.xcsettings | 8 - ios/Runner/AppDelegate.swift | 13 - .../AppIcon.appiconset/Contents.json | 1 - .../AppIcon.appiconset/_/100.png | Bin 5249 -> 0 bytes .../AppIcon.appiconset/_/102.png | Bin 5290 -> 0 bytes .../AppIcon.appiconset/_/1024.png | Bin 116639 -> 0 bytes .../AppIcon.appiconset/_/114.png | Bin 5858 -> 0 bytes .../AppIcon.appiconset/_/120.png | Bin 6306 -> 0 bytes .../AppIcon.appiconset/_/128.png | Bin 4757 -> 0 bytes .../AppIcon.appiconset/_/144.png | Bin 6815 -> 0 bytes .../AppIcon.appiconset/_/152.png | Bin 8150 -> 0 bytes .../AppIcon.appiconset/_/16.png | Bin 742 -> 0 bytes .../AppIcon.appiconset/_/167.png | Bin 8938 -> 0 bytes .../AppIcon.appiconset/_/172.png | Bin 9259 -> 0 bytes .../AppIcon.appiconset/_/180.png | Bin 9621 -> 0 bytes .../AppIcon.appiconset/_/196.png | Bin 10939 -> 0 bytes .../AppIcon.appiconset/_/20.png | Bin 968 -> 0 bytes .../AppIcon.appiconset/_/216.png | Bin 12322 -> 0 bytes .../AppIcon.appiconset/_/256.png | Bin 13672 -> 0 bytes .../AppIcon.appiconset/_/29.png | Bin 1477 -> 0 bytes .../AppIcon.appiconset/_/32.png | Bin 1346 -> 0 bytes .../AppIcon.appiconset/_/40.png | Bin 2178 -> 0 bytes .../AppIcon.appiconset/_/48.png | Bin 2252 -> 0 bytes .../AppIcon.appiconset/_/50.png | Bin 2588 -> 0 bytes .../AppIcon.appiconset/_/512.png | Bin 25340 -> 0 bytes .../AppIcon.appiconset/_/55.png | Bin 2910 -> 0 bytes .../AppIcon.appiconset/_/57.png | Bin 2960 -> 0 bytes .../AppIcon.appiconset/_/58.png | Bin 2992 -> 0 bytes .../AppIcon.appiconset/_/60.png | Bin 3217 -> 0 bytes .../AppIcon.appiconset/_/64.png | Bin 2336 -> 0 bytes .../AppIcon.appiconset/_/66.png | Bin 3465 -> 0 bytes .../AppIcon.appiconset/_/72.png | Bin 3835 -> 0 bytes .../AppIcon.appiconset/_/76.png | Bin 3926 -> 0 bytes .../AppIcon.appiconset/_/80.png | Bin 3708 -> 0 bytes .../AppIcon.appiconset/_/87.png | Bin 4524 -> 0 bytes .../AppIcon.appiconset/_/88.png | Bin 4662 -> 0 bytes .../AppIcon.appiconset/_/92.png | Bin 4782 -> 0 bytes ios/Runner/Base.lproj/LaunchScreen.storyboard | 44 -- ios/Runner/Base.lproj/Main.storyboard | 26 - ios/Runner/Info.plist | 55 -- ios/Runner/Runner-Bridging-Header.h | 1 - .../sourcer_campaign_controller.dart | 4 +- lib/models/sourcer_campaign_model.dart | 12 +- lib/views/light_join_campaign_view.dart | 148 +++--- 57 files changed, 135 insertions(+), 909 deletions(-) delete mode 100644 ios/.gitignore delete mode 100644 ios/Flutter/AppFrameworkInfo.plist delete mode 100644 ios/Flutter/Debug.xcconfig delete mode 100644 ios/Flutter/Release.xcconfig delete mode 100644 ios/Runner.xcodeproj/project.pbxproj delete mode 100644 ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings delete mode 100644 ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme delete mode 100644 ios/Runner.xcworkspace/contents.xcworkspacedata delete mode 100644 ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings delete mode 100644 ios/Runner/AppDelegate.swift delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/100.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/102.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/1024.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/114.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/120.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/128.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/144.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/152.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/16.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/167.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/172.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/180.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/196.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/20.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/216.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/256.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/29.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/32.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/40.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/48.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/50.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/512.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/55.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/57.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/58.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/60.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/64.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/66.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/72.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/76.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/80.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/87.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/88.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/_/92.png delete mode 100644 ios/Runner/Base.lproj/LaunchScreen.storyboard delete mode 100644 ios/Runner/Base.lproj/Main.storyboard delete mode 100644 ios/Runner/Info.plist delete mode 100644 ios/Runner/Runner-Bridging-Header.h diff --git a/assets/abi_campaign.json b/assets/abi_campaign.json index 3430caf..b4fb411 100644 --- a/assets/abi_campaign.json +++ b/assets/abi_campaign.json @@ -426,6 +426,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "validFiles", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/contracts/Campaign.sol b/contracts/Campaign.sol index 28736ae..a56fc9b 100644 --- a/contracts/Campaign.sol +++ b/contracts/Campaign.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.17; import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "./MCSfactory.sol"; -import "@openzeppelin/contracts/security/PullPayment.sol" + contract Campaign is Ownable, Initializable { string internal name; @@ -42,11 +42,10 @@ contract Campaign is Ownable, Initializable { } function withdrawCredits() public { - uint amount = credits[msg.sender]; - require(amount != 0); - require(factoryContractAddress.balanceOf(address(this)) >= amount); - credits[msg.sender] = 0; - factoryContractAddress.transfer(msg.sender,amount); + require(credits[msg.sender] > 0, "empty balance to withdraw"); + require(factoryContractAddress.balanceOf(address(this)) >= credits[msg.sender], "can't withdraw more than campaign balance"); + delete credits[msg.sender]; + factoryContractAddress.transfer(msg.sender,credits[msg.sender]); factoryContractAddress.removeCampaignToClaim(msg.sender,address(this)); } @@ -130,27 +129,35 @@ contract Campaign is Ownable, Initializable { isClosed = factoryContractAddress.closeCampaign(); uint256 balance = getCampaignBalance(); uint256 verifiesTotalReward = (balance * 50 / 100); - uint256 workerReward = (balance - verifiesTotalReward) / validFiles; - uint256 verifierReward = verifiesTotalReward / numberOfActiveVerifiers; - uint256 refound = balance - (workerReward + verifierReward); - if(refound > 0) { + if(validFiles == 0) { // caso in cui non ci siano dati validi + uint256 refound = balance - verifiesTotalReward; + uint256 verifierReward = verifiesTotalReward / numberOfActiveVerifiers; factoryContractAddress.putCampaignToClaim(addressCrowdSourcer,address(this), "refound", refound); - } - - for(uint i; i - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - App - CFBundleIdentifier - io.flutter.flutter.app - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - App - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - MinimumOSVersion - 9.0 - - diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig deleted file mode 100644 index 592ceee..0000000 --- a/ios/Flutter/Debug.xcconfig +++ /dev/null @@ -1 +0,0 @@ -#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig deleted file mode 100644 index 592ceee..0000000 --- a/ios/Flutter/Release.xcconfig +++ /dev/null @@ -1 +0,0 @@ -#include "Generated.xcconfig" diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index 75f77d3..0000000 --- a/ios/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,481 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 50; - objects = { - -/* Begin PBXBuildFile section */ - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; - 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 97C146EB1CF9000F007C117D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 9740EEB11CF90186004384FC /* Flutter */ = { - isa = PBXGroup; - children = ( - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 9740EEB31CF90195004384FC /* Generated.xcconfig */, - ); - name = Flutter; - sourceTree = ""; - }; - 97C146E51CF9000F007C117D = { - isa = PBXGroup; - children = ( - 9740EEB11CF90186004384FC /* Flutter */, - 97C146F01CF9000F007C117D /* Runner */, - 97C146EF1CF9000F007C117D /* Products */, - ); - sourceTree = ""; - }; - 97C146EF1CF9000F007C117D /* Products */ = { - isa = PBXGroup; - children = ( - 97C146EE1CF9000F007C117D /* Runner.app */, - ); - name = Products; - sourceTree = ""; - }; - 97C146F01CF9000F007C117D /* Runner */ = { - isa = PBXGroup; - children = ( - 97C146FA1CF9000F007C117D /* Main.storyboard */, - 97C146FD1CF9000F007C117D /* Assets.xcassets */, - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, - ); - path = Runner; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 97C146ED1CF9000F007C117D /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 9740EEB61CF901F6004384FC /* Run Script */, - 97C146EA1CF9000F007C117D /* Sources */, - 97C146EB1CF9000F007C117D /* Frameworks */, - 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, - 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Runner; - productName = Runner; - productReference = 97C146EE1CF9000F007C117D /* Runner.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 97C146E61CF9000F007C117D /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1300; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 97C146ED1CF9000F007C117D = { - CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 1100; - }; - }; - }; - buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 97C146E51CF9000F007C117D; - productRefGroup = 97C146EF1CF9000F007C117D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 97C146ED1CF9000F007C117D /* Runner */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 97C146EC1CF9000F007C117D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; - }; - 9740EEB61CF901F6004384FC /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 97C146EA1CF9000F007C117D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 97C146FA1CF9000F007C117D /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C146FB1CF9000F007C117D /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C147001CF9000F007C117D /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 249021D3217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Profile; - }; - 249021D4217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.mobileCrowdSensing; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Profile; - }; - 97C147031CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 97C147041CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 97C147061CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.mobileCrowdSensing; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; - 97C147071CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.mobileCrowdSensing; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147031CF9000F007C117D /* Debug */, - 97C147041CF9000F007C117D /* Release */, - 249021D3217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147061CF9000F007C117D /* Debug */, - 97C147071CF9000F007C117D /* Release */, - 249021D4217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 97C146E61CF9000F007C117D /* Project object */; -} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a..0000000 --- a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c..0000000 --- a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index c87d15a..0000000 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 1d526a1..0000000 --- a/ios/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c..0000000 --- a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift deleted file mode 100644 index 70693e4..0000000 --- a/ios/Runner/AppDelegate.swift +++ /dev/null @@ -1,13 +0,0 @@ -import UIKit -import Flutter - -@UIApplicationMain -@objc class AppDelegate: FlutterAppDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - GeneratedPluginRegistrant.register(with: self) - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } -} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index ffab254..0000000 --- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1 +0,0 @@ -{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"idiom":"watch","filename":"172.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"38mm","scale":"2x","size":"86x86","expected-size":"172","role":"quickLook"},{"idiom":"watch","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"38mm","scale":"2x","size":"40x40","expected-size":"80","role":"appLauncher"},{"idiom":"watch","filename":"88.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"40mm","scale":"2x","size":"44x44","expected-size":"88","role":"appLauncher"},{"idiom":"watch","filename":"102.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"41mm","scale":"2x","size":"45x45","expected-size":"102","role":"appLauncher"},{"idiom":"watch","filename":"92.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"41mm","scale":"2x","size":"46x46","expected-size":"92","role":"appLauncher"},{"idiom":"watch","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"44mm","scale":"2x","size":"50x50","expected-size":"100","role":"appLauncher"},{"idiom":"watch","filename":"196.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"42mm","scale":"2x","size":"98x98","expected-size":"196","role":"quickLook"},{"idiom":"watch","filename":"216.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"44mm","scale":"2x","size":"108x108","expected-size":"216","role":"quickLook"},{"idiom":"watch","filename":"48.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"38mm","scale":"2x","size":"24x24","expected-size":"48","role":"notificationCenter"},{"idiom":"watch","filename":"55.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"42mm","scale":"2x","size":"27.5x27.5","expected-size":"55","role":"notificationCenter"},{"idiom":"watch","filename":"66.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"45mm","scale":"2x","size":"33x33","expected-size":"66","role":"notificationCenter"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"watch","role":"companionSettings","scale":"3x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"watch","role":"companionSettings","scale":"2x"},{"size":"1024x1024","expected-size":"1024","filename":"1024.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"watch-marketing","scale":"1x"},{"size":"128x128","expected-size":"128","filename":"128.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"256x256","expected-size":"256","filename":"256.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"128x128","expected-size":"256","filename":"256.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"256x256","expected-size":"512","filename":"512.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"32","filename":"32.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"512x512","expected-size":"512","filename":"512.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"16","filename":"16.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"32","filename":"32.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"64","filename":"64.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"512x512","expected-size":"1024","filename":"1024.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"}]} \ No newline at end of file diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/100.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/100.png deleted file mode 100644 index 30294f4bc94754414f2de39bbcf7a81a5ecdca47..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5249 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 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/1024.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/1024.png deleted file mode 100644 index bf676a51586a267fbb068321be1818127906ddb7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 116639 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 y8oJJ` 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 F{vSn(6srIL diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/114.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/114.png deleted file mode 100644 index 72e4267b30ef757d6a404ddfdead61068eade643..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5858 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 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/120.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/120.png deleted file mode 100644 index bc5a0e186771cdb85331513f86f71b322651407e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6306 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 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/152.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/152.png deleted file mode 100644 index 3c77f086b49b72ccdc29079e8d22a49a2f18c67e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8150 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 YKVv2`(V72~pa1{>07*qoM6N<$g0zTE82|tP diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/167.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/167.png deleted file mode 100644 index 130775174f47448dc6ecfd525bcdea472fe2bf8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8938 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 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/172.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/172.png deleted file mode 100644 index 5ba8f97d92d3fc3879cd8861e8fda6447915880b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9259 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 N002ovPDHLkV1lnrugd@c diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/180.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/180.png deleted file mode 100644 index 69a1737493981a99f758eba47625ce60a32d7efd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9621 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 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/20.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/20.png deleted file mode 100644 index e0b94abd80ef6381d887f7751bc1b312aeb9b1db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 968 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 B 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 bLq4G#`5|zU>X7cwi!snV;o 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

w<^)Yj~bb31eOIdEL2?mo!RghMCq< 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ℑ8GFqhR zCgt-n0G6NmWZYZQ?8X9jEBhyZGuFeA9Us!p+&76I?YGfADQchZYN*A<{EK;hNe9gK z$2-##*k)=n%{4(fn~>!p$gNlCy$9rGf&pM~`Nkr4S<$oPjbe*QB5*!g&VR%EE<9T{ zy7Zbuax5=4-WuYeuT1*CrKSA-_`ae7hDZY5e;7{q7BqAhI0_`**OVJY+u;bo#u{S* zy7_+T@17q0bt(M{+iqWNIG!2&`s>3{ZBZrjB(9h~tTh*az>@A9ew=%33gM~-FLjb) zeg1JWc?8!tID|N#wfm4DU*B}NS|iDdwUZ356Fp6DMl~d*Gw)md-z>m?(gU;>2J|9e z9mhrWRTIAR#Z&!y>| za|QCsF3IO+N3{dy6OJ#QG{C3~AqXs`im&_JC`nxWL@$raGMq&ZqZf@YD_cq?!?QOp zn*9lsA`2Q%rOc#OtZM;*vLYksHA~3vgxO z2yu3&Cc;dYMqU#6Bwb02^0rzeAUw>xx4iE7RX~5Zf84CSOW5bJzPjsg(Kvpo&1d7o z!gK_zFe?JE!;gNQ`Ky)%Fdfvw8uDRJHjP-MnwTa0!7D4p;xOHWy}p&=Sc|ECOs@&- zlHk}F%b!xIB<`aRei50qAuZA0T^ZbqMiL?(7{UplH{X{>CE?;kKfA-i+}|LFX>hq5 z*YC%+)O{eXPIC?#>7IpRM;y*%k;sP^2vL@E{nObEk3Q{>!A6+OHe_w?jS(WAXJ(4} zItCD@Oj(KRgsEV}V^XDY5OUG$q;-i4U3I)#07amw8s`Rtr1|5Kjtr8s7Y|93XpldF z{%qFcr~?J27)TQ9h@2DfTl``pU7tR9kW5PqOz$U#5u(o~rl73aSjzC_FyM^_QZ-Yp zg{58T3dHJY``l6lH;+X-r&sXU_ zuEaz?iAfPU*9kbD!msCtpqz=IqTKlUn;FtlHe^T}XE?z|o7nQy>kk9B)Nea#S8>pc z7y6myUs%OBG(jwk?3ZDRq*Nm?2Z4pA8M?>dmuu$gHqr3AxyYb9d->qH=4Sn@StkEs z$Fz2*W+0uvSztnb=dlV9Kl=1l$R0FF#O~~-FZb3W>y2&Y3wkZ$8mYz(yN7AYZm*e zu_EO)LuN%|5RL!RC<@EjR(Yl$m{R!^H8`pQDOA8riAMDBFE((DBBm^iR`StcA>qYb zn!-NAPkf}xLYNXRDN*kU4|O2LI1AqPdT-3VJeV?Rd*y9T3RFH8!`&T@-c_kW;PIGJ zo;YzYTb{|}U#JyZ<6_Q|hPP)Px)e@R3^R7gv$msyMyRTPH5TU}k%GYqqVfI$J-WHdpRs3V9*RuxeLkp~|LiCaR% zkccKGMxusbM2T_m0WrqGfN=q%Kmx%rA<8ByqbO^bL_otL>-6+=Raf;j=XO`m+C49x zx9Pg~{^$PZKmWO-rf+Q1!OaY!;x^`#d(E2}WtmT+!cw2Zr0`_wHdzq+xJ5EUa_LYR%$p?VM@FP%U*X2sWx| zCJTegVdecUV+X{{_uYR5ys^hOBC@*Gw0pUtB$K}8xe0NW-s!UbkjID30ksKb66yjf zf7=$cdP0R};$Vw(plQCKsd76+5gptszxmrIJ#B>8Fekz0V;NTM^Qm#AC%SlQ|62aSk2tj zro{}#)+pA@bg51VksWd3QpmFJJW>JJo%*%&8cAAcojWRKXqEOGP^M`0wb94EvjHpj z`Xp>+YO7{!Y}0Et*IZ*$B! zviJCw! zV;j{<+cX{yx@_rqt^obwa51G>UhgvhR-2chl|6FtyQ=&ICfc^ z7Lqdx=FsI~M$QOcnc}iwoXygmX?{HyQW4d(2*1%wL+G6}Sn>R1hf%ebd10JSW@$X^ zv-M<1xs&(a&Y)uGm(!YOC)hkQ(KWQLYt9sC?QMn%Z=y;+gt}VA2M;E2dU?IA+MDK^ zlOdJTdflI(UI@ebD?WK7fn_PaJmPaMReZt-WxG!YoNd)K%yPMVXl`hT*-Jz$TuxUtB=vR!Eooe%kXK^Zk=mT{EM&Ls?q9-iLb&e2P{ zCujlKhavso_JNkEMKM2;m&V?+p=qa$kCjoK$k(lt>I|rcB|Fpnb|LH?Gy)bX(xEQ; zel_a=*H%q2mi{UR fQ_8iXe^LGe7fPGrSPx({7FPXR9Hu~SKn_GRTw>Yes6bMTa8#W7^6N?idE6X=mU+$8YuXp5kw?y3Pz)e zKmH2A2cm`=8q`vVz6esOKFEtc018;zH={8UrIEyL+1>8^zUI4kXPMdV%x+QVX?N%D z+;h+OopZino2M!qu}fh9=YY=vjRA}SVPZvm^}qkj;s9v#We?C5j!uK2xy?KU( z3di3z1eoYPfz50`DnTgwr^{sc>{&~!f9`~hVwFQzoq)nw<>B# zvi$CMAD_(oLM8O)R`R3!odytahFdI#!$X!h+Q?}K*BuU(agY6{1J zK?{9r)D`lc`^(3h-?~DA!YNY>fbNxDV9R|9-hR}C9Y_}F57%7|O9kFN>)@+jLKFYf0*p za}Ew&@{!Y7ok^(zaD2Kohu(s;u6T_i*<3A!*gahZ&+Y(8D}bWI@#=tvJ^iNm?Z~Wy z4=(!R0Es4iVzR<}EMRhL4u#syc#}nDQ*t<7I#or{mL`?u#Dc(@xxKYX7XS{N_t0a> zlQ#jtaD1C3s7bq)J&qkGZDFsi07TCq+DVSoJ9$G&u(5oM80fYb#-BEkHzYmH7%00O z`@VLt)Fyz)S4df12C(FCxFJh~nkbj-0YWIXUe{;sOC&o2MuyT(#74>b@LGnw8x7nM zOV%G6lC^F`f|}UzDFx|@Cu55MlnvNsvJx|NxP%iD1ymVCe311t>7s={yjBZFz z*2A;DXh=GAVj^0NeA1frrU7Idh>Js)yo7nfAA zUV?atkbh4+Lm>i;&e%eFjUkc+U{%Q)pNh$LDHXeO44-e$2~j-%MOCms=A$%*c>@X| zqE#mAiYBCP@6dpw!xr*}f*mK8ait`G%bac*Kn+N1RE6WcK@)vzw3K9Z5QI!*P69v_ zMC5w=H=B5DorW{NdHC>x2T#~l`bASP%?uQ~uRo~c#lDPWop*8YN13cm0oXopZ#VG% zQx-Z+nUEEaLt!^!G=dU&SJ4hJHe-u*Q^VQGx=;>9uu-zE01&Z2Z%Fs|0DCs*Vo1r= zhlC^xaR4KyZP6>ohHJ@6MiV10T3dEFcActX(QZ7RD6Cq&i1>jVwQkEX zOl`B!k&&!4u)J{67LMDLfj9{IOao>s8;)LTyC_+QOcZG9Nl8{J)7Xq7qCFEpJsC6G z@5aq&!^UK7{ChlE+XB$${`F-vfJ9&t(@!jL)!K{eKSo{sk`V-!82|tP07*qoM6N<$ Eg49)Pr2qf` diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/40.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/40.png deleted file mode 100644 index fc6830226cd6593574665b437f333f59ed625024..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2178 zcmV-|2z~d7P)Px-JV``BR9HvFS$%9))fxYt`~9}%qaT8Z1Hsv{s^W1ye z_p`limhAlVzP;}~=lss|@q2#Hsc70YBvE820uUnnK}sMf`c|=-|J!Gx7(fD-@c`Qo zQE7@mx&HqFSpbl%Ht0yyRthY*LWQXUN6rR#=hFa|CZLc-^NbW3I+5wd>xdkHWH|zN zZ=H(ujV26rWb3~ibMWLr7dpL^HE6>iNQ4a#08Q6K=#3;`hXK;Wv=@2K2mKPi8|YB`&!V0}j|5hB|iG3MTXozrQ)7$d8MnZ!^v-}CpyP~>-A6r~O#>-ybdWg! zFW3^BZ_}~-YGc?svT4+ZbUyI= zeIC}f*vt~8#xOv7g)F5CiD$oJqOMxYnKR@BSl5!lNBw}Qh1^JUE_r|((a~6DBv5_; zY*?t_o7b8=f8)M1_J1N#VHCGwP8QPwjt@*Vfwc`97F?lm9DeXwfE}F@ON4}zhV{e;D9Z0O{KuHIV$E>Do};MnZW>U zCw+9B3Ha2-$a*x;1kRI`RFYj>nG$&EYbpNR{;rFy?KY}X^p-${p39FpJV+${jd?28 z-Dtup;5La@x?Mco;X+lCgQRWU0GL(=e7#QRn58iJYOTgx*xBRbz$qUUreK!%+lM|s zrx>Tf0LkO8VRcyM=3b`+fq~p+__g+2b;PC@4CK)1;fZ*fbs@1?jtv|w7|!A1l3U#BP81D(A-zS}Y}fV4r(hnHMZLSdb! zxGyHZ7~qApMDu(DtLwEy7Ch1$;76@CQWH?wEbBZ1Bsn1{LC)Ku{Gy@|(@ShArWry` z%9&(T{-6c(Pv=X?QY)DX99fapBCE}-2G-o5qqa)rxNAS{ak=Yvz#1_d!_GKvLVko&{A!|nh zH(&!dO$Sa45Rr#gjL|n8%98*u~$fSMksSYnb;a?&IF4`Smoq z`eY6}8+3r$D)6BjXJ|0! zlmPlO0rnmD@S9E-7ahS(Sq!o$&BRT7bAyI8^G&2(iEqD}#<}c9dyEE&vMat7;~v@t zZk#T#rO85Bq}GSYIEuy(&-?hnUK{=PNcfbz-J;Vjx>8`vk`%l0k4J56ZTHy4`Sr3? zLJI2iTBs=t%Nwl|pOMy&d+&dK>|$f9!(qggtJM7wk&n*=<4 zr-{oe#(%x>!FeAK{FUmf#1o4RESepv=u&z!)}qgJWU%w7kExaz-GZ?+qJH?kYc({^ zP%+t55?vB;^*QC?v46Sj%56(c%)eY6v!x*LFCKC5%%QNNjOt=?18qdN4a9|$jPR9Bg!$v->g)~Be%j}%HEw`OTwCl= zpF diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/48.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/48.png deleted file mode 100644 index 8ac214b5605963fbf6280c534266e0ead9a70c51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2252 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 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/58.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/58.png deleted file mode 100644 index cd52ea0fee9b29fcbb3a50e495fe300e947cd596..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2992 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 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/80.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/80.png deleted file mode 100644 index 55149bdc5a61742e4dc5c401cf8785109565621a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3708 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 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/92.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/_/92.png deleted file mode 100644 index b4d354dba79154446b24be87534509c067dd13c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4782 zcmV;f5>f4mP)Px{Xh}ptRCr$PT?>#@)tUb8z1_DTGcb(9O9IL(AwE(VH6VmX5Ct@%!K!TS)+WZ? zwNhCV*^TZdph-}7BPMIm;OcJTn&2i|acg%Y(SRZ%K><-DVetV$UICQ1!!R@bxQ}zT z{&V`wbkB6py|?>z(;MbiB~=dhan5(Y`@jFcwX6T5lcWEr2?81btsn53VBPhQe!y#s zcjXKhp9%e6?%*8gmr-!IhKp?<{sg4>0;G;HeNbNtk)1Tw-wk+@`6M(y>B;hcC$X&?j-U5Tpi|D}iBNi6EWWzKx-xdr#vsMR@qgK|Hrwpfk zI~-_=GW`3E2@E8G+=JD90YjDwfwy#HCsyv&&}4dBF9bk`MIcmJ@C!>z6XY=sz|2X= zYU&$LzzM9=S&lDUtYP7#q%ie@uuqta0Ct|R@s%}Mn1)`G<#Zn1Kc;ic8>^!^8L2AC z8DnToIryMc!`@bgBPk8KrlBEPJ;r+iPO_UUk7cu?m^{)Haytm%3NhPd_|kJ}9PZEr zn~ITFz1-U`({bx%iK>EKcyo@n48xlr*jTyS#nxj$Jfb10hp*^80T&D73_rO(h6|gc zQc(t!uOt{qdf)kCCtf?MqcK{1BMR^bX2vjUbObKxih$1w^pE>!#st9M&?^tTQ= zY#s5Ctt(H!39P8b@zf153?C2?%*?k+{A^Hpq2F4c!n%XN0JCqv@0%XOb>kv|#h0J8 zlsZRQUGxr!PG$I{_~?g=;vVCFJBaa|1KTPkDt9WQiZ+i_jU$YP3#*xZ`s zcyMM6v&Te4$e^kW7p|JrG5KGuvaSxcTDbj13muMuh{kCPrzxzXR;g*%#2{x zm{?#Lt~Qji7{2&y8YivpUvVXxn7)mrI%1^T9gS^WKa z2Mwkcinr_w@HPv$el*9DnGJzuxUyd8Aib z;tbP98klw=1%9NTpwx!YAv&;RLnqc8&@j-4N$d4|Pr$owz!{#rK8Dc&6{iH8<8Rlb z@WwG|a(UUgwBfW1Fs~E6cIWx;inSawJ_3AedK^u0qf1XI-Lw0ojW0iMAsW#t4#fEa zT$qM7aOE(LAI_1VIw{Y-tQBGkF@!wLmAf){aEpt9G0k_#HmD`!iEW7!R6PG=8kl-M z!w;@W${0~D{49(FaQyZ2DeO3@A?brK70GaQv2gD#j?azLu;|lqXqqm-6AR9Jf^d^_ zaTNOVhCgJnNKb6B!pae1#2vKZ-K58F(U??7YBZRQyj^t6q~eedKs@Dw(#|JcE#38V89g{=q;06 zH^9*t@LbrI7=Bg&R~}i`1=0>BjJdE) z2bc^=GXmRj(P2|`QL;R0Xix#adI!Gl0H?Q1GOp9+7}>}%eWZ>_BMgjfHbjg&VH%)_ zAVn76Z)ezX+{K1N3~!&5!SjYleTkQzW@kR&PtDJXlstxSKjwUf*LlnWB!Hq0984pTiSynO@_#Vi>S^iiuH!q$yZngDWQ?_e7;^RN%>F3{U

8{ISMG&{ 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 IM6N<$f}qtlB>(^b diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index 7aa6dfb..0000000 --- a/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard deleted file mode 100644 index f3c2851..0000000 --- a/ios/Runner/Base.lproj/Main.storyboard +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist deleted file mode 100644 index 034f874..0000000 --- a/ios/Runner/Info.plist +++ /dev/null @@ -1,55 +0,0 @@ - - - - - NSLocationAlwaysUsageDescription - Needed to access location - NSLocationWhenInUseUsageDescription - Needed to access location - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Mobile Crowd Sensing - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - mobile_crowd_sensing - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - CADisableMinimumFrameDurationOnPhone - - UIStatusBarHidden - - - diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h deleted file mode 100644 index 308a2a5..0000000 --- a/ios/Runner/Runner-Bridging-Header.h +++ /dev/null @@ -1 +0,0 @@ -#import "GeneratedPluginRegistrant.h" diff --git a/lib/controllers/sourcer_campaign_controller.dart b/lib/controllers/sourcer_campaign_controller.dart index 84b003d..cc3c275 100644 --- a/lib/controllers/sourcer_campaign_controller.dart +++ b/lib/controllers/sourcer_campaign_controller.dart @@ -20,6 +20,7 @@ class _SourcerCampaignControllerState extends State { String fileCount = '0'; String fileChecked = '0'; String workersCount = '0'; + String validFiles = '0'; late String name = '', lat = '', lng = '', @@ -39,6 +40,7 @@ class _SourcerCampaignControllerState extends State { fileCount = jsonCounters['fileCount'].toString(); fileChecked = jsonCounters['fileChecked'].toString(); workersCount = jsonCounters['workersCount'].toString(); + validFiles = jsonCounters["validFiles"].toString(); }); } }); @@ -137,7 +139,7 @@ class _SourcerCampaignControllerState extends State { Flexible( flex: 5, child: Text( - "Sourcing Status:\nuploaded $fileCount files\nchecked $fileChecked of $fileCount\nwith the contribution of $workersCount workers", + "Sourcing Status:\nuploaded $fileCount files\nchecked $fileChecked of $fileCount \nvalid files: $validFiles \nwith the contribution of $workersCount workers", style: CustomTextStyle.spaceMono(context), )), const SizedBox( diff --git a/lib/models/sourcer_campaign_model.dart b/lib/models/sourcer_campaign_model.dart index 490fe8d..16b2260 100644 --- a/lib/models/sourcer_campaign_model.dart +++ b/lib/models/sourcer_campaign_model.dart @@ -5,7 +5,7 @@ class SourcerCampaignModel { static Future getCountersData(String contractAddress) async { - String? fileChecked,fileCount,workersCount; + String? fileChecked,fileCount,workersCount,validFiles; SessionModel sessionData = SessionModel(); late SmartContractModel smartContract; @@ -19,7 +19,8 @@ class SourcerCampaignModel { await smartContract.queryCall('checkedFiles', []); List? workersCountRaw = await smartContract.queryCall('numberOfActiveWorkers', []); - + List? validFilesRaw = + await smartContract.queryCall('validFiles', []); if (fileCheckedRaw != null) { fileChecked = fileCheckedRaw[0].toString(); } @@ -30,12 +31,17 @@ class SourcerCampaignModel { if (workersCountRaw != null) { workersCount = workersCountRaw[0].toString(); } + + if (validFilesRaw != null) { + validFiles = validFilesRaw[0].toString(); + } } return "{" "\"fileChecked\":\"$fileChecked\"," "\"fileCount\":\"$fileCount\"," - "\"workersCount\":\"$workersCount\"" + "\"workersCount\":\"$workersCount\"," + "\"validFiles\":\"$validFiles\"" "}"; } diff --git a/lib/views/light_join_campaign_view.dart b/lib/views/light_join_campaign_view.dart index 745aac7..68755ca 100644 --- a/lib/views/light_join_campaign_view.dart +++ b/lib/views/light_join_campaign_view.dart @@ -22,7 +22,7 @@ class LightJoinCampaignViewState extends State { EnvironmentSensors environmentSensors = EnvironmentSensors(); bool activeSensor = false; - bool activeUpload = false; + bool isUpload = true; double sum = 0; List lights = []; @@ -65,8 +65,8 @@ class LightJoinCampaignViewState extends State { const SizedBox(height: 20), Row( children: [ - Text( - 'Name: ', style: CustomTextStyle.merriweatherBold(context)), + Text('Name: ', + style: CustomTextStyle.merriweatherBold(context)), Text( '${campaignSelectedData['name']}', style: CustomTextStyle.inconsolata(context), @@ -77,8 +77,7 @@ class LightJoinCampaignViewState extends State { children: [ Text('Latitude: ', style: CustomTextStyle.merriweatherBold(context)), - Text( - '${campaignSelectedData['lat']}', + Text('${campaignSelectedData['lat']}', style: CustomTextStyle.inconsolata(context)), Text('Longitude: ', style: CustomTextStyle.merriweatherBold(context)), @@ -100,34 +99,41 @@ class LightJoinCampaignViewState extends State { ), ], ), - Center(child: TextButton( - style: ButtonStyle(backgroundColor: MaterialStateProperty.all(CustomColors.blue900(context))), - onPressed: () async { - bool lightAvailable = await environmentSensors - .getSensorAvailable(SensorType.Light); - if (lightAvailable) { - setState(() { - activeSensor = true; - }); - } else { - setState(() { - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (BuildContext context) => - const DialogView( - message: - "This device doesen't integrate the appropriate sensor"))); - }); - } - }, - child: Text('Take data',style: CustomTextStyle.spaceMonoWhite(context),))), + Center( + child: TextButton( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all( + CustomColors.blue900(context))), + onPressed: () async { + bool lightAvailable = await environmentSensors + .getSensorAvailable(SensorType.Light); + if (lightAvailable) { + setState(() { + activeSensor = true; + }); + } else { + setState(() { + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (BuildContext context) => + const DialogView( + message: + "This device doesen't integrate the appropriate sensor"))); + }); + } + }, + child: Text( + 'Take data', + style: CustomTextStyle.spaceMonoWhite(context), + ))), activeSensor ? StreamBuilder( stream: environmentSensors.light, builder: (context, snapshot) { if (!snapshot.hasData) { - return const Center(child:CircularProgressIndicator()); + return const Center( + child: CircularProgressIndicator()); } else { lights.add(snapshot.data!); sum += lights.last; @@ -136,9 +142,11 @@ class LightJoinCampaignViewState extends State { return Column(children: [ Row(children: [ Text('Average Ambient Light: ', - style: CustomTextStyle.merriweatherBold(context)), + style: CustomTextStyle.merriweatherBold( + context)), Text('$averageRelevation', - style: CustomTextStyle.inconsolata(context)) + style: CustomTextStyle.inconsolata( + context)) ]), Row(children: [ Text('Number of relevations: ', @@ -148,23 +156,27 @@ class LightJoinCampaignViewState extends State { style: CustomTextStyle.inconsolata( context)) ]), - (!activeUpload)? + (isUpload)? FloatingActionButton( onPressed: () async { + setState(() { + isUpload = false; + }); String? res = - await UploadIpfsModel.uploadLight( - lights, - averageRelevation, - campaignSelectedData[ - 'contractAddress']); - - if (res != null) { - if (res == 'Data uploaded') { - setState(() { + await UploadIpfsModel.uploadLight( + lights, + averageRelevation, + campaignSelectedData[ + 'contractAddress']); + setState(() { + activeSensor = false; + isUpload = true; + if (res != null) { + if (res == 'Data uploaded') { lights.clear(); averageRelevation = 0; sum = 0; - activeSensor = false; + if(!mounted) return; ScaffoldMessenger.of(context) .showSnackBar(SnackBar( content: Text( @@ -172,21 +184,29 @@ class LightJoinCampaignViewState extends State { style: CustomTextStyle .spaceMonoWhite(context), ))); - Navigator.of(context).pushNamedAndRemoveUntil( - '/home', (Route route) => false); - }); - } - setState(() { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar( - content: Text( - res, - style: CustomTextStyle - .spaceMonoWhite(context), - ))); - }); - } else { - setState(() { + Navigator.of(context) + .pushNamedAndRemoveUntil( + '/home', + (Route route) => + false); + } else { + lights.clear(); + averageRelevation = 0; + sum = 0; + if(!mounted) return; + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + res, + style: CustomTextStyle + .spaceMonoWhite(context), + ))); + } + } else { + lights.clear(); + averageRelevation = 0; + sum = 0; + if(!mounted) return; ScaffoldMessenger.of(context) .showSnackBar(SnackBar( content: Text( @@ -194,20 +214,14 @@ class LightJoinCampaignViewState extends State { style: CustomTextStyle .spaceMonoWhite(context), ))); - }); - } + } + }); }, - backgroundColor: CustomColors.blue900(context), + backgroundColor: + CustomColors.blue900(context), child: const Icon(Icons.file_upload_sharp)) - : Expanded(child: Column( - mainAxisSize: MainAxisSize.max, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: const [ - CircularProgressIndicator() - ], - ),), + : const Center(child: CircularProgressIndicator()) ]); } }) From d5ed421d30df1a053715cad981148ab0cf0f3dae Mon Sep 17 00:00:00 2001 From: Giacomo Date: Sun, 12 Feb 2023 15:29:48 +0100 Subject: [PATCH 25/34] conversion from wai to MCScoin visualization --- contracts/Campaign.sol | 3 +-- lib/controllers/campaign_list_controller.dart | 2 +- lib/controllers/claim_campaign_controller.dart | 2 +- lib/controllers/create_campaign_form_controller.dart | 4 ++-- lib/controllers/sourcer_campaign_controller.dart | 11 ++++++----- .../sourcer_closed_campaign_controller.dart | 9 ++++----- 6 files changed, 15 insertions(+), 16 deletions(-) diff --git a/contracts/Campaign.sol b/contracts/Campaign.sol index a56fc9b..9fa84af 100644 --- a/contracts/Campaign.sol +++ b/contracts/Campaign.sol @@ -42,11 +42,10 @@ contract Campaign is Ownable, Initializable { } function withdrawCredits() public { - require(credits[msg.sender] > 0, "empty balance to withdraw"); require(factoryContractAddress.balanceOf(address(this)) >= credits[msg.sender], "can't withdraw more than campaign balance"); - delete credits[msg.sender]; factoryContractAddress.transfer(msg.sender,credits[msg.sender]); factoryContractAddress.removeCampaignToClaim(msg.sender,address(this)); + delete credits[msg.sender]; } function getAllFilesInfo() public view returns(File[] memory){ diff --git a/lib/controllers/campaign_list_controller.dart b/lib/controllers/campaign_list_controller.dart index 388741b..f72be37 100644 --- a/lib/controllers/campaign_list_controller.dart +++ b/lib/controllers/campaign_list_controller.dart @@ -98,7 +98,7 @@ class _CampaignListControllerState contractAddress = current[7].toString(); readebleLocation = current[8]; isSubscribed = current[9]; - balance = "${current[10].toString()} wei"; + balance = "${(BigInt.parse(current[10].toString()).toDouble() /1000000000000000000)} MCScoin"; return GestureDetector( onTap: () { diff --git a/lib/controllers/claim_campaign_controller.dart b/lib/controllers/claim_campaign_controller.dart index e8cb827..82dfee5 100644 --- a/lib/controllers/claim_campaign_controller.dart +++ b/lib/controllers/claim_campaign_controller.dart @@ -177,7 +177,7 @@ class _ClaimCampaignControllerState extends State { style: CustomTextStyle.spaceMonoBold(context), ), Text( - reward, + "${BigInt.parse(reward).toDouble()/1000000000000000000} MCScoin", style: CustomTextStyle.spaceMono(context), ) ])), diff --git a/lib/controllers/create_campaign_form_controller.dart b/lib/controllers/create_campaign_form_controller.dart index 0a9449e..b1cacfd 100644 --- a/lib/controllers/create_campaign_form_controller.dart +++ b/lib/controllers/create_campaign_form_controller.dart @@ -134,9 +134,9 @@ class _CreateCampaignFormControllerState ), Slider( min: 0, - max: 1000000000, + max: 1000000000000000000, divisions: 100, - label: "${_howMuch.toInt()} wei", + label: "${_howMuch.toInt()/1000000000000000000} MCScoin", activeColor: CustomColors.blue900(context), value: _howMuch, onChanged: (newValue) { diff --git a/lib/controllers/sourcer_campaign_controller.dart b/lib/controllers/sourcer_campaign_controller.dart index cc3c275..a913811 100644 --- a/lib/controllers/sourcer_campaign_controller.dart +++ b/lib/controllers/sourcer_campaign_controller.dart @@ -167,11 +167,12 @@ class _SourcerCampaignControllerState extends State { }), TextButton( child: const Text('Yes'), - onPressed: () { - setState(() async { + onPressed: () async { + String result = + await CloseCampaignModel.closeMyCampaign( + contractAddress); + setState(() { Navigator.of(ctx).pop(true); - String result = await CloseCampaignModel - .closeMyCampaign(contractAddress); if (result.contains("Campaign Closed")) { ScaffoldMessenger.of(context) .showSnackBar(SnackBar( @@ -187,7 +188,7 @@ class _SourcerCampaignControllerState extends State { ScaffoldMessenger.of(context) .showSnackBar(SnackBar( content: Text( - result, + result, style: CustomTextStyle.spaceMonoWhite( context), ))); diff --git a/lib/controllers/sourcer_closed_campaign_controller.dart b/lib/controllers/sourcer_closed_campaign_controller.dart index 5b3d2a4..59a8384 100644 --- a/lib/controllers/sourcer_closed_campaign_controller.dart +++ b/lib/controllers/sourcer_closed_campaign_controller.dart @@ -81,17 +81,16 @@ class _SourcerClosedCampaignControllerState extends State[ - Row(children: [ + FittedBox( fit: BoxFit.contain,child: + Row(children: [ //loop - (names.length != - widget.contractAddress! - .length) + (names.length != widget.contractAddress!.length) ? GlobalText.loadingText(context) : Text( "Name: ${names[index]}", style: CustomTextStyle.spaceMono(context), ), - ]), + ])), Row(children: [ (latitude.length != widget.contractAddress!.length) ? GlobalText.loadingText(context) From 94712058f12c6abf4d1b8e5802917466c1aa38d4 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Mon, 13 Feb 2023 18:42:14 +0100 Subject: [PATCH 26/34] added geofence to sensing screen (ligth, photo) the system start a geofence and then check if the user exit from the area --- lib/models/geofence_model.dart | 97 +++++++++++++++++++++++++ lib/views/light_join_campaign_view.dart | 11 +++ lib/views/photo_join_campaign_view.dart | 14 ++++ 3 files changed, 122 insertions(+) diff --git a/lib/models/geofence_model.dart b/lib/models/geofence_model.dart index 9c8ad55..8467e66 100644 --- a/lib/models/geofence_model.dart +++ b/lib/models/geofence_model.dart @@ -1,4 +1,6 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:geolocator/geolocator.dart'; import 'package:mobile_crowd_sensing/services/notification_channels.dart'; @@ -6,6 +8,8 @@ import '../controllers/distance_controller.dart'; import 'dart:async'; import 'dart:ui'; +import '../utils/styles.dart'; + enum GeofenceEvent { init, enter, exit } class Geofence { @@ -140,6 +144,99 @@ class Geofence { }); } + geoFenceService(BuildContext context) async { + DartPluginRegistrant.ensureInitialized(); + + String debugString = "[GEOFENCE $title]"; + + if (kDebugMode) { + print('\x1B[31m [GEOFENCE SERVICE] geofence open for:' + '\n $title' + '\n $address' + '\n $lat ' + '\n $lng ' + '\n $radius \x1B[0m'); + } + + if (kDebugMode) { + print('\x1B[31m [GEOFENCE SERVICE] geofence open for:' + '\n $title' + '\n $address' + '\n $lat ' + '\n $lng ' + '\n $radius \x1B[0m'); + } + + await _startGeofenceService( + pointedLatitude: lat, + pointedLongitude: lng, + radiusMeter: radius, // TO CHANGE + eventPeriodInSeconds: 10); + + GeofenceEvent? previous; + + getGeofenceStream()?.listen((GeofenceEvent event) { + if (kDebugMode) { + print(event.toString()); + } + + if (previous == null || previous == GeofenceEvent.init) { + switch (event) { + case GeofenceEvent.enter: + previous = event; + break; + case GeofenceEvent.exit: + previous = event; + break; + default: + previous = event; + break; + } + } + + switch (event) { + case GeofenceEvent.init: + if (kDebugMode) { + print('\x1B[31m $debugString status: Init\x1B[0m'); + } + previous = event; + break; + case GeofenceEvent.enter: + if (kDebugMode) { + print('\x1B[31m $debugString status: Enter\x1B[0m'); + } + if (previous != event) { + } else { + if (kDebugMode) { + print('\x1B[31m $debugString status not changed \x1B[0m'); + } + } + previous = event; + break; + case GeofenceEvent.exit: + if (kDebugMode) { + print('\x1B[31m $debugString status: Exit\x1B[0m'); + } + if (previous != event) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text( + "Exit from the area", + style: CustomTextStyle.spaceMonoWhite(context), + ))); + stopGeofenceService(); + Navigator.of(context).pushNamedAndRemoveUntil( + '/home', (Route route) => false); + } else { + if (kDebugMode) { + print('\x1B[31m $debugString status not changed \x1B[0m'); + } + } + previous = event; + break; + } + }); + } + _startGeofenceService( {required String pointedLatitude, required String pointedLongitude, diff --git a/lib/views/light_join_campaign_view.dart b/lib/views/light_join_campaign_view.dart index 68755ca..755b3e1 100644 --- a/lib/views/light_join_campaign_view.dart +++ b/lib/views/light_join_campaign_view.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:environment_sensors/environment_sensors.dart'; import 'package:flutter/material.dart'; +import 'package:mobile_crowd_sensing/models/geofence_model.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; import '../models/upload_ipfs_model.dart'; import '../utils/join_campaign_factory.dart'; @@ -27,6 +28,13 @@ class LightJoinCampaignViewState extends State { List lights = []; double averageRelevation = 0; + late Geofence geo; + + @override + void dispose() { + geo.stopGeofenceService(); + super.dispose(); + } @override Widget build(BuildContext context) { @@ -34,6 +42,9 @@ class LightJoinCampaignViewState extends State { campaignSelectedData = jsonDecode(jsonEncode(parameters)); SessionModel sessionData = SessionModel(); + geo = Geofence(campaignSelectedData['name'], campaignSelectedData['contractAddress'], campaignSelectedData['lat'], campaignSelectedData['lng'], campaignSelectedData['range']); + geo.geoFenceService(context); + return Scaffold( resizeToAvoidBottomInset: false, appBar: AppBar( diff --git a/lib/views/photo_join_campaign_view.dart b/lib/views/photo_join_campaign_view.dart index f94bb43..9abd0f1 100644 --- a/lib/views/photo_join_campaign_view.dart +++ b/lib/views/photo_join_campaign_view.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import '../models/geofence_model.dart'; import '../models/upload_ipfs_model.dart'; import '../utils/join_campaign_factory.dart'; import '../utils/styles.dart'; @@ -23,6 +24,15 @@ class PhotoJoinCampaignViewState extends State { List pictures = []; bool gate = true; bool visible = false; + late Geofence geo; + + + @override + void dispose() { + geo.stopGeofenceService(); + super.dispose(); + } + @override Widget build(BuildContext context) { dynamic space = DeviceDimension.deviceWidth(context) * 0.05; @@ -31,6 +41,10 @@ class PhotoJoinCampaignViewState extends State { parameters = ModalRoute.of(context)!.settings.arguments; campaignSelectedData = jsonDecode(jsonEncode(parameters)); SessionModel sessionData = SessionModel(); + + geo = Geofence(campaignSelectedData['name'], campaignSelectedData['contractAddress'], campaignSelectedData['lat'], campaignSelectedData['lng'], campaignSelectedData['range']); + geo.geoFenceService(context); + (pictures.isNotEmpty) ? visible = true : visible = false; return Scaffold( resizeToAvoidBottomInset: false, From 87e09df54432cc2404d217be05d7efc0cbef678d Mon Sep 17 00:00:00 2001 From: Giacomo Date: Mon, 13 Feb 2023 20:47:35 +0100 Subject: [PATCH 27/34] fixed floating point --- lib/controllers/campaign_list_controller.dart | 4 +++- .../claim_campaign_controller.dart | 5 ++-- .../create_campaign_form_controller.dart | 2 +- lib/controllers/wallet_controller.dart | 16 +++++++++---- pubspec.lock | 24 +++++++++++++++++++ pubspec.yaml | 1 + 6 files changed, 44 insertions(+), 8 deletions(-) diff --git a/lib/controllers/campaign_list_controller.dart b/lib/controllers/campaign_list_controller.dart index f72be37..e38a74f 100644 --- a/lib/controllers/campaign_list_controller.dart +++ b/lib/controllers/campaign_list_controller.dart @@ -1,3 +1,4 @@ +import 'package:big_dart/big_dart.dart'; import 'package:flutter/material.dart'; import 'package:mobile_crowd_sensing/models/campaign_list_model.dart'; import 'package:numberpicker/numberpicker.dart'; @@ -98,7 +99,8 @@ class _CampaignListControllerState contractAddress = current[7].toString(); readebleLocation = current[8]; isSubscribed = current[9]; - balance = "${(BigInt.parse(current[10].toString()).toDouble() /1000000000000000000)} MCScoin"; + balance = "${(Big(current[10].toString()).div(Big("1000000000000000000"))).toString()} MCScoin"; + print("DEBUG::::::: $balance"); return GestureDetector( onTap: () { diff --git a/lib/controllers/claim_campaign_controller.dart b/lib/controllers/claim_campaign_controller.dart index 82dfee5..38613fd 100644 --- a/lib/controllers/claim_campaign_controller.dart +++ b/lib/controllers/claim_campaign_controller.dart @@ -1,3 +1,4 @@ +import 'package:big_dart/big_dart.dart'; import 'package:flutter/material.dart'; import 'package:flutter_config/flutter_config.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; @@ -76,7 +77,7 @@ class _ClaimCampaignControllerState extends State { context: context, builder: (ctx) => AlertDialog( title: const Text('Want to Claim?'), - content: Text('you will recive:\n$reward MCSCoin'), + content: Text('you will recive:\n${(Big(reward.toString())/Big(1000000000000000000)).toString()} MCSCoin'), actions: [ TextButton( child: const Text('No'), @@ -177,7 +178,7 @@ class _ClaimCampaignControllerState extends State { style: CustomTextStyle.spaceMonoBold(context), ), Text( - "${BigInt.parse(reward).toDouble()/1000000000000000000} MCScoin", + "${Big(reward).div(Big("1000000000000000000")).toString()} MCScoin", style: CustomTextStyle.spaceMono(context), ) ])), diff --git a/lib/controllers/create_campaign_form_controller.dart b/lib/controllers/create_campaign_form_controller.dart index b1cacfd..c316682 100644 --- a/lib/controllers/create_campaign_form_controller.dart +++ b/lib/controllers/create_campaign_form_controller.dart @@ -17,7 +17,7 @@ class _CreateCampaignFormControllerState extends State { final _formKey = GlobalKey(); String selectedValue = 'photo'; - double _howMuch = 1000; + double _howMuch = 0; int _howFar = 100; final titleController = TextEditingController(); String? address; diff --git a/lib/controllers/wallet_controller.dart b/lib/controllers/wallet_controller.dart index 0e8b1ee..358b93c 100644 --- a/lib/controllers/wallet_controller.dart +++ b/lib/controllers/wallet_controller.dart @@ -1,5 +1,7 @@ import 'dart:async'; import 'dart:convert'; +import 'package:big_dart/big_dart.dart'; +import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; import '../models/wallet_model.dart'; @@ -77,12 +79,18 @@ class _WalletControllerState extends State { }); } + bool isNumeric(String s) { + if(s == null) { + return false; + } + return double.tryParse(s) != null; + } + Widget _formatBalance(String balance) { - double? parsed = double.tryParse(balance); - if (parsed != null && balance != "0") { - parsed = parsed / 1000000000000000000; + if (balance != "0" && isNumeric(balance)) { + Big res = Big(balance).div(Big("1000000000000000000")); return Text( - parsed.toString(), + res.toString(), style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ); } else { diff --git a/pubspec.lock b/pubspec.lock index 67350a9..baac19e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -41,6 +41,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.10.0" + big_dart: + dependency: "direct main" + description: + name: big_dart + sha256: fced31c3db87e489f7ed95e44ae4778b50aa97f2dedcbfb2364372eef6769425 + url: "https://pub.dev" + source: hosted + version: "1.0.1" boolean_selector: dependency: transitive description: @@ -289,6 +297,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.8" + decimal: + dependency: "direct main" + description: + name: decimal + sha256: eece91944f523657c75a3a008a90ec7f7eb3986191153a78570c7d0ac8ef3d01 + url: "https://pub.dev" + source: hosted + version: "2.3.2" device_info_plus: dependency: "direct main" description: @@ -1032,6 +1048,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.2.1" + rational: + dependency: transitive + description: + name: rational + sha256: ba58e9e18df9abde280e8b10051e4bce85091e41e8e7e411b6cde2e738d357cf + url: "https://pub.dev" + source: hosted + version: "2.2.2" sec: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 9e7a197..10157ca 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -67,6 +67,7 @@ dependencies: connectivity: ^3.0.6 flutter_isolate: ^2.0.4 walletconnect_secure_storage: ^1.0.0 + big_dart: ^1.0.1 dev_dependencies: flutter_test: From 1de6938536d6190e9bc4cf4de689fdca022e52df Mon Sep 17 00:00:00 2001 From: Giacomo Date: Tue, 14 Feb 2023 19:42:18 +0100 Subject: [PATCH 28/34] aggiunto logout --- contracts/Campaign.sol | 1 + lib/controllers/wallet_controller.dart | 1 - lib/main.dart | 3 -- lib/models/geofence_model.dart | 4 +-- lib/models/session_model.dart | 6 ++++ lib/views/wallet_view.dart | 39 ++++++++++++++++++++------ pubspec.lock | 16 ----------- 7 files changed, 39 insertions(+), 31 deletions(-) diff --git a/contracts/Campaign.sol b/contracts/Campaign.sol index 9fa84af..98554dd 100644 --- a/contracts/Campaign.sol +++ b/contracts/Campaign.sol @@ -125,6 +125,7 @@ contract Campaign is Ownable, Initializable { function closeCampaignAndPay() public payable { require(msg.sender == addressCrowdSourcer,'you are not the owner'); + require(numberOfActiveVerifiers > 0, 'you cant close a campaign without verifier'); isClosed = factoryContractAddress.closeCampaign(); uint256 balance = getCampaignBalance(); uint256 verifiesTotalReward = (balance * 50 / 100); diff --git a/lib/controllers/wallet_controller.dart b/lib/controllers/wallet_controller.dart index 358b93c..e4e0f2d 100644 --- a/lib/controllers/wallet_controller.dart +++ b/lib/controllers/wallet_controller.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:convert'; import 'package:big_dart/big_dart.dart'; -import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; import '../models/wallet_model.dart'; diff --git a/lib/main.dart b/lib/main.dart index ad3bd34..b138282 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -25,9 +25,6 @@ import 'package:mobile_crowd_sensing/views/validate_photo_view.dart'; import 'package:mobile_crowd_sensing/views/wallet_view.dart'; import 'dart:async'; import 'package:connectivity/connectivity.dart'; -import 'package:walletconnect_dart/walletconnect_dart.dart'; - -import 'models/db_session_model.dart'; class LifecycleWatcher extends StatefulWidget { const LifecycleWatcher({super.key}); diff --git a/lib/models/geofence_model.dart b/lib/models/geofence_model.dart index 8467e66..330b700 100644 --- a/lib/models/geofence_model.dart +++ b/lib/models/geofence_model.dart @@ -285,9 +285,9 @@ class Geofence { } } - stopGeofenceService() { + Future stopGeofenceService() async { if (_positionStream != null) { - _positionStream!.cancel(); + await _positionStream!.cancel(); } } } diff --git a/lib/models/session_model.dart b/lib/models/session_model.dart index a976727..eb15d11 100644 --- a/lib/models/session_model.dart +++ b/lib/models/session_model.dart @@ -119,6 +119,12 @@ class SessionModel { _initSession(); } + Future disconnect() async { + await dbSession.deleteSession(connector!.session.accounts[0]); + await connector!.killSession(); + connector = null; + await ethClient.dispose(); + } EthereumWalletConnectProvider getProvider(){ return provider; diff --git a/lib/views/wallet_view.dart b/lib/views/wallet_view.dart index 2ba6af8..b116b1b 100644 --- a/lib/views/wallet_view.dart +++ b/lib/views/wallet_view.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:mobile_crowd_sensing/models/session_model.dart'; import 'package:mobile_crowd_sensing/utils/styles.dart'; @@ -12,21 +13,41 @@ class WalletView extends StatelessWidget { @override Widget build(BuildContext context) { SessionModel session = SessionModel(); - if(!session.provider.connector.connected) { + if (!session.provider.connector.connected) { WidgetsBinding.instance.addPostFrameCallback((_) { - Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => const LoginView())); - });} + Navigator.pushReplacement( + context, MaterialPageRoute(builder: (_) => const LoginView())); + }); + } return Scaffold( appBar: AppBar( - title: const Text("HOME"), + title: Row(children: [ + Flexible(flex: 2, child: Container()), + const Flexible(flex: 1, child: Text("HOME")), + Flexible(flex: 1, child: Container()), + Flexible( + flex: 1, + child: TextButton( + onPressed: () { + SessionModel().disconnect(); + Future.delayed(Duration.zero, () { + Navigator.of(context) + .pushNamedAndRemoveUntil('/login', (Route route) => false); + }); + }, + child: const Text( + "LOGOUT", + style: TextStyle( + fontSize: 12, + color: Colors.white, + ), + ))) + ]), centerTitle: true, backgroundColor: CustomColors.blue900(context), ), - body: Column( children: const [ - WalletController(), - ClaimCampaignController() - ]) - ); + body: Column( + children: const [WalletController(), ClaimCampaignController()])); } } diff --git a/pubspec.lock b/pubspec.lock index baac19e..a69c1d6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -297,14 +297,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.8" - decimal: - dependency: "direct main" - description: - name: decimal - sha256: eece91944f523657c75a3a008a90ec7f7eb3986191153a78570c7d0ac8ef3d01 - url: "https://pub.dev" - source: hosted - version: "2.3.2" device_info_plus: dependency: "direct main" description: @@ -1048,14 +1040,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.2.1" - rational: - dependency: transitive - description: - name: rational - sha256: ba58e9e18df9abde280e8b10051e4bce85091e41e8e7e411b6cde2e738d357cf - url: "https://pub.dev" - source: hosted - version: "2.2.2" sec: dependency: transitive description: From 640412c37ac357f08fa32f9ccc5ad53556b39d79 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Thu, 16 Feb 2023 13:58:35 +0100 Subject: [PATCH 29/34] fix minor bug logout not awaited funcion before redirrect --- lib/models/session_model.dart | 10 +++++++--- lib/views/wallet_view.dart | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/models/session_model.dart b/lib/models/session_model.dart index eb15d11..26e4e61 100644 --- a/lib/models/session_model.dart +++ b/lib/models/session_model.dart @@ -92,9 +92,13 @@ class SessionModel { if (kDebugMode) { print('\x1B[31m[EVENT DISCONNECT] \x1B[0m'); } - connector!.killSession(); - connector = null; - ethClient.dispose(); + try{ + ethClient.dispose(); + connector!.killSession(); + connector = null; + } catch (e) { + print('\x1B[31m[EVENT DISCONNECT] ERROR: ${e.toString()} \x1B[0m'); + } }, onConnect: (SessionStatus session){ if (kDebugMode) { diff --git a/lib/views/wallet_view.dart b/lib/views/wallet_view.dart index b116b1b..ae7a7bd 100644 --- a/lib/views/wallet_view.dart +++ b/lib/views/wallet_view.dart @@ -29,8 +29,8 @@ class WalletView extends StatelessWidget { Flexible( flex: 1, child: TextButton( - onPressed: () { - SessionModel().disconnect(); + onPressed: () async { + await SessionModel().disconnect(); Future.delayed(Duration.zero, () { Navigator.of(context) .pushNamedAndRemoveUntil('/login', (Route route) => false); From 2b2e6bc48aeb7309dae806992e31a1b73309d1a2 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Thu, 16 Feb 2023 16:32:29 +0100 Subject: [PATCH 30/34] fixed stop service, when upload worker --- lib/views/light_join_campaign_view.dart | 1 + lib/views/photo_join_campaign_view.dart | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/views/light_join_campaign_view.dart b/lib/views/light_join_campaign_view.dart index 755b3e1..26bb671 100644 --- a/lib/views/light_join_campaign_view.dart +++ b/lib/views/light_join_campaign_view.dart @@ -195,6 +195,7 @@ class LightJoinCampaignViewState extends State { style: CustomTextStyle .spaceMonoWhite(context), ))); + geo.stopGeofenceService(); Navigator.of(context) .pushNamedAndRemoveUntil( '/home', diff --git a/lib/views/photo_join_campaign_view.dart b/lib/views/photo_join_campaign_view.dart index 9abd0f1..2a0b9df 100644 --- a/lib/views/photo_join_campaign_view.dart +++ b/lib/views/photo_join_campaign_view.dart @@ -244,6 +244,7 @@ class PhotoJoinCampaignViewState extends State { style: CustomTextStyle .spaceMonoWhite(context), ))); + geo.stopGeofenceService(); Navigator.of(context).pushNamedAndRemoveUntil( '/home', (Route route) => false); }); From a385e2e3a358a2ffd39fd5782892e10775bd7e94 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Fri, 17 Feb 2023 21:26:21 +0100 Subject: [PATCH 31/34] validate light controller refactor --- .../validate_light_controller.dart | 391 ++++++++++-------- lib/models/validate_model.dart | 4 +- 2 files changed, 223 insertions(+), 172 deletions(-) diff --git a/lib/controllers/validate_light_controller.dart b/lib/controllers/validate_light_controller.dart index 8e44fd5..e44253f 100644 --- a/lib/controllers/validate_light_controller.dart +++ b/lib/controllers/validate_light_controller.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import '../../utils/join_campaign_factory.dart'; import '../../utils/styles.dart'; import '../models/validate_model.dart'; +import '../utils/spalsh_screens.dart'; import '../views/dialog_view.dart'; class ValidateLightController extends JoinCampaignFactory { @@ -19,188 +20,238 @@ class ValidateLightControllerState extends State { dynamic campaignSelectedData = {}; Object? parameters; EnvironmentSensors environmentSensors = EnvironmentSensors(); - bool activeSensor = false, sensorGate = false, downloadGate = false; + bool activeSensor = false, sensorGate = false; double sum = 0, averageRelevation = 0; - late String? hash = "Loading...", time = "Loading...", relevation = "Loading..."; - late List? data; + late String? time = "Loading...", relevation = "Loading..."; + late List fileInfo = []; + late List data = []; List lights = []; - _prepareData() async { + _prepareData(String hash, String contractAddress) async { data = await ValidateModel.downloadLightFiles(hash); - downloadGate = !downloadGate; - time = DateTime.fromMillisecondsSinceEpoch(int.parse(data![0])).toString(); - relevation = double.parse(data![1]).toString(); + fileInfo = await ValidateModel.getFileData(hash, contractAddress); + time = DateTime.fromMillisecondsSinceEpoch(int.parse(data[0])).toString(); + relevation = double.parse(data[1]).toString(); } @override Widget build(BuildContext context) { parameters = ModalRoute.of(context)!.settings.arguments; campaignSelectedData = jsonDecode(jsonEncode(parameters)); - hash = campaignSelectedData['ipfsHash']; - if (hash != null && !downloadGate) { - _prepareData(); - } - return - ListView( - shrinkWrap: false, - children: [ - Column( - children: [ - Text( - 'ipfs hash: ', - style: CustomTextStyle.spaceMonoBold(context), - ), - Text( - '${campaignSelectedData['ipfsHash']}', - style: CustomTextStyle.inconsolata(context), - ), - ], - ), - Center(child: TextButton( - style: ButtonStyle( - backgroundColor: MaterialStateProperty.all( - CustomColors.blue900(context)), - maximumSize: - MaterialStateProperty.all(const Size(200, 40)), - ), - onPressed: () async { - bool lightAvailable = await environmentSensors - .getSensorAvailable(SensorType.Light); - if (lightAvailable) { - setState(() { - activeSensor = true; - sensorGate = !sensorGate; - sum = 0; - lights.clear(); - averageRelevation = 0; - }); - } else { - setState(() { - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (BuildContext context) => - const DialogView( - message: - "This device doesn't integrate the appropriate sensor"))); - }); - } - }, - child: const Text('Check Data', - style: TextStyle(color: Colors.white)))), - (activeSensor && sensorGate) ? - StreamBuilder( + String hash = campaignSelectedData['ipfsHash']; + String contractAddress = campaignSelectedData["contractAddress"]; - stream: environmentSensors.light, - builder: (context, snapshot) { - if (!snapshot.hasData) { - return const Center(child: CircularProgressIndicator()); - } else { - lights.add(snapshot.data!); - sum += lights.last; - averageRelevation = double.parse( - (sum / lights.length).toStringAsFixed(2)); - return Padding( - padding: EdgeInsets.only( - top: DeviceDimension.deviceHeight(context) * 0.15, - left: DeviceDimension.deviceWidth(context) * 0.09, + return FutureBuilder( + future: _prepareData(hash, contractAddress), + builder: (BuildContext context, AsyncSnapshot snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.none: + return const Center(child: Text('Sorry something goes wrong...')); + case ConnectionState.waiting: + return CustomSplashScreen.fadingCubeBlueBg(context); + default: + return _buildPage(hash); + } + }); + } + + Widget _buildPage(hash) + { + return ListView(shrinkWrap: false, children: [ + Padding( + padding: const EdgeInsets.all(10), + child: Column( + children: [ + Text( + 'ipfs hash: ', + style: CustomTextStyle.spaceMonoBold(context), + ), + FittedBox( + fit: BoxFit.fitWidth, + child: Text( + '${campaignSelectedData['ipfsHash']}', + style: CustomTextStyle.inconsolata(context), + )), + const SizedBox( + height: 20, + ), + Row(children: [ + Text('Average Data Collected: ', + style: CustomTextStyle.merriweatherBold(context)), + Text('$relevation ', + style: CustomTextStyle.inconsolata(context)), + ]), + Row(children: [ + Text('On: ', style: CustomTextStyle.merriweatherBold(context)), + Text('$time', style: CustomTextStyle.inconsolata(context)), + ]), + const SizedBox( + height: 20, + ), + Row(children: [ + Text('Latitude: ', + style: CustomTextStyle.merriweatherBold(context)), + Text('${double.parse(fileInfo[5].toString()) / 10000000}', + style: CustomTextStyle.inconsolata(context)), + ]), + Row(children: [ + Text('Longitude: ', + style: CustomTextStyle.merriweatherBold(context)), + Text('${double.parse(fileInfo[6].toString()) / 10000000}', + style: CustomTextStyle.inconsolata(context)), + ]), + ], + )), + const SizedBox( + height: 20, + ), + Center( + child: TextButton( + style: ButtonStyle( + backgroundColor: + MaterialStateProperty.all(CustomColors.blue900(context)), + maximumSize: MaterialStateProperty.all(const Size(200, 40)), + ), + onPressed: () async { + bool lightAvailable = await environmentSensors + .getSensorAvailable(SensorType.Light); + if (lightAvailable) { + setState(() { + activeSensor = true; + sensorGate = !sensorGate; + sum = 0; + lights.clear(); + averageRelevation = 0; + }); + } else { + setState(() { + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (BuildContext context) => const DialogView( + message: + "This device doesn't integrate the appropriate sensor"))); + }); + } + }, + child: const Text('Check Data', + style: TextStyle(color: Colors.white)))), + (activeSensor && sensorGate) + ? StreamBuilder( + stream: environmentSensors.light, + builder: (context, snapshot) { + if (!snapshot.hasData) { + return const Center(child: CircularProgressIndicator()); + } else { + lights.add(snapshot.data!); + sum += lights.last; + averageRelevation = + double.parse((sum / lights.length).toStringAsFixed(2)); + return Padding( + padding: EdgeInsets.only( + top: DeviceDimension.deviceHeight(context) * 0.15, + left: DeviceDimension.deviceWidth(context) * 0.09, + ), + child: Wrap( + alignment: + WrapAlignment.spaceAround, // set your alignment + children: [ + Row(children: [ + Text('Average Ambient Light: ', + style: CustomTextStyle.merriweatherBold( + context)), + Text('$averageRelevation', + style: CustomTextStyle.inconsolata(context)) + ]), + Row(children: [ + Text('Number of relevations: ', + style: CustomTextStyle.merriweatherBold( + context)), + Text('${lights.length}', + style: CustomTextStyle.inconsolata(context)) + ]), + const SizedBox( + height: 50, ), - child: Wrap( - alignment: WrapAlignment - .spaceAround, // set your alignment - children: [ - Row(children: [ - Text('Average Ambient Light: ', - style: CustomTextStyle.merriweatherBold( - context)), - Text('$averageRelevation', - style: CustomTextStyle.inconsolata( - context)) - ]), - Row(children: [ - Text('Number of relevations: ', - style: CustomTextStyle.merriweatherBold( - context)), - Text('${lights.length}', - style: CustomTextStyle.inconsolata( - context)) - ]), - Row(children: [ - Text('Average Data Collected: ', - style: CustomTextStyle.merriweatherBold( - context)), - Text('$relevation ', - style: CustomTextStyle.inconsolata( - context)), - ]), - Row(children: [ - Text(' On: ', - style: CustomTextStyle.merriweatherBold( - context)), - Text('$time', - style: CustomTextStyle.inconsolata( - context)), - ]), - FloatingActionButton( - heroTag: "verified", - onPressed: () async { - bool res = await ValidateModel.approveOrNot(campaignSelectedData['contractAddress'], hash, true); - if(res) { - if(!mounted) {return;} - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar( - content: Text( - 'Data verified', - style: CustomTextStyle.spaceMonoWhite(context), - ))); - Navigator.of(context) - .pushNamedAndRemoveUntil('/home', (Route route) => false); - } else { - if(!mounted) {return;} - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar( - content: Text( - 'An Error occurred', - style: CustomTextStyle.spaceMonoWhite(context), - ))); - } - }, - backgroundColor: - CustomColors.green600(context), - child: const Icon(Icons.check)), - FloatingActionButton( - heroTag: "notVerified", - onPressed: () async { - bool res = await ValidateModel.approveOrNot(campaignSelectedData['contractAddress'], hash, false); - if(res) { - if(!mounted) {return;} - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar( - content: Text( - 'Data verified', - style: CustomTextStyle.spaceMonoWhite(context), - ))); - Navigator.of(context) - .pushNamedAndRemoveUntil('/home', (Route route) => false); - } else { - if(!mounted) {return;} - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar( - content: Text( - 'An Error occurred', - style: CustomTextStyle.spaceMonoWhite(context), - ))); - } - }, - backgroundColor: - CustomColors.red600(context), - child: const Icon(Icons.close)), - ])); - } - }) - : const Center( child:Text( - "check data for get a relevation and compare the result")) - ]); + FloatingActionButton( + heroTag: "verified", + onPressed: () async { + bool res = await ValidateModel.approveOrNot( + campaignSelectedData['contractAddress'], + hash, + true); + if (res) { + if (!mounted) { + return; + } + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + 'Data verified', + style: CustomTextStyle.spaceMonoWhite( + context), + ))); + Navigator.of(context) + .pushNamedAndRemoveUntil('/home', + (Route route) => false); + } else { + if (!mounted) { + return; + } + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + 'An Error occurred', + style: CustomTextStyle.spaceMonoWhite( + context), + ))); + } + }, + backgroundColor: CustomColors.green600(context), + child: const Icon(Icons.check)), + FloatingActionButton( + heroTag: "notVerified", + onPressed: () async { + bool res = await ValidateModel.approveOrNot( + campaignSelectedData['contractAddress'], + hash, + false); + if (res) { + if (!mounted) { + return; + } + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + 'Data verified', + style: CustomTextStyle.spaceMonoWhite( + context), + ))); + Navigator.of(context) + .pushNamedAndRemoveUntil('/home', + (Route route) => false); + } else { + if (!mounted) { + return; + } + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + 'An Error occurred', + style: CustomTextStyle.spaceMonoWhite( + context), + ))); + } + }, + backgroundColor: CustomColors.red600(context), + child: const Icon(Icons.close)), + ])); + } + }) + : const Center( + child: Text( + "check data for get a relevation and compare the result")) + ]); } } diff --git a/lib/models/validate_model.dart b/lib/models/validate_model.dart index 06a8bdf..2a8c497 100644 --- a/lib/models/validate_model.dart +++ b/lib/models/validate_model.dart @@ -8,8 +8,8 @@ import 'ipfs_client_model.dart'; class ValidateModel { static downloadLightFiles(hashToDownload) async { - String? res = - await IpfsClientModel.downloadItemIPFS(hashToDownload, 'lights'); + String? res = await IpfsClientModel.downloadItemIPFS(hashToDownload, 'lights'); + if (res != null) { List value = res.split('/'); return value; From a252fc1f102c55478ca4b7449fab2b2fcc1d6a0e Mon Sep 17 00:00:00 2001 From: Giacomo Date: Fri, 17 Feb 2023 22:11:46 +0100 Subject: [PATCH 32/34] sensor light controller --- lib/controllers/light_sensor_controller.dart | 178 +++++++++++++ .../validate_light_controller.dart | 241 ++++-------------- lib/views/light_join_campaign_view.dart | 11 +- 3 files changed, 232 insertions(+), 198 deletions(-) create mode 100644 lib/controllers/light_sensor_controller.dart diff --git a/lib/controllers/light_sensor_controller.dart b/lib/controllers/light_sensor_controller.dart new file mode 100644 index 0000000..c557b7a --- /dev/null +++ b/lib/controllers/light_sensor_controller.dart @@ -0,0 +1,178 @@ +import 'dart:convert'; + +import 'package:environment_sensors/environment_sensors.dart'; +import 'package:flutter/material.dart'; + +import '../models/validate_model.dart'; +import '../utils/styles.dart'; +import '../views/dialog_view.dart'; + +class LightSensorController extends StatefulWidget { + const LightSensorController({Key? key}) : super(key: key); + + @override + State createState() => _LightSensorControllerState(); +} + +class _LightSensorControllerState extends State { + dynamic campaignSelectedData = {}; + Object? parameters; + EnvironmentSensors environmentSensors = EnvironmentSensors(); + bool activeSensor = false, sensorGate = false; + double sum = 0, averageRelevation = 0; + List lights = []; + + @override + Widget build(BuildContext context) { + parameters = ModalRoute.of(context)!.settings.arguments; + campaignSelectedData = jsonDecode(jsonEncode(parameters)); + String hash = campaignSelectedData['ipfsHash']; + + return Column( children: [ + Center(child:TextButton( + style: ButtonStyle( + backgroundColor: + MaterialStateProperty.all(CustomColors.blue900(context)), + maximumSize: MaterialStateProperty.all(const Size(200, 40)), + ), + onPressed: () async { + bool lightAvailable = await environmentSensors + .getSensorAvailable(SensorType.Light); + if (lightAvailable) { + setState(() { + activeSensor = true; + sensorGate = !sensorGate; + sum = 0; + lights.clear(); + averageRelevation = 0; + }); + } else { + setState(() { + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (BuildContext context) => const DialogView( + message: + "This device doesn't integrate the appropriate sensor"))); + }); + } + }, + child: const Text('Check Data',style: TextStyle(color: Colors.white)))), + (activeSensor && sensorGate)? + StreamBuilder( + stream: environmentSensors.light, + builder: (context, snapshot) { + if (!snapshot.hasData) { + return const Center(child: CircularProgressIndicator()); + } else { + lights.add(snapshot.data!); + sum += lights.last; + averageRelevation = + double.parse((sum / lights.length).toStringAsFixed(2)); + return Padding( + padding: EdgeInsets.only( + top: DeviceDimension.deviceHeight(context) * 0.15, + left: DeviceDimension.deviceWidth(context) * 0.09, + ), + child: Wrap( + alignment: + WrapAlignment.spaceAround, // set your alignment + children: [ + Row(children: [ + Text('Average Ambient Light: ', + style: CustomTextStyle.merriweatherBold( + context)), + Text('$averageRelevation', + style: CustomTextStyle.inconsolata(context)) + ]), + Row(children: [ + Text('Number of relevations: ', + style: CustomTextStyle.merriweatherBold( + context)), + Text('${lights.length}', + style: CustomTextStyle.inconsolata(context)) + ]), + const SizedBox( + height: 50, + ), + FloatingActionButton( + heroTag: "verified", + onPressed: () async { + bool res = await ValidateModel.approveOrNot( + campaignSelectedData['contractAddress'], + hash, + true); + if (res) { + if (!mounted) { + return; + } + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + 'Data verified', + style: CustomTextStyle.spaceMonoWhite( + context), + ))); + Navigator.of(context) + .pushNamedAndRemoveUntil('/home', + (Route route) => false); + } else { + if (!mounted) { + return; + } + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + 'An Error occurred', + style: CustomTextStyle.spaceMonoWhite( + context), + ))); + } + }, + backgroundColor: CustomColors.green600(context), + child: const Icon(Icons.check)), + FloatingActionButton( + heroTag: "notVerified", + onPressed: () async { + bool res = await ValidateModel.approveOrNot( + campaignSelectedData['contractAddress'], + hash, + false); + if (res) { + if (!mounted) { + return; + } + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + 'Data verified', + style: CustomTextStyle.spaceMonoWhite( + context), + ))); + Navigator.of(context) + .pushNamedAndRemoveUntil('/home', + (Route route) => false); + } else { + if (!mounted) { + return; + } + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text( + 'An Error occurred', + style: CustomTextStyle.spaceMonoWhite( + context), + ))); + } + }, + backgroundColor: CustomColors.red600(context), + child: const Icon(Icons.close)), + ])); + } + }) + : const Center( + child: Text( + "check data for get a relevation and compare the result")) + ]); + } +} diff --git a/lib/controllers/validate_light_controller.dart b/lib/controllers/validate_light_controller.dart index e44253f..ac69df6 100644 --- a/lib/controllers/validate_light_controller.dart +++ b/lib/controllers/validate_light_controller.dart @@ -5,7 +5,7 @@ import '../../utils/join_campaign_factory.dart'; import '../../utils/styles.dart'; import '../models/validate_model.dart'; import '../utils/spalsh_screens.dart'; -import '../views/dialog_view.dart'; +import 'light_sensor_controller.dart'; class ValidateLightController extends JoinCampaignFactory { const ValidateLightController({super.key}); @@ -56,202 +56,49 @@ class ValidateLightControllerState extends State { }); } - Widget _buildPage(hash) - { - return ListView(shrinkWrap: false, children: [ - Padding( - padding: const EdgeInsets.all(10), - child: Column( - children: [ - Text( - 'ipfs hash: ', - style: CustomTextStyle.spaceMonoBold(context), - ), - FittedBox( - fit: BoxFit.fitWidth, - child: Text( - '${campaignSelectedData['ipfsHash']}', - style: CustomTextStyle.inconsolata(context), - )), - const SizedBox( - height: 20, - ), - Row(children: [ - Text('Average Data Collected: ', - style: CustomTextStyle.merriweatherBold(context)), - Text('$relevation ', - style: CustomTextStyle.inconsolata(context)), - ]), - Row(children: [ - Text('On: ', style: CustomTextStyle.merriweatherBold(context)), - Text('$time', style: CustomTextStyle.inconsolata(context)), - ]), - const SizedBox( - height: 20, - ), - Row(children: [ - Text('Latitude: ', - style: CustomTextStyle.merriweatherBold(context)), - Text('${double.parse(fileInfo[5].toString()) / 10000000}', - style: CustomTextStyle.inconsolata(context)), - ]), - Row(children: [ - Text('Longitude: ', - style: CustomTextStyle.merriweatherBold(context)), - Text('${double.parse(fileInfo[6].toString()) / 10000000}', - style: CustomTextStyle.inconsolata(context)), - ]), - ], - )), - const SizedBox( - height: 20, - ), - Center( - child: TextButton( - style: ButtonStyle( - backgroundColor: - MaterialStateProperty.all(CustomColors.blue900(context)), - maximumSize: MaterialStateProperty.all(const Size(200, 40)), - ), - onPressed: () async { - bool lightAvailable = await environmentSensors - .getSensorAvailable(SensorType.Light); - if (lightAvailable) { - setState(() { - activeSensor = true; - sensorGate = !sensorGate; - sum = 0; - lights.clear(); - averageRelevation = 0; - }); - } else { - setState(() { - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (BuildContext context) => const DialogView( - message: - "This device doesn't integrate the appropriate sensor"))); - }); - } - }, - child: const Text('Check Data', - style: TextStyle(color: Colors.white)))), - (activeSensor && sensorGate) - ? StreamBuilder( - stream: environmentSensors.light, - builder: (context, snapshot) { - if (!snapshot.hasData) { - return const Center(child: CircularProgressIndicator()); - } else { - lights.add(snapshot.data!); - sum += lights.last; - averageRelevation = - double.parse((sum / lights.length).toStringAsFixed(2)); - return Padding( - padding: EdgeInsets.only( - top: DeviceDimension.deviceHeight(context) * 0.15, - left: DeviceDimension.deviceWidth(context) * 0.09, - ), - child: Wrap( - alignment: - WrapAlignment.spaceAround, // set your alignment - children: [ - Row(children: [ - Text('Average Ambient Light: ', - style: CustomTextStyle.merriweatherBold( - context)), - Text('$averageRelevation', - style: CustomTextStyle.inconsolata(context)) - ]), - Row(children: [ - Text('Number of relevations: ', - style: CustomTextStyle.merriweatherBold( - context)), - Text('${lights.length}', - style: CustomTextStyle.inconsolata(context)) - ]), - const SizedBox( - height: 50, - ), - FloatingActionButton( - heroTag: "verified", - onPressed: () async { - bool res = await ValidateModel.approveOrNot( - campaignSelectedData['contractAddress'], - hash, - true); - if (res) { - if (!mounted) { - return; - } - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar( - content: Text( - 'Data verified', - style: CustomTextStyle.spaceMonoWhite( - context), - ))); - Navigator.of(context) - .pushNamedAndRemoveUntil('/home', - (Route route) => false); - } else { - if (!mounted) { - return; - } - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar( - content: Text( - 'An Error occurred', - style: CustomTextStyle.spaceMonoWhite( - context), - ))); - } - }, - backgroundColor: CustomColors.green600(context), - child: const Icon(Icons.check)), - FloatingActionButton( - heroTag: "notVerified", - onPressed: () async { - bool res = await ValidateModel.approveOrNot( - campaignSelectedData['contractAddress'], - hash, - false); - if (res) { - if (!mounted) { - return; - } - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar( - content: Text( - 'Data verified', - style: CustomTextStyle.spaceMonoWhite( - context), - ))); - Navigator.of(context) - .pushNamedAndRemoveUntil('/home', - (Route route) => false); - } else { - if (!mounted) { - return; - } - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar( - content: Text( - 'An Error occurred', - style: CustomTextStyle.spaceMonoWhite( - context), - ))); - } - }, - backgroundColor: CustomColors.red600(context), - child: const Icon(Icons.close)), - ])); - } - }) - : const Center( + Widget _buildPage(hash) { + return Padding( + padding: const EdgeInsets.all(10), + child: Column(children: [ + Text( + 'ipfs hash: ', + style: CustomTextStyle.spaceMonoBold(context), + ), + FittedBox( + fit: BoxFit.fitWidth, child: Text( - "check data for get a relevation and compare the result")) - ]); + '${campaignSelectedData['ipfsHash']}', + style: CustomTextStyle.inconsolata(context), + )), + const SizedBox( + height: 20, + ), + Row(children: [ + Text('Average Data Collected: ', + style: CustomTextStyle.merriweatherBold(context)), + Text('$relevation ', style: CustomTextStyle.inconsolata(context)), + ]), + Row(children: [ + Text('On: ', style: CustomTextStyle.merriweatherBold(context)), + Text('$time', style: CustomTextStyle.inconsolata(context)), + ]), + const SizedBox( + height: 20, + ), + Row(children: [ + Text('Latitude: ', + style: CustomTextStyle.merriweatherBold(context)), + Text('${double.parse(fileInfo[5].toString()) / 10000000}', + style: CustomTextStyle.inconsolata(context)), + ]), + Row(children: [ + Text('Longitude: ', + style: CustomTextStyle.merriweatherBold(context)), + Text('${double.parse(fileInfo[6].toString()) / 10000000}', + style: CustomTextStyle.inconsolata(context)), + ]), + const LightSensorController() + ]) + ); } } diff --git a/lib/views/light_join_campaign_view.dart b/lib/views/light_join_campaign_view.dart index 26bb671..dc9abce 100644 --- a/lib/views/light_join_campaign_view.dart +++ b/lib/views/light_join_campaign_view.dart @@ -90,6 +90,10 @@ class LightJoinCampaignViewState extends State { style: CustomTextStyle.merriweatherBold(context)), Text('${campaignSelectedData['lat']}', style: CustomTextStyle.inconsolata(context)), + ], + ), + Row( + children: [ Text('Longitude: ', style: CustomTextStyle.merriweatherBold(context)), Text( @@ -237,7 +241,12 @@ class LightJoinCampaignViewState extends State { ]); } }) - : const Text("NO DATA FOR THE MOMENT") + : Center( child: + Column( children: const [ + SizedBox(height: 20,), + Text("NO DATA FOR THE MOMENT") + ]) + ) ])) ]))); } From 4ad58e01cefbb7c636d0cfac544c0e06b1e0ddd5 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Sun, 19 Feb 2023 18:58:01 +0100 Subject: [PATCH 33/34] Update services.dart --- lib/services/services.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/services/services.dart b/lib/services/services.dart index f1ea2fd..aee6c89 100644 --- a/lib/services/services.dart +++ b/lib/services/services.dart @@ -125,10 +125,10 @@ class Services { ServicesController.statusBackgroundService = false; timer.cancel(); for (var element in geoList) { - element.stopGeofenceService(); + await element.stopGeofenceService(); } geoList.clear(); - service.stopSelf(); + await service.stopSelf(); if (kDebugMode) { print( '\x1B[31m [CLOSED SERVICE] No campaigns to follow. stop the service.\x1B[0m'); From da79008fd9864036fc6626f2c53c9cc42b7a5b0c Mon Sep 17 00:00:00 2001 From: Giacomo Date: Sun, 19 Feb 2023 19:13:23 +0100 Subject: [PATCH 34/34] aggiornate dipendenze camera --- pubspec.lock | 60 ++++++++++++++++++++++++++-------------------------- pubspec.yaml | 2 +- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index a69c1d6..fbedb0f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "0c80aeab9bc807ab10022cd3b2f4cf2ecdf231949dc1ddd9442406a003f19201" + sha256: "569ddca58d535e601dd1584afa117710abc999d036c0cd2c51777fb257df78e8" url: "https://pub.dev" source: hosted - version: "52.0.0" + version: "53.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: cd8ee83568a77f3ae6b913a36093a1c9b1264e7cb7f834d9ddd2311dade9c1f4 + sha256: "10927c4b7c7c88b1adbca278c3d5531db92e2f4b4abf04e2919a800af965f3f5" url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "5.5.0" archive: dependency: "direct main" description: @@ -29,10 +29,10 @@ packages: dependency: transitive description: name: args - sha256: "139d809800a412ebb26a3892da228b2d0ba36f0ef5d9a82166e5e52ec8d61611" + sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.0" async: dependency: transitive description: @@ -85,10 +85,10 @@ packages: dependency: transitive description: name: build_resolvers - sha256: "7c35a3a7868626257d8aee47b51c26b9dba11eaddf3431117ed2744951416aab" + sha256: db49b8609ef8c81cca2b310618c3017c00f03a92af44c04d310b907b2d692d95 url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.2.0" build_runner: dependency: "direct main" description: @@ -261,10 +261,10 @@ packages: dependency: transitive description: name: cryptography - sha256: e0e37f79665cd5c86e8897f9abe1accfe813c0cc5299dab22256e22fddc1fef8 + sha256: ffd770340e5a48f57e473c42d9036a773c43b396e80b41a2dd164ffaf53f57a4 url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.1.1" csslib: dependency: transitive description: @@ -301,10 +301,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: "7ff671ed0a6356fa8f2e1ae7d3558d3fb7b6a41e24455e4f8df75b811fb8e4ab" + sha256: "1d6e5a61674ba3a68fb048a7c7b4ff4bebfed8d7379dbe8f2b718231be9a7c95" url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "8.1.0" device_info_plus_platform_interface: dependency: transitive description: @@ -466,10 +466,10 @@ packages: dependency: transitive description: name: flutter_local_notifications_linux - sha256: "8f6c1611e0c4a88a382691a97bb3c3feb24cc0c0b54152b8b5fb7ffb837f7fbf" + sha256: ccb08b93703aeedb58856e5637450bf3ffec899adb66dc325630b68994734b89 url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.0.0+1" flutter_local_notifications_platform_interface: dependency: transitive description: @@ -490,10 +490,10 @@ packages: dependency: "direct main" description: name: flutter_native_splash - sha256: "048bd1f1dc0e5ea25899f702815934d9a9e916fe23451c320e7dd94d5e3ad933" + sha256: e301ae206ff0fb09b67d3716009c6c28c2da57a0ad164827b178421bb9d601f7 url: "https://pub.dev" source: hosted - version: "2.2.17" + version: "2.2.18" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -514,10 +514,10 @@ packages: dependency: transitive description: name: flutter_secure_storage_linux - sha256: "736436adaf91552433823f51ce22e098c2f0551db06b6596f58597a25b8ea797" + sha256: "0912ae29a572230ad52d8a4697e5518d7f0f429052fd51df7e5a7952c7efe2a3" url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.1.3" flutter_secure_storage_macos: dependency: transitive description: @@ -700,10 +700,10 @@ packages: dependency: transitive description: name: image - sha256: "3686865febd85c57a632d87a0fb1f0a8a9ef602fdb68d909c3e9aa29ec70fd24" + sha256: "483a389d6ccb292b570c31b3a193779b1b0178e7eb571986d9a49904b6861227" url: "https://pub.dev" source: hosted - version: "4.0.13" + version: "4.0.15" infinite_listview: dependency: transitive description: @@ -836,10 +836,10 @@ packages: dependency: "direct main" description: name: open_street_map_search_and_pick - sha256: "806c24b042b01658be0d083f34e9b43563ab6c0a49f4583b10e6b36b41f59167" + sha256: "5320774b5217a554c6bbe371d473728c8d2ed5e572a623735d425aa2b63c79bb" url: "https://pub.dev" source: hosted - version: "0.0.15" + version: "0.0.16" package_config: dependency: transitive description: @@ -884,10 +884,10 @@ packages: dependency: transitive description: name: path_provider_linux - sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + sha256: "2e32f1640f07caef0d3cb993680f181c79e54a3827b997d5ee221490d131fbd9" url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.1.8" path_provider_platform_interface: dependency: transitive description: @@ -1209,18 +1209,18 @@ packages: dependency: "direct main" description: name: syncfusion_flutter_charts - sha256: "400fa4c57a22f17b78fac6d086e39ecc7b7ece760fdf2041f235951f05640976" + sha256: "34d4c1cd35de6ebe5a3cdfe72a1154fdb04117625517609308d992789121bf78" url: "https://pub.dev" source: hosted - version: "20.4.49" + version: "20.4.50" syncfusion_flutter_core: dependency: transitive description: name: syncfusion_flutter_core - sha256: b5cb2525beb38fae36a363f72f8a2db92ed3995d6f0695968412cc6836e3a7b7 + sha256: "33141f9073c607bd113898d241aa6a03ccc1856a314bd061015180c35d47012f" url: "https://pub.dev" source: hosted - version: "20.4.49" + version: "20.4.50" synchronized: dependency: transitive description: @@ -1297,10 +1297,10 @@ packages: dependency: transitive description: name: universal_io - sha256: "79f78ddad839ee3aae3ec7c01eb4575faf0d5c860f8e5223bc9f9c17f7f03cef" + sha256: "06866290206d196064fd61df4c7aea1ffe9a4e7c4ccaa8fcded42dd41948005d" url: "https://pub.dev" source: hosted - version: "2.0.4" + version: "2.2.0" url_launcher: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 10157ca..a91094b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -44,7 +44,7 @@ dependencies: flutter_intl: ^0.0.1 flutter_config: ^2.0.0 http: ^0.13.5 - camera: ^0.10.0+4 + camera: ^0.10.3 path_provider: ^2.0.11 path: ^1.8.2 environment_sensors: ^0.2.0