From 52232e6283d259f1bd8d92bd739f4d532e59bc40 Mon Sep 17 00:00:00 2001 From: oltimaloku Date: Fri, 2 Feb 2024 12:17:15 -0800 Subject: [PATCH 1/6] Restructured geo sphere view model and geo sphere service to make view model maintain state. Service files should only be used to make calls to backend. --- .../features/auth/services/auth_service.dart | 6 +-- .../services/geo_sphere_service.dart | 40 ++----------------- .../view_model/geo_sphere_view_model.dart | 22 +++++++--- 3 files changed, 24 insertions(+), 44 deletions(-) diff --git a/client/lib/features/auth/services/auth_service.dart b/client/lib/features/auth/services/auth_service.dart index a37bdf1..344ae27 100644 --- a/client/lib/features/auth/services/auth_service.dart +++ b/client/lib/features/auth/services/auth_service.dart @@ -1,9 +1,9 @@ -import 'package:georeal/global_variables.dart'; +import 'package:georeal/constants/env_variables.dart'; import 'package:http/http.dart' as http; class AuthService { static Future login(String email, String password) async { - var uri = Uri.parse('${GlobalVariables.URI}/auth/login'); + var uri = Uri.parse('${EnvVariables.uri}/auth/login'); var response = await http.post( uri, body: { @@ -21,7 +21,7 @@ class AuthService { static Future register( String name, String email, String password) async { - var uri = Uri.parse('${GlobalVariables.URI}/auth/register'); + var uri = Uri.parse('${EnvVariables.uri}/auth/register'); var response = await http.post( uri, body: { diff --git a/client/lib/features/geo_sphere/services/geo_sphere_service.dart b/client/lib/features/geo_sphere/services/geo_sphere_service.dart index f4882f2..a28f009 100644 --- a/client/lib/features/geo_sphere/services/geo_sphere_service.dart +++ b/client/lib/features/geo_sphere/services/geo_sphere_service.dart @@ -5,36 +5,11 @@ import 'package:georeal/constants/env_variables.dart'; import 'package:http/http.dart' as http; import '../../../models/geo_sphere_model.dart'; -import '../../gallery/services/gallery_service.dart'; /// handles http requests for the GeoSpheres class GeoSphereService { - final GalleryService _galleryService; - final List _geoSpheres = []; - - GeoSphereService(this._galleryService) { - getAllGeoSpheres(); - } - - List get geoSpheres => _geoSpheres; - - void createGeoSphere( - double latitude, double longitude, double radius, String name) { - var newGeoSphere = GeoSphere( - latitude: latitude, - longitude: longitude, - radiusInMeters: radius, - name: name, - ); - - _geoSpheres.add(newGeoSphere); - postGeoSphere(geoSphere: newGeoSphere); - - _galleryService.createGalleryForGeoSphere(newGeoSphere.geoSphereId); - } - - void postGeoSphere({ + static void createGeoSphere({ required GeoSphere geoSphere, }) async { try { @@ -42,9 +17,7 @@ class GeoSphereService { log(geoSphere.toGeoJsonString()); http.Response res = await http.post( - Uri.parse('${EnvVariables.uri}/geofences'), - body: json .encode({'name': geoSphere.name, 'geojson': geoSphere.toGeoJson()}), headers: { @@ -63,20 +36,15 @@ class GeoSphereService { } } - Future getAllGeoSpheres() async { + static Future getAllGeoSpheres() async { try { - - var response = await http.get(Uri.parse('${EnvVariables.uri}/geofences')); - if (response.statusCode == 200) { List geofencesData = json.decode(response.body); - // Process the data - // Assuming GeoSphere.fromMap() is a constructor that creates a GeoSphere from a Map - _geoSpheres.clear(); + for (var geofenceData in geofencesData) { - _geoSpheres.add(GeoSphere.fromMap(geofenceData)); + // TODO: handle geosjson data } } else { print('Request failed with status: ${response.statusCode}.'); diff --git a/client/lib/features/geo_sphere/view_model/geo_sphere_view_model.dart b/client/lib/features/geo_sphere/view_model/geo_sphere_view_model.dart index 4702574..e2fb8b0 100644 --- a/client/lib/features/geo_sphere/view_model/geo_sphere_view_model.dart +++ b/client/lib/features/geo_sphere/view_model/geo_sphere_view_model.dart @@ -17,10 +17,11 @@ class GeoSphereViewModel extends ChangeNotifier { bool inGeoSphere = false; final GeoSphereService _geoSphereService; final LocationViewModel _locationViewModel; + final List _geoSpheres = []; GeoSphereViewModel(this._geoSphereService, this._locationViewModel); - List get geoSpheres => _geoSphereService.geoSpheres; + List get geoSpheres => _geoSpheres; Future setAndCreateGeoSphere(double radius, String name) async { LocationData? locationData = _locationViewModel.currentLocation; @@ -29,16 +30,27 @@ class GeoSphereViewModel extends ChangeNotifier { if (locationData != null && locationData.latitude != null && locationData.longitude != null) { - _geoSphereService.createGeoSphere( - locationData.latitude!, locationData.longitude!, radius, name); + GeoSphere newGeoSphere = GeoSphere( + latitude: locationData.latitude!, + longitude: locationData.longitude!, + radiusInMeters: radius, + name: name); + _geoSpheres.add(newGeoSphere); + GeoSphereService.createGeoSphere(geoSphere: newGeoSphere); notifyListeners(); } else { locationData = await _locationViewModel.fetchLocation(); if (locationData != null && locationData.latitude != null && locationData.longitude != null) { - _geoSphereService.createGeoSphere( - locationData.latitude!, locationData.longitude!, radius, name); + GeoSphere newGeoSphere = GeoSphere( + latitude: locationData.latitude!, + longitude: locationData.longitude!, + radiusInMeters: radius, + name: name); + _geoSpheres.add(newGeoSphere); + GeoSphereService.createGeoSphere(geoSphere: newGeoSphere); + notifyListeners(); } else { // location data is still not available From 9bdc5c87432c44fe5a6eb0a1354d31c42f2cea0d Mon Sep 17 00:00:00 2001 From: oltimaloku Date: Fri, 2 Feb 2024 17:23:34 -0800 Subject: [PATCH 2/6] Moved gallery business logic from gallery service to gallery view model --- .../gallery/services/gallery_service.dart | 21 -------------- .../view_model/gallery_view_model.dart | 28 +++++++++++++++++++ .../gallery/views/geo_sphere_gallery.dart | 7 ++--- .../gallery/widgets/photo_prompt.dart | 18 ++++++------ .../view_model/geo_sphere_view_model.dart | 19 +++++++------ client/lib/home_router.dart | 21 -------------- client/lib/main.dart | 8 ++++-- 7 files changed, 57 insertions(+), 65 deletions(-) create mode 100644 client/lib/features/gallery/view_model/gallery_view_model.dart diff --git a/client/lib/features/gallery/services/gallery_service.dart b/client/lib/features/gallery/services/gallery_service.dart index f63fec7..e98fa4f 100644 --- a/client/lib/features/gallery/services/gallery_service.dart +++ b/client/lib/features/gallery/services/gallery_service.dart @@ -3,26 +3,9 @@ import 'dart:io'; import 'package:georeal/constants/env_variables.dart'; import 'package:http/http.dart' as http; -import '../../../models/gallery_model.dart'; - /// Handles http requests for the Gallery class GalleryService { - final Map _galleries = {}; - - void createGalleryForGeoSphere(String geoSphereId) { - _galleries[geoSphereId] = Gallery(id: geoSphereId); - } - - void addPhotoToGallery(String geoSphereId, String photoPath) { - final gallery = _galleries[geoSphereId]; - if (gallery != null) { - gallery.photoPaths.add(photoPath); - } else { - print("Gallery with this id does not exist!"); - } - } - Future uploadPhoto(String geoSphereId, File photo) async { var uri = Uri.parse('${EnvVariables.uri}/geofences'); @@ -42,8 +25,4 @@ class GalleryService { throw Exception("Error occurred: $e"); } } - - List getPhotosFromGallery(String geoSphereId) { - return _galleries[geoSphereId]?.photoPaths ?? []; - } } diff --git a/client/lib/features/gallery/view_model/gallery_view_model.dart b/client/lib/features/gallery/view_model/gallery_view_model.dart new file mode 100644 index 0000000..ec53a64 --- /dev/null +++ b/client/lib/features/gallery/view_model/gallery_view_model.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; + +import '../../../models/gallery_model.dart'; + +class GalleryViewModel extends ChangeNotifier { + final Map _galleries = {}; + + get galleries => _galleries; + + void createGallery(String geoSphereId) { + _galleries[geoSphereId] = Gallery(id: geoSphereId); + } + + void addPhotoToGallery(String geoSphereId, String photoPath) { + final gallery = _galleries[geoSphereId]; + if (gallery != null) { + gallery.photoPaths.add(photoPath); + } else { + Gallery newGallery = Gallery(id: geoSphereId); + newGallery.photoPaths.add(photoPath); + _galleries[geoSphereId] = newGallery; + } + } + + List getPhotosFromGallery(String geoSphereId) { + return _galleries[geoSphereId]?.photoPaths ?? []; + } +} diff --git a/client/lib/features/gallery/views/geo_sphere_gallery.dart b/client/lib/features/gallery/views/geo_sphere_gallery.dart index b83dd07..ac07fbd 100644 --- a/client/lib/features/gallery/views/geo_sphere_gallery.dart +++ b/client/lib/features/gallery/views/geo_sphere_gallery.dart @@ -1,12 +1,11 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:georeal/features/gallery/view_model/gallery_view_model.dart'; import 'package:georeal/features/gallery/widgets/gallery_navbar.dart'; import 'package:georeal/models/geo_sphere_model.dart'; import 'package:provider/provider.dart'; -import '../services/gallery_service.dart'; - /// Gallery view for a specific GeoSphere class GeoSphereGallery extends StatelessWidget { @@ -19,9 +18,9 @@ class GeoSphereGallery extends StatelessWidget { @override Widget build(BuildContext context) { - final galleryService = Provider.of(context, listen: false); + final galleryViewModel = context.watch(); List photoPaths = - galleryService.getPhotosFromGallery(geoSphere.geoSphereId); + galleryViewModel.getPhotosFromGallery(geoSphere.geoSphereId); return Scaffold( body: SafeArea( diff --git a/client/lib/features/gallery/widgets/photo_prompt.dart b/client/lib/features/gallery/widgets/photo_prompt.dart index 1dfac50..0e38495 100644 --- a/client/lib/features/gallery/widgets/photo_prompt.dart +++ b/client/lib/features/gallery/widgets/photo_prompt.dart @@ -1,13 +1,13 @@ +import 'dart:developer'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:georeal/features/gallery/view_model/gallery_view_model.dart'; import 'package:image_picker/image_picker.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; -import '../../gallery/services/gallery_service.dart'; - /// Prompt to add a photo to a GeoSphere class PhotoPrompt extends StatefulWidget { @@ -21,18 +21,18 @@ class PhotoPrompt extends StatefulWidget { class _PhotoPromptState extends State { File? image; - Future pickImage(ImageSource source) async { + Future pickImage(ImageSource source, BuildContext context) async { try { final image = await ImagePicker().pickImage(source: source); if (image == null) return; final imageTemporary = File(image.path); this.image = imageTemporary; - + log("beofre"); // Save the image path to the gallery - Provider.of(context, listen: false) + Provider.of(context, listen: false) .addPhotoToGallery(widget.geoSphereId, image.path); - + log("after"); /* Provider.of(context, listen: false) .uploadPhoto(widget.geoSphereId, imageTemporary);*/ @@ -50,7 +50,7 @@ class _PhotoPromptState extends State { child: Column( children: [ ElevatedButton( - onPressed: () => pickImage(ImageSource.gallery), + onPressed: () => pickImage(ImageSource.gallery, context), child: const Text("Pick Gallery"), ), ElevatedButton( @@ -58,13 +58,13 @@ class _PhotoPromptState extends State { if (Platform.isAndroid) { var status = await Permission.camera.request(); if (status.isGranted) { - pickImage(ImageSource.camera); + pickImage(ImageSource.camera, context); } else { print("bruh"); } } else if (Platform.isIOS) { // TODO: Implement iOS camera permission - pickImage(ImageSource.camera); + pickImage(ImageSource.camera, context); } }, child: const Text("Pick Camera"), diff --git a/client/lib/features/geo_sphere/view_model/geo_sphere_view_model.dart b/client/lib/features/geo_sphere/view_model/geo_sphere_view_model.dart index e2fb8b0..5127d14 100644 --- a/client/lib/features/geo_sphere/view_model/geo_sphere_view_model.dart +++ b/client/lib/features/geo_sphere/view_model/geo_sphere_view_model.dart @@ -31,10 +31,11 @@ class GeoSphereViewModel extends ChangeNotifier { locationData.latitude != null && locationData.longitude != null) { GeoSphere newGeoSphere = GeoSphere( - latitude: locationData.latitude!, - longitude: locationData.longitude!, - radiusInMeters: radius, - name: name); + latitude: locationData.latitude!, + longitude: locationData.longitude!, + radiusInMeters: radius, + name: name, + ); _geoSpheres.add(newGeoSphere); GeoSphereService.createGeoSphere(geoSphere: newGeoSphere); notifyListeners(); @@ -44,10 +45,12 @@ class GeoSphereViewModel extends ChangeNotifier { locationData.latitude != null && locationData.longitude != null) { GeoSphere newGeoSphere = GeoSphere( - latitude: locationData.latitude!, - longitude: locationData.longitude!, - radiusInMeters: radius, - name: name); + latitude: locationData.latitude!, + longitude: locationData.longitude!, + radiusInMeters: radius, + name: name, + ); + _geoSpheres.add(newGeoSphere); GeoSphereService.createGeoSphere(geoSphere: newGeoSphere); diff --git a/client/lib/home_router.dart b/client/lib/home_router.dart index 08521e8..1cd16b1 100644 --- a/client/lib/home_router.dart +++ b/client/lib/home_router.dart @@ -1,27 +1,7 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; -import 'package:georeal/constants/env_variables.dart'; import 'package:georeal/features/geo_sphere/views/geo_spheres_view.dart'; import 'package:georeal/features/home/screens/home_screen.dart'; import 'package:georeal/global_variables.dart'; -import 'package:http/http.dart' as http; - -Future checkServerStatus() async { - try { - print("[georeal] Checking server"); - final response = await http.get(Uri.parse(EnvVariables.uri)); - - if (response.statusCode == 200) { - var data = json.decode(response.body); - print('[georeal] Server status: ${data['status']}'); - } else { - print('[georeal] Server error: ${response.statusCode}'); - } - } catch (e) { - print('[georeal] Error checking server status: $e'); - } -} import 'features/geo_sphere/widgets/add_geo_sphere_modal.dart'; @@ -38,7 +18,6 @@ class _HomeRouterState extends State { @override void initState() { super.initState(); - checkServerStatus(); } int _page = 0; diff --git a/client/lib/main.dart b/client/lib/main.dart index b00852e..56adce7 100644 --- a/client/lib/main.dart +++ b/client/lib/main.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:georeal/features/gallery/services/gallery_service.dart'; +import 'package:georeal/features/gallery/view_model/gallery_view_model.dart'; import 'package:georeal/features/geo_sphere/services/geo_sphere_service.dart'; import 'package:georeal/features/view_models/user_view_model.dart'; import 'package:georeal/home_router.dart'; @@ -15,7 +16,7 @@ Future main() async { WidgetsFlutterBinding.ensureInitialized(); GalleryService galleryService = GalleryService(); - GeoSphereService geoSphereService = GeoSphereService(galleryService); + GeoSphereService geoSphereService = GeoSphereService(); LocationViewModel locationViewModel = LocationViewModel(); runApp( @@ -36,7 +37,10 @@ Future main() async { ), Provider( create: (context) => galleryService, - ) + ), + Provider( + create: (context) => GalleryViewModel(), + ), ], child: const MyApp(), ), From 3ed0e0b72ca9bd750754d94b02626a4d3496bd1f Mon Sep 17 00:00:00 2001 From: oltimaloku Date: Fri, 2 Feb 2024 17:46:19 -0800 Subject: [PATCH 3/6] Refactored home screen to make it stateless --- .../view_model/geo_sphere_view_model.dart | 21 ++++----- .../features/home/screens/home_screen.dart | 45 ++----------------- client/lib/main.dart | 7 ++- 3 files changed, 15 insertions(+), 58 deletions(-) diff --git a/client/lib/features/geo_sphere/view_model/geo_sphere_view_model.dart b/client/lib/features/geo_sphere/view_model/geo_sphere_view_model.dart index 5127d14..0e80700 100644 --- a/client/lib/features/geo_sphere/view_model/geo_sphere_view_model.dart +++ b/client/lib/features/geo_sphere/view_model/geo_sphere_view_model.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:developer' as log; import 'dart:math'; import 'package:flutter/material.dart'; @@ -15,11 +16,11 @@ typedef LocationCallback = void Function(List geoSphere); class GeoSphereViewModel extends ChangeNotifier { bool inGeoSphere = false; - final GeoSphereService _geoSphereService; + final LocationViewModel _locationViewModel; final List _geoSpheres = []; - GeoSphereViewModel(this._geoSphereService, this._locationViewModel); + GeoSphereViewModel(this._locationViewModel); List get geoSpheres => _geoSpheres; @@ -57,13 +58,11 @@ class GeoSphereViewModel extends ChangeNotifier { notifyListeners(); } else { // location data is still not available - // print("Location data is not available to create GeoSphere."); } } } void deleteGeoSphere(GeoSphere geoSphereToDelete) { - // Assuming _geoSpheres is a List geoSpheres .removeWhere((geoSphere) => geoSphere.name == geoSphereToDelete.name); notifyListeners(); @@ -76,10 +75,9 @@ class GeoSphereViewModel extends ChangeNotifier { if (placemarks.isNotEmpty) { geocode.Placemark place = placemarks[0]; - return place.subLocality ?? - 'Unknown'; // Returns the neighborhood or 'Unknown' if null + return place.subLocality ?? 'Unknown'; } - return 'No neighborhood found'; // Return this if placemarks list is empty + return 'No neighborhood found'; } catch (e) { print("Error occurred: $e"); return 'Error occurred'; // Return this in case of an error @@ -153,7 +151,7 @@ class GeoSphereViewModel extends ChangeNotifier { return containingGeoSpheres; } - Future startLocationChecks(LocationCallback callback) async { + Future startLocationChecks() async { // Request background location permission Timer.periodic( const Duration(seconds: 10), @@ -161,19 +159,16 @@ class GeoSphereViewModel extends ChangeNotifier { LocationData? currentLocation = _locationViewModel.currentLocation; if (currentLocation == null) { - print("Current location is null; are permissions set appropriately?"); + log.log( + "Current location is null; are permissions set appropriately?"); } else { if (currentLocation.latitude != null && currentLocation.longitude != null) { - // print( - // "Current Location: ${currentLocation.latitude}, ${currentLocation.longitude}"); - List currentGeoSpheres = isPointInGeoSphere( currentLocation.latitude!, currentLocation.longitude!); if (currentGeoSpheres.isNotEmpty) { inGeoSphere = true; - callback(currentGeoSpheres); notifyListeners(); } } else { diff --git a/client/lib/features/home/screens/home_screen.dart b/client/lib/features/home/screens/home_screen.dart index 209311e..678996f 100644 --- a/client/lib/features/home/screens/home_screen.dart +++ b/client/lib/features/home/screens/home_screen.dart @@ -5,52 +5,15 @@ import 'package:georeal/features/gallery/widgets/photo_prompt.dart'; import 'package:georeal/features/geo_sphere/view_model/geo_sphere_view_model.dart'; import 'package:provider/provider.dart'; -import '../../../models/geo_sphere_model.dart'; -import '../../view_models/user_view_model.dart'; import '../widgets/map.dart'; /// HomeScreen is the main screen of the app which contains the Map -class HomeScreen extends StatefulWidget { +class HomeScreen extends StatelessWidget { const HomeScreen({super.key}); - @override - State createState() => _HomeScreenState(); -} - -class _HomeScreenState extends State { - bool isLocationServiceStarted = false; - List geoSpheres = []; - - void showCustomToast(List geoSpheres) { - // checking mounted here ensures that home screen is still - // in widget tree before showing the toast - this.geoSpheres = geoSpheres; - /* - if (mounted) { - CustomToast.show( - context, - "You have entered ${geoSpheres.last.name}, press this button to add to its gallery!", - geoSpheres.last, - ); - } - */ - } - @override Widget build(BuildContext context) { - final userViewModel = Provider.of(context, listen: false); - log('email: ${userViewModel.user.email}'); - final geoSphereViewModel = - Provider.of(context, listen: false); - // TODO: move this to a seperate method in the geo sphere view model - if (!isLocationServiceStarted) { - geoSphereViewModel.startLocationChecks(showCustomToast); - log("Start location checks"); - isLocationServiceStarted = true; - } else { - // TODO: Handle - } return Scaffold( body: Stack( children: [ @@ -97,15 +60,15 @@ class _HomeScreenState extends State { ], ), onTap: () => { - log("$geoSpheres"), - log("Tapped on camera button: ${geoSphereViewModel.inGeoSphere}"), + log('${geoSphereViewModel.inGeoSphere}'), if (geoSphereViewModel.inGeoSphere) { showDialog( context: context, builder: (context) { return PhotoPrompt( - geoSphereId: geoSpheres.last.geoSphereId); + geoSphereId: geoSphereViewModel + .geoSpheres.last.geoSphereId); }) } else diff --git a/client/lib/main.dart b/client/lib/main.dart index 56adce7..e6371b3 100644 --- a/client/lib/main.dart +++ b/client/lib/main.dart @@ -18,6 +18,8 @@ Future main() async { GalleryService galleryService = GalleryService(); GeoSphereService geoSphereService = GeoSphereService(); LocationViewModel locationViewModel = LocationViewModel(); + GeoSphereViewModel geoSphereViewModel = GeoSphereViewModel(locationViewModel); + geoSphereViewModel.startLocationChecks(); runApp( MultiProvider( @@ -28,10 +30,7 @@ Future main() async { ChangeNotifierProvider( create: (_) => locationViewModel, ), - ChangeNotifierProvider( - create: (context) => - GeoSphereViewModel(geoSphereService, locationViewModel), - ), + ChangeNotifierProvider(create: (context) => geoSphereViewModel), Provider( create: (context) => geoSphereService, ), From 5a9307bb8a2a541a9a32903fbf966434ad274232 Mon Sep 17 00:00:00 2001 From: oltimaloku Date: Fri, 2 Feb 2024 18:06:46 -0800 Subject: [PATCH 4/6] fix: photo prompt throws error on first click --- .../gallery/view_model/gallery_view_model.dart | 3 +++ .../lib/features/gallery/widgets/photo_prompt.dart | 14 ++++++++------ client/lib/main.dart | 2 +- client/macos/Runner.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/client/lib/features/gallery/view_model/gallery_view_model.dart b/client/lib/features/gallery/view_model/gallery_view_model.dart index ec53a64..f23b496 100644 --- a/client/lib/features/gallery/view_model/gallery_view_model.dart +++ b/client/lib/features/gallery/view_model/gallery_view_model.dart @@ -9,16 +9,19 @@ class GalleryViewModel extends ChangeNotifier { void createGallery(String geoSphereId) { _galleries[geoSphereId] = Gallery(id: geoSphereId); + notifyListeners(); } void addPhotoToGallery(String geoSphereId, String photoPath) { final gallery = _galleries[geoSphereId]; if (gallery != null) { gallery.photoPaths.add(photoPath); + notifyListeners(); } else { Gallery newGallery = Gallery(id: geoSphereId); newGallery.photoPaths.add(photoPath); _galleries[geoSphereId] = newGallery; + notifyListeners(); } } diff --git a/client/lib/features/gallery/widgets/photo_prompt.dart b/client/lib/features/gallery/widgets/photo_prompt.dart index 0e38495..fc1c436 100644 --- a/client/lib/features/gallery/widgets/photo_prompt.dart +++ b/client/lib/features/gallery/widgets/photo_prompt.dart @@ -21,7 +21,8 @@ class PhotoPrompt extends StatefulWidget { class _PhotoPromptState extends State { File? image; - Future pickImage(ImageSource source, BuildContext context) async { + Future pickImage( + ImageSource source, GalleryViewModel galleryViewModel) async { try { final image = await ImagePicker().pickImage(source: source); if (image == null) return; @@ -30,8 +31,7 @@ class _PhotoPromptState extends State { this.image = imageTemporary; log("beofre"); // Save the image path to the gallery - Provider.of(context, listen: false) - .addPhotoToGallery(widget.geoSphereId, image.path); + galleryViewModel.addPhotoToGallery(widget.geoSphereId, image.path); log("after"); /* Provider.of(context, listen: false) @@ -43,6 +43,8 @@ class _PhotoPromptState extends State { @override Widget build(BuildContext context) { + final galleryViewModel = + Provider.of(context, listen: false); return AlertDialog( title: const Text("Add a photo!"), content: SizedBox( @@ -50,7 +52,7 @@ class _PhotoPromptState extends State { child: Column( children: [ ElevatedButton( - onPressed: () => pickImage(ImageSource.gallery, context), + onPressed: () => pickImage(ImageSource.gallery, galleryViewModel), child: const Text("Pick Gallery"), ), ElevatedButton( @@ -58,13 +60,13 @@ class _PhotoPromptState extends State { if (Platform.isAndroid) { var status = await Permission.camera.request(); if (status.isGranted) { - pickImage(ImageSource.camera, context); + pickImage(ImageSource.camera, galleryViewModel); } else { print("bruh"); } } else if (Platform.isIOS) { // TODO: Implement iOS camera permission - pickImage(ImageSource.camera, context); + pickImage(ImageSource.camera, galleryViewModel); } }, child: const Text("Pick Camera"), diff --git a/client/lib/main.dart b/client/lib/main.dart index e6371b3..7f9af2e 100644 --- a/client/lib/main.dart +++ b/client/lib/main.dart @@ -37,7 +37,7 @@ Future main() async { Provider( create: (context) => galleryService, ), - Provider( + ChangeNotifierProvider( create: (context) => GalleryViewModel(), ), ], diff --git a/client/macos/Runner.xcodeproj/project.pbxproj b/client/macos/Runner.xcodeproj/project.pbxproj index 5a657d4..6c8da36 100644 --- a/client/macos/Runner.xcodeproj/project.pbxproj +++ b/client/macos/Runner.xcodeproj/project.pbxproj @@ -259,7 +259,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1430; ORGANIZATIONNAME = ""; TargetAttributes = { 331C80D4294CF70F00263BE5 = { diff --git a/client/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/client/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 965fdf8..41cd340 100644 --- a/client/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/client/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ Date: Fri, 2 Feb 2024 18:36:20 -0800 Subject: [PATCH 5/6] feat: user is navigated to gallery upon successful upload of photo to gallery --- client/lib/common/custom_toast.dart | 2 +- .../features/gallery/widgets/photo_prompt.dart | 15 ++++++++++++--- client/lib/features/home/screens/home_screen.dart | 4 ++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/client/lib/common/custom_toast.dart b/client/lib/common/custom_toast.dart index ead121c..775f53e 100644 --- a/client/lib/common/custom_toast.dart +++ b/client/lib/common/custom_toast.dart @@ -40,7 +40,7 @@ class CustomToast { context: context, builder: ((context) { return PhotoPrompt( - geoSphereId: geoSphere.geoSphereId, + geosphere: geoSphere, ); })); }, diff --git a/client/lib/features/gallery/widgets/photo_prompt.dart b/client/lib/features/gallery/widgets/photo_prompt.dart index fc1c436..3e2e480 100644 --- a/client/lib/features/gallery/widgets/photo_prompt.dart +++ b/client/lib/features/gallery/widgets/photo_prompt.dart @@ -8,11 +8,14 @@ import 'package:image_picker/image_picker.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; +import '../../../models/geo_sphere_model.dart'; +import '../views/geo_sphere_gallery.dart'; + /// Prompt to add a photo to a GeoSphere class PhotoPrompt extends StatefulWidget { - final String geoSphereId; - const PhotoPrompt({super.key, required this.geoSphereId}); + final GeoSphere geosphere; + const PhotoPrompt({super.key, required this.geosphere}); @override State createState() => _PhotoPromptState(); @@ -31,11 +34,17 @@ class _PhotoPromptState extends State { this.image = imageTemporary; log("beofre"); // Save the image path to the gallery - galleryViewModel.addPhotoToGallery(widget.geoSphereId, image.path); + galleryViewModel.addPhotoToGallery( + widget.geosphere.geoSphereId, image.path); log("after"); /* Provider.of(context, listen: false) .uploadPhoto(widget.geoSphereId, imageTemporary);*/ + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => GeoSphereGallery(geoSphere: widget.geosphere), + ), + ); } on PlatformException catch (e) { print("Failed to pick image: $e"); } diff --git a/client/lib/features/home/screens/home_screen.dart b/client/lib/features/home/screens/home_screen.dart index 678996f..af767bd 100644 --- a/client/lib/features/home/screens/home_screen.dart +++ b/client/lib/features/home/screens/home_screen.dart @@ -67,8 +67,8 @@ class HomeScreen extends StatelessWidget { context: context, builder: (context) { return PhotoPrompt( - geoSphereId: geoSphereViewModel - .geoSpheres.last.geoSphereId); + geosphere: + geoSphereViewModel.geoSpheres.last); }) } else From 71e4f54b37a4b35d3dbb4081e0b08545c9576481 Mon Sep 17 00:00:00 2001 From: oltimaloku Date: Fri, 2 Feb 2024 18:38:17 -0800 Subject: [PATCH 6/6] Made gallery service methods static --- client/lib/features/gallery/services/gallery_service.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/lib/features/gallery/services/gallery_service.dart b/client/lib/features/gallery/services/gallery_service.dart index e98fa4f..593cefd 100644 --- a/client/lib/features/gallery/services/gallery_service.dart +++ b/client/lib/features/gallery/services/gallery_service.dart @@ -6,7 +6,7 @@ import 'package:http/http.dart' as http; /// Handles http requests for the Gallery class GalleryService { - Future uploadPhoto(String geoSphereId, File photo) async { + static Future uploadPhoto(String geoSphereId, File photo) async { var uri = Uri.parse('${EnvVariables.uri}/geofences'); var request = http.MultipartRequest('POST', uri)