From 5c2fa27aa7b605402f13d7f867b428c2f5b9c9f2 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Tue, 18 Feb 2025 22:56:50 +0100 Subject: [PATCH 1/5] ad helper --- .../android/app/src/main/AndroidManifest.xml | 3 ++ covas_mobile/ios/Runner/Info.plist | 3 ++ covas_mobile/lib/classes/ad_helper.dart | 38 ++++++++++++++++++ covas_mobile/lib/main.dart | 27 +++++++++++-- covas_mobile/lib/pages/EditSettings.dart | 2 +- .../Flutter/GeneratedPluginRegistrant.swift | 2 + covas_mobile/pubspec.lock | 40 +++++++++++++++++++ covas_mobile/pubspec.yaml | 1 + 8 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 covas_mobile/lib/classes/ad_helper.dart diff --git a/covas_mobile/android/app/src/main/AndroidManifest.xml b/covas_mobile/android/app/src/main/AndroidManifest.xml index 71290e3..510d7ba 100644 --- a/covas_mobile/android/app/src/main/AndroidManifest.xml +++ b/covas_mobile/android/app/src/main/AndroidManifest.xml @@ -6,6 +6,9 @@ android:label="covas_mobile" android:name="${applicationName}" android:icon="@mipmap/ic_launcher"> + NSLocationWhenInUseUsageDescription Your location is needed for showing nearby events + GADApplicationIdentifier + ca-app-pub-4855855675386260~3438207239 + diff --git a/covas_mobile/lib/classes/ad_helper.dart b/covas_mobile/lib/classes/ad_helper.dart new file mode 100644 index 0000000..92ac812 --- /dev/null +++ b/covas_mobile/lib/classes/ad_helper.dart @@ -0,0 +1,38 @@ +import 'package:google_mobile_ads/google_mobile_ads.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; + +class AdHelper { + static BannerAd? bannerAd; + static bool isBannerAdLoaded = false; + + static Future loadBannerAd(Function setStateCallback) async { + await dotenv.load(fileName: ".env"); + final adUnitId = dotenv.env['AD_UNIT_ID'] ?? ''; + + bannerAd = BannerAd( + adUnitId: adUnitId, // Replace with actual ID + size: AdSize.banner, + request: AdRequest(), + listener: BannerAdListener( + onAdLoaded: (ad) { + setStateCallback(() { + isBannerAdLoaded = true; + }); + }, + onAdFailedToLoad: (ad, error) { + print('Banner Ad failed to load: $error'); + isBannerAdLoaded = false; + ad.dispose(); + }, + ), + ); + + bannerAd?.load(); + } + + static void disposeAd() { + bannerAd?.dispose(); + bannerAd = null; + isBannerAdLoaded = false; + } +} diff --git a/covas_mobile/lib/main.dart b/covas_mobile/lib/main.dart index 25fc343..87b78d0 100644 --- a/covas_mobile/lib/main.dart +++ b/covas_mobile/lib/main.dart @@ -1,8 +1,11 @@ import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:http/http.dart' as http; - +import 'classes/ad_helper.dart'; import 'dart:convert'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:google_mobile_ads/google_mobile_ads.dart'; + import 'dart:io'; //import 'MyHomePage.dart'; @@ -14,7 +17,9 @@ import 'classes/alert.dart'; import 'variable/globals.dart' as globals; import 'package:permission_handler/permission_handler.dart'; -void main() { +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await MobileAds.instance.initialize(); runApp(MyApp()); } @@ -128,9 +133,17 @@ class _LoginDemoState extends State with ShowAlertDialog { @override void initState() { + super.initState(); + AdHelper.loadBannerAd(setState); + _checkLocationPermission(); start(); - super.initState(); + } + + @override + void dispose() { + AdHelper.disposeAd(); // Dispose of ad when the widget is removed + super.dispose(); } Future _checkLocationPermission() async { @@ -252,7 +265,13 @@ class _LoginDemoState extends State with ShowAlertDialog { onTap: () { Navigator.push( context, MaterialPageRoute(builder: (_) => AddProfile())); - }) + }), + if (AdHelper.isBannerAdLoaded) + SizedBox( + height: AdHelper.bannerAd!.size.height.toDouble(), + width: AdHelper.bannerAd!.size.width.toDouble(), + child: AdWidget(ad: AdHelper.bannerAd!), + ), ], ), ), diff --git a/covas_mobile/lib/pages/EditSettings.dart b/covas_mobile/lib/pages/EditSettings.dart index 8ce10e3..e9c25ce 100644 --- a/covas_mobile/lib/pages/EditSettings.dart +++ b/covas_mobile/lib/pages/EditSettings.dart @@ -125,7 +125,7 @@ class _EditProfileState extends State child: TextButton( onPressed: () {}, child: Text( - 'Mettre à jour les paramètres', + 'Mettre à jour', style: TextStyle(color: Colors.white, fontSize: 25), ), ), diff --git a/covas_mobile/macos/Flutter/GeneratedPluginRegistrant.swift b/covas_mobile/macos/Flutter/GeneratedPluginRegistrant.swift index 32ef7bb..3f99c38 100644 --- a/covas_mobile/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/covas_mobile/macos/Flutter/GeneratedPluginRegistrant.swift @@ -10,6 +10,7 @@ import geolocator_apple import path_provider_foundation import shared_preferences_foundation import url_launcher_macos +import webview_flutter_wkwebview func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) @@ -17,4 +18,5 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) + WebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "WebViewFlutterPlugin")) } diff --git a/covas_mobile/pubspec.lock b/covas_mobile/pubspec.lock index 8440d75..86ac378 100644 --- a/covas_mobile/pubspec.lock +++ b/covas_mobile/pubspec.lock @@ -304,6 +304,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.3" + google_mobile_ads: + dependency: "direct main" + description: + name: google_mobile_ads + sha256: "0d4a3744b5e8ed1b8be6a1b452d309f811688855a497c6113fc4400f922db603" + url: "https://pub.dev" + source: hosted + version: "5.3.1" http: dependency: "direct main" description: @@ -877,6 +885,38 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + webview_flutter: + dependency: transitive + description: + name: webview_flutter + sha256: "889a0a678e7c793c308c68739996227c9661590605e70b1f6cf6b9a6634f7aec" + url: "https://pub.dev" + source: hosted + version: "4.10.0" + webview_flutter_android: + dependency: transitive + description: + name: webview_flutter_android + sha256: "512c26ccc5b8a571fd5d13ec994b7509f142ff6faf85835e243dde3538fdc713" + url: "https://pub.dev" + source: hosted + version: "4.3.2" + webview_flutter_platform_interface: + dependency: transitive + description: + name: webview_flutter_platform_interface + sha256: d937581d6e558908d7ae3dc1989c4f87b786891ab47bb9df7de548a151779d8d + url: "https://pub.dev" + source: hosted + version: "2.10.0" + webview_flutter_wkwebview: + dependency: transitive + description: + name: webview_flutter_wkwebview + sha256: "7310de7efa4e6df8b3d2ff14aef3f290bc00b43363f2d0028845e6de46507fc9" + url: "https://pub.dev" + source: hosted + version: "3.18.1" xdg_directories: dependency: transitive description: diff --git a/covas_mobile/pubspec.yaml b/covas_mobile/pubspec.yaml index 91f4711..a8ac907 100644 --- a/covas_mobile/pubspec.yaml +++ b/covas_mobile/pubspec.yaml @@ -50,6 +50,7 @@ dependencies: permission_handler: ^11.3.1 url_launcher: ^6.3.1 mapbox_gl: ^0.16.0 + google_mobile_ads: ^5.3.1 dev_dependencies: flutter_test: -- 2.47.2 From 729e0ce1ca497ec2aa3529948c230789c15813c4 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Wed, 19 Feb 2025 23:03:12 +0100 Subject: [PATCH 2/5] use many pub in different page --- covas_mobile/lib/classes/ad_helper.dart | 23 +++++------------- covas_mobile/lib/main.dart | 30 ++++++++++++------------ covas_mobile/lib/pages/ListItemMenu.dart | 21 ++++++++++++++++- 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/covas_mobile/lib/classes/ad_helper.dart b/covas_mobile/lib/classes/ad_helper.dart index 92ac812..61bd66c 100644 --- a/covas_mobile/lib/classes/ad_helper.dart +++ b/covas_mobile/lib/classes/ad_helper.dart @@ -2,37 +2,26 @@ import 'package:google_mobile_ads/google_mobile_ads.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; class AdHelper { - static BannerAd? bannerAd; - static bool isBannerAdLoaded = false; - - static Future loadBannerAd(Function setStateCallback) async { + static Future createBannerAd(Function setStateCallback) async { await dotenv.load(fileName: ".env"); final adUnitId = dotenv.env['AD_UNIT_ID'] ?? ''; - bannerAd = BannerAd( - adUnitId: adUnitId, // Replace with actual ID + BannerAd bannerAd = BannerAd( + adUnitId: adUnitId, size: AdSize.banner, request: AdRequest(), listener: BannerAdListener( onAdLoaded: (ad) { - setStateCallback(() { - isBannerAdLoaded = true; - }); + setStateCallback(() {}); }, onAdFailedToLoad: (ad, error) { print('Banner Ad failed to load: $error'); - isBannerAdLoaded = false; ad.dispose(); }, ), ); - bannerAd?.load(); - } - - static void disposeAd() { - bannerAd?.dispose(); - bannerAd = null; - isBannerAdLoaded = false; + bannerAd.load(); + return bannerAd; } } diff --git a/covas_mobile/lib/main.dart b/covas_mobile/lib/main.dart index 87b78d0..1d4665a 100644 --- a/covas_mobile/lib/main.dart +++ b/covas_mobile/lib/main.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:http/http.dart' as http; -import 'classes/ad_helper.dart'; import 'dart:convert'; -import 'package:flutter_dotenv/flutter_dotenv.dart'; + +import 'classes/ad_helper.dart'; import 'package:google_mobile_ads/google_mobile_ads.dart'; import 'dart:io'; @@ -39,6 +39,7 @@ class LoginDemo extends StatefulWidget { } class _LoginDemoState extends State with ShowAlertDialog { + BannerAd? _bannerAd; TextEditingController inputPseudo = TextEditingController(); TextEditingController inputPassword = TextEditingController(); Future _login(BuildContext context) async { @@ -134,18 +135,16 @@ class _LoginDemoState extends State with ShowAlertDialog { @override void initState() { super.initState(); - AdHelper.loadBannerAd(setState); + AdHelper.createBannerAd(() => setState(() {})).then((ad) { + setState(() { + _bannerAd = ad; + }); + }); _checkLocationPermission(); start(); } - @override - void dispose() { - AdHelper.disposeAd(); // Dispose of ad when the widget is removed - super.dispose(); - } - Future _checkLocationPermission() async { PermissionStatus status = await Permission.location.status; @@ -196,6 +195,13 @@ class _LoginDemoState extends State with ShowAlertDialog { body: SingleChildScrollView( child: Column( children: [ + _bannerAd == null + ? SizedBox.shrink() + : SizedBox( + height: _bannerAd!.size.height.toDouble(), + width: _bannerAd!.size.width.toDouble(), + child: AdWidget(ad: _bannerAd!), + ), Padding( padding: const EdgeInsets.only(top: 60.0), child: Center( @@ -266,12 +272,6 @@ class _LoginDemoState extends State with ShowAlertDialog { Navigator.push( context, MaterialPageRoute(builder: (_) => AddProfile())); }), - if (AdHelper.isBannerAdLoaded) - SizedBox( - height: AdHelper.bannerAd!.size.height.toDouble(), - width: AdHelper.bannerAd!.size.width.toDouble(), - child: AdWidget(ad: AdHelper.bannerAd!), - ), ], ), ), diff --git a/covas_mobile/lib/pages/ListItemMenu.dart b/covas_mobile/lib/pages/ListItemMenu.dart index b4105b8..58f1b1f 100644 --- a/covas_mobile/lib/pages/ListItemMenu.dart +++ b/covas_mobile/lib/pages/ListItemMenu.dart @@ -16,7 +16,12 @@ import 'package:permission_handler/permission_handler.dart'; import "Camera.dart"; import 'package:camera/camera.dart'; -void main() { +import '../classes/ad_helper.dart'; +import 'package:google_mobile_ads/google_mobile_ads.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await MobileAds.instance.initialize(); initializeDateFormatting("fr_FR", null).then((_) => runApp(const MyApp())); } @@ -40,6 +45,8 @@ class ListItemMenu extends StatefulWidget { } class _MyHomePageState extends State { + BannerAd? _bannerAd; + Future> postsFuture = getPosts(); List filteredPosts = []; String geographicalZone = ''; @@ -138,6 +145,11 @@ class _MyHomePageState extends State { @override void initState() { super.initState(); + AdHelper.createBannerAd(() => setState(() {})).then((ad) { + setState(() { + _bannerAd = ad; + }); + }); // Initialize data fetch when the page loads _getCurrentLocation(); } @@ -543,6 +555,13 @@ class _MyHomePageState extends State { drawer: MyDrawer(), body: Column( children: [ + _bannerAd == null + ? SizedBox.shrink() + : SizedBox( + height: _bannerAd!.size.height.toDouble(), + width: _bannerAd!.size.width.toDouble(), + child: AdWidget(ad: _bannerAd!), + ), if (showInputSearch) _buildSearchField( controller: inputItem, -- 2.47.2 From 47c014cddacca93db51a03aab56877e524e0ff28 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Wed, 19 Feb 2025 23:24:21 +0100 Subject: [PATCH 3/5] add pub in update event --- covas_mobile/lib/pages/ItemMenu.dart | 20 +++++++++++++++++- covas_mobile/lib/pages/UpdateEventImage.dart | 22 ++++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/covas_mobile/lib/pages/ItemMenu.dart b/covas_mobile/lib/pages/ItemMenu.dart index 3e40bb4..db6ae9c 100644 --- a/covas_mobile/lib/pages/ItemMenu.dart +++ b/covas_mobile/lib/pages/ItemMenu.dart @@ -21,7 +21,12 @@ import 'MapboxPages.dart'; import 'ListItemByOrganizers.dart'; import 'EditEvent.dart'; -void main() { +import '../classes/ad_helper.dart'; +import 'package:google_mobile_ads/google_mobile_ads.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await MobileAds.instance.initialize(); initializeDateFormatting("fr_FR", null).then((_) => (const MyApp())); } @@ -69,6 +74,8 @@ class ItemMenu extends StatefulWidget { } class _ItemMenuState extends State with ShowAlertDialog { + BannerAd? _bannerAd; + String listUser = ""; String eventName = ""; String eventStartDate = ""; @@ -84,6 +91,11 @@ class _ItemMenuState extends State with ShowAlertDialog { @override void initState() { super.initState(); + AdHelper.createBannerAd(() => setState(() {})).then((ad) { + setState(() { + _bannerAd = ad; + }); + }); _getEventInfos(); } @@ -174,6 +186,12 @@ class _ItemMenuState extends State with ShowAlertDialog { body: SingleChildScrollView( child: Column( children: [ + _bannerAd == null + ? SizedBox.shrink() + : SizedBox( + height: _bannerAd!.size.height.toDouble(), + width: _bannerAd!.size.width.toDouble(), + child: AdWidget(ad: _bannerAd!)), Padding( padding: const EdgeInsets.only(top: 60.0), child: Image.network( diff --git a/covas_mobile/lib/pages/UpdateEventImage.dart b/covas_mobile/lib/pages/UpdateEventImage.dart index f95ddb4..30823c5 100644 --- a/covas_mobile/lib/pages/UpdateEventImage.dart +++ b/covas_mobile/lib/pages/UpdateEventImage.dart @@ -16,7 +16,12 @@ import '../classes/eventAdded.dart'; import '../variable/globals.dart' as globals; -void main() { +import '../classes/ad_helper.dart'; +import 'package:google_mobile_ads/google_mobile_ads.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await MobileAds.instance.initialize(); runApp(MyApp()); } @@ -45,6 +50,8 @@ class UpdateeventImage extends StatefulWidget { class _UpdateeventImageState extends State with ShowAlertDialog, ShowEventDialog { + BannerAd? _bannerAd; + TextEditingController inputName = TextEditingController(); TextEditingController inputDate = TextEditingController(); @@ -308,8 +315,13 @@ class _UpdateeventImageState extends State @override void initState() { - start(); super.initState(); + AdHelper.createBannerAd(() => setState(() {})).then((ad) { + setState(() { + _bannerAd = ad; + }); + }); + start(); } final _formKey = GlobalKey(); @@ -426,6 +438,12 @@ class _UpdateeventImageState extends State child: SingleChildScrollView( child: Column( children: [ + _bannerAd == null + ? SizedBox.shrink() + : SizedBox( + height: _bannerAd!.size.height.toDouble(), + width: _bannerAd!.size.width.toDouble(), + child: AdWidget(ad: _bannerAd!)), Padding( padding: const EdgeInsets.only(top: 60.0), child: Center( -- 2.47.2 From 38e99085332a848a1cbaeb6a578a89aa1e0ace01 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Wed, 19 Feb 2025 23:32:31 +0100 Subject: [PATCH 4/5] add pub --- covas_mobile/lib/pages/AddProfile.dart | 20 +++++++++++++++- .../lib/pages/DisplayPictureScreen.dart | 24 ++++++++++++++++--- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/covas_mobile/lib/pages/AddProfile.dart b/covas_mobile/lib/pages/AddProfile.dart index 96d374b..f97fae4 100644 --- a/covas_mobile/lib/pages/AddProfile.dart +++ b/covas_mobile/lib/pages/AddProfile.dart @@ -11,7 +11,12 @@ import '../classes/alert.dart'; import '../variable/globals.dart' as globals; -void main() { +import '../classes/ad_helper.dart'; +import 'package:google_mobile_ads/google_mobile_ads.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await MobileAds.instance.initialize(); runApp(MyApp()); } @@ -33,6 +38,8 @@ class AddProfile extends StatefulWidget { } class _AddProfileState extends State with ShowAlertDialog { + BannerAd? _bannerAd; + TextEditingController inputUserName = TextEditingController(); TextEditingController inputName = TextEditingController(); @@ -133,6 +140,11 @@ class _AddProfileState extends State with ShowAlertDialog { @override void initState() { super.initState(); + AdHelper.createBannerAd(() => setState(() {})).then((ad) { + setState(() { + _bannerAd = ad; + }); + }); } final _formKey = GlobalKey(); @@ -154,6 +166,12 @@ class _AddProfileState extends State with ShowAlertDialog { child: SingleChildScrollView( child: Column( children: [ + _bannerAd == null + ? SizedBox.shrink() + : SizedBox( + height: _bannerAd!.size.height.toDouble(), + width: _bannerAd!.size.width.toDouble(), + child: AdWidget(ad: _bannerAd!)), Padding( padding: const EdgeInsets.only( left: 15.0, right: 15.0, top: 15, bottom: 0), diff --git a/covas_mobile/lib/pages/DisplayPictureScreen.dart b/covas_mobile/lib/pages/DisplayPictureScreen.dart index 41c86fd..73711df 100644 --- a/covas_mobile/lib/pages/DisplayPictureScreen.dart +++ b/covas_mobile/lib/pages/DisplayPictureScreen.dart @@ -14,7 +14,12 @@ import 'dart:convert'; import '../variable/globals.dart' as globals; import '../classes/MyDrawer.dart'; -void main() { +import '../classes/ad_helper.dart'; +import 'package:google_mobile_ads/google_mobile_ads.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await MobileAds.instance.initialize(); runApp(MyApp()); } @@ -56,9 +61,18 @@ class DisplayPictureScreen extends StatefulWidget { // A widget that displays the picture taken by the user. class DisplayPictureScreenState extends State with ShowDescImageAdd, ShowAlertDialog, TickerProviderStateMixin { + BannerAd? _bannerAd; + late AnimationController controller; @override void initState() { + super.initState(); + AdHelper.createBannerAd(() => setState(() {})).then((ad) { + setState(() { + _bannerAd = ad; + }); + }); + controller = AnimationController( /// [AnimationController]s can be created with `vsync: this` because of /// [TickerProviderStateMixin]. @@ -68,7 +82,6 @@ class DisplayPictureScreenState extends State setState(() {}); }); controller.repeat(reverse: false); - super.initState(); _getEventInfosFromImage(); } @@ -160,12 +173,17 @@ class DisplayPictureScreenState extends State // The image is stored as a file on the device. Use the `Image.file` // constructor with the given path to display the image. drawer: MyDrawer(), - body: Padding( padding: const EdgeInsets.all(20.0), child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ + _bannerAd == null + ? SizedBox.shrink() + : SizedBox( + height: _bannerAd!.size.height.toDouble(), + width: _bannerAd!.size.width.toDouble(), + child: AdWidget(ad: _bannerAd!)), Text( 'Analyse de l\'image en cours', style: Theme.of(context).textTheme.titleLarge, -- 2.47.2 From c31e275dae1aa0e81d2a0895be1f834332b7f4a2 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Sun, 23 Feb 2025 22:18:01 +0100 Subject: [PATCH 5/5] add pub --- covas_mobile/lib/pages/EditEvent.dart | 332 +++++++++++------------ covas_mobile/lib/pages/EditProfile.dart | 19 +- covas_mobile/lib/pages/EditSettings.dart | 19 +- 3 files changed, 199 insertions(+), 171 deletions(-) diff --git a/covas_mobile/lib/pages/EditEvent.dart b/covas_mobile/lib/pages/EditEvent.dart index 8beb2e5..69d7691 100644 --- a/covas_mobile/lib/pages/EditEvent.dart +++ b/covas_mobile/lib/pages/EditEvent.dart @@ -22,7 +22,12 @@ import '../classes/eventAdded.dart'; import '../variable/globals.dart' as globals; -void main() { +import '../classes/ad_helper.dart'; +import 'package:google_mobile_ads/google_mobile_ads.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await MobileAds.instance.initialize(); runApp(MyApp()); } @@ -54,6 +59,7 @@ class EditEvent extends StatefulWidget { class _EditEventState extends State with ShowAlertDialog, ShowEventDialog { + BannerAd? _bannerAd; TextEditingController inputName = TextEditingController(); TextEditingController inputDate = TextEditingController(); @@ -159,177 +165,161 @@ class _EditEventState extends State } Future _updateEvent(BuildContext context) async { - var name = inputName.text; - var place = inputGeo.text; - var description = inputDesc.text; - List tags = List.from(_stringTagController.getTags as List); - List organizers = - List.from(_stringOrgaController.getTags as List); - - var startDateFormat = formatDate(startDatepicker.text); - //DateTime startDateCompare = DateTime.parse(startDateFormat); - DateTime dateNow = DateTime.now(); - var endDateFormat = formatDate(endDatepicker.text); - var startDate = - "${startDateFormat}T${startTimepicker.text.replaceAll('-', ':')}"; - var endDate = "${endDateFormat}T${endTimepicker.text.replaceAll('-', ':')}"; - DateTime startDateCompare = DateTime.parse(startDate); - if (startDateCompare.isAfter(dateNow)) { - SharedPreferences prefs = await SharedPreferences.getInstance(); - var accessToken = prefs.getString("access_token") ?? ""; - - if (accessToken.isNotEmpty) { - try { - await dotenv.load(); - final ApiTokenGoogle = dotenv.env['PLACE_API_KEY'] ?? ''; - // Searchbox API for geocoding the place (No session token) - final searchboxUrl = Uri.parse( - 'https://maps.googleapis.com/maps/api/place/textsearch/json?query=${place}&key=${ApiTokenGoogle}'); - - // Perform the request - final searchboxResponse = await http.get(searchboxUrl); - - if (searchboxResponse.statusCode == 200) { - final data = json.decode(searchboxResponse.body); - print("data : ${data}"); - - if (data['results'].isNotEmpty) { - place = data['results'][0]['formatted_address']; - final coordinates = data['results'][0]['geometry']['location']; - final longitude = coordinates["lng"]; // Longitude - final latitude = coordinates["lat"]; // Latitude - var urlGet = Uri.parse( - "${globals.api}/events/search?item=${name}&date_event=${startDate}&min_lat=$latitude&max_lat=$latitude" - "&min_lon=$longitude&max_lon=$longitude"); - - var responseGet = await http.get(urlGet, headers: { - HttpHeaders.cookieHeader: 'access_token=${accessToken}' - }); - if (responseGet.statusCode == 200) { - var events = jsonDecode(utf8.decode(responseGet.bodyBytes)); - if (events.length > 0) { - if (events[0]["id"] != widget.events!.id) { - showAlertDialog( - context, "Info evenement", "Evenement deja existant"); - } - - return; - } - } - - if (widget.imgPath.isNotEmpty) { - final params = { - 'expiration': '15552000', - 'key': dotenv.env["IMGBB_API_KEY"], - }; - print("Post Img"); - final urlPost = Uri.parse('https://api.imgbb.com/1/upload') - .replace(queryParameters: params); - File image = File(widget.imgPath); - Uint8List _bytes = await image.readAsBytes(); - String _base64String = base64.encode(_bytes); - - final req = http.MultipartRequest('POST', urlPost) - ..fields['image'] = _base64String; - - final stream = await req.send(); - final res = await http.Response.fromStream(stream); - - final status = res.statusCode; - print("code status imgbb ${status}"); - if (status != 200) { - showAlertDialog(context, "Erreur image", "Image non posté"); - return; - } - var body = json.decode(utf8.decode(res.bodyBytes)); - imgUrl = body["data"]["url"]; - } - var urlPut = - Uri.parse("${globals.api}/events/${widget.events!.id}"); - var responsePut = await http.put(urlPut, - headers: { - HttpHeaders.cookieHeader: 'access_token=${accessToken}', - HttpHeaders.acceptHeader: - 'application/json, text/plain, */*', - HttpHeaders.contentTypeHeader: 'application/json' - }, - body: jsonEncode({ - 'name': name, - 'place': place, - 'start_date': startDate, - 'end_date': endDate, - 'organizers': organizers, - 'latitude': latitude, - 'longitude': longitude, - 'description': description, - "imgUrl": imgUrl, - "tags": tags - })); - print(responsePut.statusCode); - if ((responsePut.statusCode == 200) || - (responsePut.statusCode == 201)) { - showEventDialog(context, "Evenement ${name} modifie"); - } else { - var text = ""; - switch (responsePut.statusCode) { - case 400: - { - text = "Requête mal construite"; - } - break; - case 406: - { - text = "Mot de passe incorrect"; - } - break; - case 404: - { - text = "Utilisateur inconnu"; - } - break; - case 403: - { - text = "Utilisateur desactive"; - } - break; - case 410: - { - text = "Token invalide"; - } - break; - case 500: - { - text = "Probleme interne du serveur"; - } - break; - default: - { - text = "Probleme d'authentification inconnu"; - } - break; - } - showAlertDialog(context, "Erreur serveur", text); - } - } else { - showAlertDialog( - context, "Erreur serveur", "Aucune donnée geographique"); - } - } else { - showAlertDialog(context, "Erreur serveur", "Mapbox non accessible"); - } - } catch (e) { - showAlertDialog(context, "Erreur serveur", "${e}"); - } - } else { - showAlertDialog(context, "Erreur utilisateur", "Champ vide"); - } - } else { - showAlertDialog(context, "Erreur evenement", "Evenement non futur"); + if (!_isEventInFuture()) { + _showErrorDialog(context, "Erreur evenement", "Evenement non futur"); + return; } + + final accessToken = await _getAccessToken(); + if (accessToken.isEmpty) { + _showErrorDialog(context, "Erreur utilisateur", "Champ vide"); + return; + } + + try { + await dotenv.load(); + final geolocation = await _fetchGeolocation(); + if (geolocation == null) { + _showErrorDialog( + context, "Erreur serveur", "Aucune donnée geographique"); + return; + } + + if (await _isDuplicateEvent(accessToken, geolocation)) { + _showErrorDialog(context, "Info evenement", "Evenement deja existant"); + return; + } + + if (widget.imgPath.isNotEmpty) { + imgUrl = await _uploadImage(widget.imgPath); + if (imgUrl.isEmpty) { + _showErrorDialog(context, "Erreur image", "Image non postée"); + return; + } + } + + await _updateEventData(accessToken, geolocation); + showEventDialog(context, "Evenement ${inputName.text} modifie"); + } catch (e) { + _showErrorDialog(context, "Erreur serveur", "$e"); + } + } + + bool _isEventInFuture() { + DateTime startDateCompare = DateTime.parse( + "${formatDate(startDatepicker.text)}T${startTimepicker.text.replaceAll('-', ':')}"); + return startDateCompare.isAfter(DateTime.now()); + } + + Future _getAccessToken() async { + final prefs = await SharedPreferences.getInstance(); + return prefs.getString("access_token") ?? ""; + } + + Future?> _fetchGeolocation() async { + final apiKey = dotenv.env['PLACE_API_KEY'] ?? ''; + final response = await http.get(Uri.parse( + 'https://maps.googleapis.com/maps/api/place/textsearch/json?query=${inputGeo.text}&key=$apiKey')); + + if (response.statusCode == 200) { + final data = json.decode(response.body); + if (data['results'].isNotEmpty) { + return data['results'][0]['geometry']['location']; + } + } + return null; + } + + Future _isDuplicateEvent( + String accessToken, Map location) async { + final url = Uri.parse( + "${globals.api}/events/search?item=${inputName.text}&date_event=${formatDate(startDatepicker.text)}" + "&min_lat=${location['lat']}&max_lat=${location['lat']}" + "&min_lon=${location['lng']}&max_lon=${location['lng']}"); + + final response = await http.get(url, + headers: {HttpHeaders.cookieHeader: 'access_token=$accessToken'}); + + if (response.statusCode == 200) { + final events = jsonDecode(utf8.decode(response.bodyBytes)); + return events.isNotEmpty && events[0]["id"] != widget.events!.id; + } + return false; + } + + Future _uploadImage(String imagePath) async { + final params = { + 'expiration': '15552000', + 'key': dotenv.env["IMGBB_API_KEY"] + }; + final url = Uri.parse('https://api.imgbb.com/1/upload') + .replace(queryParameters: params); + + final image = File(imagePath); + final req = http.MultipartRequest('POST', url) + ..fields['image'] = base64.encode(await image.readAsBytes()); + + final response = await http.Response.fromStream(await req.send()); + return response.statusCode == 200 + ? json.decode(response.body)["data"]["url"] + : ""; + } + + Future _updateEventData( + String accessToken, Map location) async { + final url = Uri.parse("${globals.api}/events/${widget.events!.id}"); + final response = await http.put(url, + headers: { + HttpHeaders.cookieHeader: 'access_token=$accessToken', + HttpHeaders.acceptHeader: 'application/json, text/plain, */*', + HttpHeaders.contentTypeHeader: 'application/json' + }, + body: jsonEncode({ + 'name': inputName.text, + 'place': inputGeo.text, + 'start_date': + "${formatDate(startDatepicker.text)}T${startTimepicker.text.replaceAll('-', ':')}", + 'end_date': + "${formatDate(endDatepicker.text)}T${endTimepicker.text.replaceAll('-', ':')}", + 'organizers': + List.from(_stringOrgaController.getTags as List), + 'latitude': location['lat'], + 'longitude': location['lng'], + 'description': inputDesc.text, + "imgUrl": imgUrl, + "tags": List.from(_stringTagController.getTags as List) + })); + + if (response.statusCode != 200 && response.statusCode != 201) { + _handleErrorResponse(context, response.statusCode); + } + } + + void _handleErrorResponse(BuildContext context, int statusCode) { + final messages = { + 400: "Requête mal construite", + 406: "Mot de passe incorrect", + 404: "Utilisateur inconnu", + 403: "Utilisateur désactivé", + 410: "Token invalide", + 500: "Problème interne du serveur" + }; + _showErrorDialog(context, "Erreur serveur", + messages[statusCode] ?? "Problème d'authentification inconnu"); + } + + void _showErrorDialog(BuildContext context, String title, String message) { + showAlertDialog(context, title, message); } @override void initState() { + super.initState(); + AdHelper.createBannerAd(() => setState(() {})).then((ad) { + setState(() { + _bannerAd = ad; + }); + }); inputName.text = widget.events!.name ?? ""; startDatepicker.text = DateFormat("dd/MM/yyyy") .format(DateTime.parse( @@ -353,7 +343,6 @@ class _EditEventState extends State inputDesc.text = widget.events!.description ?? ""; initialTags = List.from(widget.events!.tags as List); initialOrga = List.from(widget.events!.organizers as List); - super.initState(); } final _formKey = GlobalKey(); @@ -467,7 +456,6 @@ class _EditEventState extends State return Scaffold( backgroundColor: Colors.white, drawer: MyDrawer(), - appBar: AppBar( title: Text("Add or Update a event"), backgroundColor: Colors.blue, @@ -478,6 +466,12 @@ class _EditEventState extends State child: SingleChildScrollView( child: Column( children: [ + _bannerAd == null + ? SizedBox.shrink() + : SizedBox( + height: _bannerAd!.size.height.toDouble(), + width: _bannerAd!.size.width.toDouble(), + child: AdWidget(ad: _bannerAd!)), if (widget.imgPath.isNotEmpty) Padding( padding: const EdgeInsets.only(top: 60.0), diff --git a/covas_mobile/lib/pages/EditProfile.dart b/covas_mobile/lib/pages/EditProfile.dart index 805c5b7..50a9aee 100644 --- a/covas_mobile/lib/pages/EditProfile.dart +++ b/covas_mobile/lib/pages/EditProfile.dart @@ -15,7 +15,12 @@ import '../classes/eventAdded.dart'; import '../variable/globals.dart' as globals; -void main() { +import '../classes/ad_helper.dart'; +import 'package:google_mobile_ads/google_mobile_ads.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await MobileAds.instance.initialize(); runApp(MyApp()); } @@ -38,6 +43,7 @@ class EditProfile extends StatefulWidget { class _EditProfileState extends State with ShowAlertDialog, ShowEventDialog { + BannerAd? _bannerAd; TextEditingController inputUserName = TextEditingController(); TextEditingController inputName = TextEditingController(); @@ -192,6 +198,11 @@ class _EditProfileState extends State @override void initState() { super.initState(); + AdHelper.createBannerAd(() => setState(() {})).then((ad) { + setState(() { + _bannerAd = ad; + }); + }); _getInfoProfile(); } @@ -215,6 +226,12 @@ class _EditProfileState extends State child: SingleChildScrollView( child: Column( children: [ + _bannerAd == null + ? SizedBox.shrink() + : SizedBox( + height: _bannerAd!.size.height.toDouble(), + width: _bannerAd!.size.width.toDouble(), + child: AdWidget(ad: _bannerAd!)), Padding( padding: const EdgeInsets.only( left: 15.0, right: 15.0, top: 15, bottom: 0), diff --git a/covas_mobile/lib/pages/EditSettings.dart b/covas_mobile/lib/pages/EditSettings.dart index e9c25ce..c79e6c2 100644 --- a/covas_mobile/lib/pages/EditSettings.dart +++ b/covas_mobile/lib/pages/EditSettings.dart @@ -10,7 +10,12 @@ import '../classes/MyDrawer.dart'; import '../classes/alert.dart'; import '../classes/eventAdded.dart'; -void main() { +import '../classes/ad_helper.dart'; +import 'package:google_mobile_ads/google_mobile_ads.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await MobileAds.instance.initialize(); runApp(MyApp()); } @@ -33,6 +38,7 @@ class EditSettings extends StatefulWidget { class _EditProfileState extends State with ShowAlertDialog, ShowEventDialog { + BannerAd? _bannerAd; TextEditingController inputUserName = TextEditingController(); int? kilometer; @@ -54,6 +60,11 @@ class _EditProfileState extends State @override void initState() { super.initState(); + AdHelper.createBannerAd(() => setState(() {})).then((ad) { + setState(() { + _bannerAd = ad; + }); + }); getParameter(); } @@ -71,6 +82,12 @@ class _EditProfileState extends State child: SingleChildScrollView( child: Column( children: [ + _bannerAd == null + ? SizedBox.shrink() + : SizedBox( + height: _bannerAd!.size.height.toDouble(), + width: _bannerAd!.size.width.toDouble(), + child: AdWidget(ad: _bannerAd!)), Padding( padding: const EdgeInsets.only( left: 15.0, -- 2.47.2