12 Commits

Author SHA1 Message Date
6c2324cb91 fix set settings 2025-09-07 20:51:27 +02:00
5ee053272e Merge pull request 'hotfix/fix-upgrade' (#50) from hotfix/fix-upgrade into main
Reviewed-on: #50
2025-09-05 21:32:28 +00:00
1bb2612de3 add initialOrga as vide 2025-09-05 23:09:20 +02:00
86f81ff009 add marker red 2025-09-04 18:11:12 +02:00
9989aebc32 add zoom after click 2025-09-04 17:26:00 +02:00
35fc1cfa25 add zoomfit 2025-09-04 09:04:24 +02:00
692d55858c add selectecmode 2025-09-02 23:18:46 +02:00
59b16e5131 fix lat lng 2025-09-02 23:05:49 +02:00
89c5e1aa6c fix set mapbox token 2025-09-02 16:32:50 +02:00
f4fb846855 fix login 2025-09-02 14:25:19 +02:00
9a9287bd20 fix permissions 2025-09-02 13:58:39 +02:00
70545052c2 Merge pull request 'feature/notification-date' (#49) from feature/notification-date into main
Reviewed-on: #49
2025-08-27 21:53:17 +00:00
5 changed files with 143 additions and 32 deletions

View File

@@ -1,5 +1,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application
android:label="covas_mobile_new"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
@@ -15,6 +18,7 @@
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:enableOnBackInvokedCallback="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user

View File

@@ -6,21 +6,28 @@ import 'pages/LoginDemo.dart';
import 'locale_provider.dart'; // <-- à adapter selon ton arborescence
import 'package:covas_mobile/gen_l10n/app_localizations.dart';
import 'classes/notification_service.dart';
import 'classes/auth_service.dart';
import 'pages/ListItemMenu.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await MobileAds.instance.initialize();
await NotificationService.initialize();
final AuthService _authService = AuthService();
final loggedIn = await _authService.isLoggedIn();
runApp(
ChangeNotifierProvider(
create: (_) => LocaleProvider(),
child: MyApp(),
child: MyApp(isLoggedIn: loggedIn),
),
);
}
class MyApp extends StatelessWidget {
final bool isLoggedIn;
const MyApp({Key? key, required this.isLoggedIn}) : super(key: key);
@override
Widget build(BuildContext context) {
final localeProvider = Provider.of<LocaleProvider>(
@@ -30,7 +37,7 @@ class MyApp extends StatelessWidget {
locale: localeProvider.locale, // <-- utilise la locale courante
supportedLocales: L10n.all,
localizationsDelegates: AppLocalizations.localizationsDelegates,
home: LoginDemo(),
home: isLoggedIn ? ListItemMenu() : LoginDemo(),
);
}
}

View File

@@ -380,8 +380,8 @@ class _EditEventState extends State<EditEvent>
imgUrl = widget.events!.imgUrl ?? "";
inputDesc.text = widget.events!.description ?? "";
initialTags = List<String>.from(widget.events!.tags as List);
initialOrga = List<String>.from(widget.events!.organizers as List);
initialTags = List<String>.from((widget.events?.tags as List?) ?? []);
initialOrga = List<String>.from((widget.events?.organizers as List?) ?? []);
}
final _formKey = GlobalKey<FormState>();

View File

@@ -48,17 +48,18 @@ class _EditProfileState extends State<EditSettings>
final AuthService _authService = AuthService();
TextEditingController inputUserName = TextEditingController();
int? kilometer;
int? kilometer = 50;
Future<void> getParameter() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
var kilometer = prefs.getDouble("kilometer")?.toInt() ?? null;
kilometer = prefs.getDouble("kilometer")?.toInt() ?? 50;
});
}
Future<void> setParameter() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
print("kilometer : ${kilometer}");
if (kilometer != null) {
prefs.setDouble("kilometer", kilometer?.toDouble() ?? 50);
showAlertDialog(
@@ -115,8 +116,7 @@ class _EditProfileState extends State<EditSettings>
AppLocalizations.of(context)?.define_kilometer ??
'Define kilometer',
),
value:
kilometer, // Set the initial selected value here, or leave as `null` if unselected.
value: kilometer,
items: [
DropdownMenuItem(
value: 5,
@@ -155,7 +155,7 @@ class _EditProfileState extends State<EditSettings>
color: Colors.blue,
borderRadius: BorderRadius.circular(20)),
child: TextButton(
onPressed: () {},
onPressed: setParameter,
child: Text(
AppLocalizations.of(context)?.update ?? "Update",
style: TextStyle(color: Colors.white, fontSize: 25),

View File

@@ -105,6 +105,11 @@ class _MapboxPagesState extends State<MapboxPages> with ShowAlertDialog {
}
Future<void> _getUserLocation() async {
await dotenv.load(fileName: ".env");
// Set the access token globally
mapbox.MapboxOptions.setAccessToken(
dotenv.env['MAPBOX_ACCESS_TOKEN'] ?? '');
try {
bool serviceEnabled = await geo.Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) return;
@@ -121,7 +126,7 @@ class _MapboxPagesState extends State<MapboxPages> with ShowAlertDialog {
setState(() {
userPosition = mapbox.Point(
coordinates:
mapbox.Position(position.latitude, position.longitude));
mapbox.Position(position.longitude, position.latitude));
isUserPositionInitialized = true;
});
@@ -134,21 +139,72 @@ class _MapboxPagesState extends State<MapboxPages> with ShowAlertDialog {
Future<void> _fetchRoute(
mapbox.Point origin, mapbox.Point destination, String mode) async {
final url = Uri.parse(
'https://api.mapbox.com/directions/v5/mapbox/$mode/${origin.coordinates.lng},${origin.coordinates.lat};${destination.coordinates.lng},${destination.coordinates.lat}?geometries=geojson&access_token=${dotenv.env['MAPBOX_ACCESS_TOKEN']}',
'https://api.mapbox.com/directions/v5/mapbox/$mode/'
'${origin.coordinates.lng},${origin.coordinates.lat};'
'${destination.coordinates.lng},${destination.coordinates.lat}'
'?geometries=geojson&access_token=${dotenv.env['MAPBOX_ACCESS_TOKEN']}',
);
final response = await http.get(url);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
final geometry = data['routes'][0]['geometry']['coordinates'];
setState(() {
routeCoordinates = (geometry as List)
.map<List<double>>((coord) => [coord[0], coord[1]])
.toList();
});
// Vérifie si 'routes' existe et contient au moins 1 élément
if (data['routes'] != null && (data['routes'] as List).isNotEmpty) {
final geometry = data['routes'][0]['geometry']['coordinates'];
setState(() {
routeCoordinates = (geometry as List)
.map<List<double>>((coord) => [coord[0], coord[1]])
.toList();
});
} else {
debugPrint("⚠️ Aucune route trouvée entre ${origin} et $destination.");
// Optionnel : afficher un snackbar/toast à lutilisateur
}
} else {
debugPrint("❌ Erreur API Mapbox: ${response.statusCode}");
}
}
Future<void> _zoomToFitRoute(List<List<double>> coordinates) async {
if (mapboxMap == null || coordinates.isEmpty) return;
double minLat = coordinates.first[1];
double maxLat = coordinates.first[1];
double minLng = coordinates.first[0];
double maxLng = coordinates.first[0];
for (var coord in coordinates) {
if (coord[1] < minLat) minLat = coord[1];
if (coord[1] > maxLat) maxLat = coord[1];
if (coord[0] < minLng) minLng = coord[0];
if (coord[0] > maxLng) maxLng = coord[0];
}
final bounds = mapbox.CoordinateBounds(
southwest: mapbox.Point(coordinates: mapbox.Position(minLng, minLat)),
northeast: mapbox.Point(coordinates: mapbox.Position(maxLng, maxLat)),
infiniteBounds: true);
// Calculer une CameraOptions automatiquement à partir des bounds
final cameraOptions = await mapboxMap!.cameraForCoordinateBounds(
bounds,
mapbox.MbxEdgeInsets(
top: 50, left: 50, right: 50, bottom: 50), // marges
0.0,
0.0,
null,
null);
// Appliquer la caméra avec animation
await mapboxMap!.flyTo(
cameraOptions,
mapbox.MapAnimationOptions(duration: 1000),
);
}
Future<void> _drawRouteAndMarkers() async {
if (mapboxMap == null || !isUserPositionInitialized) return;
@@ -175,14 +231,12 @@ class _MapboxPagesState extends State<MapboxPages> with ShowAlertDialog {
iconSize: 0.4,
));
// Add event marker
// Ajoute directement la flèche rouge à la position de lévénement
final eventIcon = await _loadMarkerImage('images/marker-red.png');
await pointAnnotationManager!.create(mapbox.PointAnnotationOptions(
geometry: mapbox.Point(
coordinates: mapbox.Position(
destination.coordinates.lng, destination.coordinates.lat)),
geometry: mapbox.Point(coordinates: mapbox.Position(longitude, latitude)),
image: eventIcon,
iconSize: 0.4,
iconSize: 0.2,
));
// Fetch and draw route
@@ -196,6 +250,7 @@ class _MapboxPagesState extends State<MapboxPages> with ShowAlertDialog {
lineColor: Colors.blue.value,
lineWidth: 4.0,
));
await _zoomToFitRoute(routeCoordinates);
}
}
@@ -211,15 +266,60 @@ class _MapboxPagesState extends State<MapboxPages> with ShowAlertDialog {
drawer: MyDrawer(),
body: isLoading
? const Center(child: CircularProgressIndicator())
: mapbox.MapWidget(
onMapCreated: (controller) {
mapboxMap = controller;
},
cameraOptions: mapbox.CameraOptions(
center: mapbox.Point(
coordinates: mapbox.Position(longitude, latitude)),
zoom: 14.0,
),
: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text("Mode : "),
DropdownButton<String>(
value: selectedMode,
items: const [
DropdownMenuItem(
value: 'driving', child: Text("🚗 Voiture")),
DropdownMenuItem(
value: 'walking', child: Text("🚶 Marche")),
DropdownMenuItem(
value: 'cycling', child: Text("🚴 Vélo")),
],
onChanged: (value) {
if (value != null) {
setState(() {
selectedMode = value;
});
}
},
),
],
),
Expanded(
child: mapbox.MapWidget(
onMapCreated: (controller) async {
mapboxMap = controller;
// Crée un manager si nécessaire
pointAnnotationManager ??= await mapboxMap!.annotations
.createPointAnnotationManager();
// Ajoute directement la flèche rouge à la position de lévénement
final eventIcon =
await _loadMarkerImage('images/marker-red.png');
await pointAnnotationManager!
.create(mapbox.PointAnnotationOptions(
geometry: mapbox.Point(
coordinates: mapbox.Position(longitude, latitude)),
image: eventIcon,
iconSize: 0.2,
));
},
cameraOptions: mapbox.CameraOptions(
center: mapbox.Point(
coordinates: mapbox.Position(longitude, latitude)),
zoom: 14.0,
),
),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: _drawRouteAndMarkers,