diff --git a/lib/src/image_and_location_data.dart b/lib/src/image_and_location_data.dart index a092f4e..de4d415 100644 --- a/lib/src/image_and_location_data.dart +++ b/lib/src/image_and_location_data.dart @@ -1,5 +1,8 @@ +import 'dart:typed_data'; + class ImageAndLocationData { final String? imagePath; + final Uint8List? imageBytes; final LocationData? locationData; String? get latitude => locationData?.latitude; String? get longitude => locationData?.longitude; @@ -8,6 +11,7 @@ class ImageAndLocationData { ImageAndLocationData({ required this.imagePath, + this.imageBytes, required this.locationData, }); } diff --git a/lib/src/map_camera.dart b/lib/src/map_camera.dart index b2cc5f3..10d471a 100644 --- a/lib/src/map_camera.dart +++ b/lib/src/map_camera.dart @@ -1,5 +1,5 @@ import 'dart:async'; -import 'dart:io'; +import 'dart:io' as io; import 'dart:math'; import 'package:camera/camera.dart'; @@ -48,8 +48,8 @@ class _MapCameraLocationState extends State { late AlignOnUpdate _followOnLocationUpdate; late StreamController _followCurrentLocationStreamController; - File? cameraImagePath; - File? ssImage; + io.File? cameraImagePath; + io.File? ssImage; String? dateTime; final globalKey = GlobalKey(); @@ -184,6 +184,11 @@ class _MapCameraLocationState extends State { CurrentLocationLayer( alignPositionStream: _followCurrentLocationStreamController.stream, alignPositionOnUpdate: _followOnLocationUpdate, + style: LocationMarkerStyle( + showHeadingSector: !kIsWeb, + showAccuracyCircle: !kIsWeb, + ), + headingStream: kIsWeb ? const Stream.empty() : null, ), ], ), @@ -233,18 +238,27 @@ class _MapCameraLocationState extends State { final rng = Random(); final boundary = globalKey.currentContext!.findRenderObject()! as RenderRepaintBoundary; final image = await boundary.toImage(pixelRatio: 2.0); - final directory = (await getApplicationDocumentsDirectory()).path; final byteData = await image.toByteData(format: ui.ImageByteFormat.png); final pngBytes = byteData!.buffer.asUint8List(); - final imgFile = File('$directory/screenshot${rng.nextInt(10000)}.png'); - await imgFile.writeAsBytes(pngBytes); + String finalPath = ''; - if (imgFile.existsSync()) { - setState(() => cameraImagePath = imgFile); + if (kIsWeb) { + // On web we use the bytes to create a blob preview or similar + // For now we just return an empty path or a fake one to avoid crash + finalPath = 'web_capture_${rng.nextInt(10000)}.png'; + } else { + final directory = (await getApplicationDocumentsDirectory()).path; + final imgFile = io.File('$directory/screenshot${rng.nextInt(10000)}.png'); + await imgFile.writeAsBytes(pngBytes); + finalPath = imgFile.path; + } + + if (finalPath.isNotEmpty) { if (widget.onImageCaptured != null) { widget.onImageCaptured!(ImageAndLocationData( - imagePath: imgFile.path, + imagePath: finalPath, + imageBytes: pngBytes, locationData: locationData, )); } @@ -265,6 +279,19 @@ class _MapCameraLocationState extends State { lngVal = pos.longitude; } + // Reverse geocoding often doesn't work well on web without a provider + if (kIsWeb) { + setState(() { + locationData = LocationData( + latitude: latVal.toString(), + longitude: lngVal.toString(), + locationName: 'Web Location', + subLocation: 'Browser Accuracy', + ); + }); + return; + } + final placeMarks = await placemarkFromCoordinates(latVal, lngVal); if (mounted) { @@ -303,37 +330,46 @@ class _MapCameraLocationState extends State { } Future _determinePosition() async { - final serviceEnabled = await Geolocator.isLocationServiceEnabled(); - if (!serviceEnabled) { - final lastKnown = await Geolocator.getLastKnownPosition(); - if (lastKnown != null) return lastKnown; - throw Exception('Location service disabled'); + // Basic service check + if (!kIsWeb) { + final serviceEnabled = await Geolocator.isLocationServiceEnabled(); + if (!serviceEnabled) { + final lastKnown = await Geolocator.getLastKnownPosition(); + if (lastKnown != null) return lastKnown; + throw Exception('Location service disabled'); + } } var permission = await Geolocator.checkPermission(); if (permission == LocationPermission.denied) { permission = await Geolocator.requestPermission(); if (permission == LocationPermission.denied) { - final lastKnown = await Geolocator.getLastKnownPosition(); - if (lastKnown != null) return lastKnown; + if (!kIsWeb) { + final lastKnown = await Geolocator.getLastKnownPosition(); + if (lastKnown != null) return lastKnown; + } throw Exception('Location permission denied'); } } if (permission == LocationPermission.deniedForever) { - final lastKnown = await Geolocator.getLastKnownPosition(); - if (lastKnown != null) return lastKnown; + if (!kIsWeb) { + final lastKnown = await Geolocator.getLastKnownPosition(); + if (lastKnown != null) return lastKnown; + } throw Exception('Location permission permanently denied'); } try { return await Geolocator.getCurrentPosition( desiredAccuracy: LocationAccuracy.medium, - timeLimit: const Duration(seconds: 8), + timeLimit: const Duration(seconds: 15), ); } catch (e) { - final lastKnown = await Geolocator.getLastKnownPosition(); - if (lastKnown != null) return lastKnown; + if (!kIsWeb) { + final lastKnown = await Geolocator.getLastKnownPosition(); + if (lastKnown != null) return lastKnown; + } rethrow; } }