From 87c25f33e061b2ad496aae54b45fb0b0a383f5ed Mon Sep 17 00:00:00 2001 From: Somye Date: Sun, 5 Jan 2025 15:55:11 +0530 Subject: [PATCH 1/9] Added geolocator and permissions --- android/app/src/main/AndroidManifest.xml | 4 + ios/Runner.xcodeproj/project.pbxproj | 8 +- ios/Runner/Info.plist | 4 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 90 ++++++++++++++++++- pubspec.yaml | 1 + .../flutter/generated_plugin_registrant.cc | 3 + windows/flutter/generated_plugins.cmake | 1 + 8 files changed, 107 insertions(+), 6 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index ab2ab3c..afb219d 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -7,6 +7,10 @@ + + + + diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index c48b2be..51f8d8f 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -107,7 +107,6 @@ 4CD6A70718A37A05253E6E62 /* Pods-RunnerTests.release.xcconfig */, 53896B7435ECC0E20EF3D9B6 /* Pods-RunnerTests.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -138,7 +137,6 @@ 2123B31439D2BCC6D361E8DD /* Pods-RunnerTests.release.xcconfig */, EF51637AE1B35676F68DF4C3 /* Pods-RunnerTests.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -506,7 +504,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = AT4J799SCP; + DEVELOPMENT_TEAM = STL7VW4HH6; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -689,7 +687,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = AT4J799SCP; + DEVELOPMENT_TEAM = STL7VW4HH6; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -712,7 +710,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = AT4J799SCP; + DEVELOPMENT_TEAM = STL7VW4HH6; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index aed65c8..54eb1d6 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -53,6 +53,10 @@ LSSupportsOpeningDocumentsInPlace + NSLocationWhenInUseUsageDescription + This app needs access to location when open. + NSLocationAlwaysAndWhenInUseUsageDescription + This app needs access to location when open. diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 20a39b0..e6d525f 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,12 +6,14 @@ import FlutterMacOS import Foundation import audioplayers_darwin +import geolocator_apple import path_provider_foundation import shared_preferences_foundation import speech_to_text func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin")) + GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SpeechToTextPlugin.register(with: registry.registrar(forPlugin: "SpeechToTextPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 8b63e05..39eafb4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -113,6 +113,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.18.0" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" + source: hosted + version: "0.3.4+2" crypto: dependency: transitive description: @@ -121,6 +129,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.6" + csv: + dependency: "direct main" + description: + name: csv + sha256: c6aa2679b2a18cb57652920f674488d89712efaf4d3fdf2e537215b35fc19d6c + url: "https://pub.dev" + source: hosted + version: "6.0.0" cupertino_icons: dependency: "direct main" description: @@ -169,6 +185,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.1" + file_picker: + dependency: "direct main" + description: + name: file_picker + sha256: c904b4ab56d53385563c7c39d8e9fa9af086f91495dfc48717ad84a42c3cf204 + url: "https://pub.dev" + source: hosted + version: "8.1.7" fixnum: dependency: transitive description: @@ -254,6 +278,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "615a505aef59b151b46bbeef55b36ce2b6ed299d160c51d84281946f0aa0ce0e" + url: "https://pub.dev" + source: hosted + version: "2.0.24" flutter_slidable: dependency: "direct main" description: @@ -288,6 +320,54 @@ packages: url: "https://pub.dev" source: hosted version: "8.2.10" + geolocator: + dependency: "direct main" + description: + name: geolocator + sha256: d2ec66329cab29cb297d51d96c067d457ca519dca8589665fa0b82ebacb7dbe4 + url: "https://pub.dev" + source: hosted + version: "13.0.2" + geolocator_android: + dependency: transitive + description: + name: geolocator_android + sha256: "7aefc530db47d90d0580b552df3242440a10fe60814496a979aa67aa98b1fd47" + url: "https://pub.dev" + source: hosted + version: "4.6.1" + geolocator_apple: + dependency: transitive + description: + name: geolocator_apple + sha256: "6154ea2682563f69fc0125762ed7e91e7ed85d0b9776595653be33918e064807" + url: "https://pub.dev" + source: hosted + version: "2.3.8+1" + geolocator_platform_interface: + dependency: transitive + description: + name: geolocator_platform_interface + sha256: "386ce3d9cce47838355000070b1d0b13efb5bc430f8ecda7e9238c8409ace012" + url: "https://pub.dev" + source: hosted + version: "4.2.4" + geolocator_web: + dependency: transitive + description: + name: geolocator_web + sha256: "2ed69328e05cd94e7eb48bb0535f5fc0c0c44d1c4fa1e9737267484d05c29b5e" + url: "https://pub.dev" + source: hosted + version: "4.1.1" + geolocator_windows: + dependency: transitive + description: + name: geolocator_windows + sha256: "53da08937d07c24b0d9952eb57a3b474e29aae2abf9dd717f7e1230995f13f0e" + url: "https://pub.dev" + source: hosted + version: "0.2.3" http: dependency: "direct main" description: @@ -701,6 +781,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + win32: + dependency: transitive + description: + name: win32 + sha256: "154360849a56b7b67331c21f09a386562d88903f90a1099c5987afc1912e1f29" + url: "https://pub.dev" + source: hosted + version: "5.10.0" xdg_directories: dependency: transitive description: @@ -719,4 +807,4 @@ packages: version: "6.5.0" sdks: dart: ">=3.5.0 <4.0.0" - flutter: ">=3.24.0" \ No newline at end of file + flutter: ">=3.24.0" diff --git a/pubspec.yaml b/pubspec.yaml index 0ef4586..c4cc2b2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -51,6 +51,7 @@ dependencies: duration_picker: ^1.2.0 circular_countdown_timer: ^0.2.4 flutter_confetti: ^0.3.4 + geolocator: ^13.0.2 dev_dependencies: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 09e8e2c..f7ae8c9 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,8 +7,11 @@ #include "generated_plugin_registrant.h" #include +#include void RegisterPlugins(flutter::PluginRegistry* registry) { AudioplayersWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin")); + GeolocatorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("GeolocatorWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 375535c..bead7fd 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST audioplayers_windows + geolocator_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST From 143da3c7ea625b2ccf1418655a570e3547b06404 Mon Sep 17 00:00:00 2001 From: Somye Date: Sun, 5 Jan 2025 15:56:42 +0530 Subject: [PATCH 2/9] upgraded to recommended settings --- ios/Runner.xcodeproj/project.pbxproj | 5 ++++- ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 51f8d8f..c3d64fb 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -249,7 +249,7 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 1510; + LastUpgradeCheck = 1620; ORGANIZATIONNAME = ""; TargetAttributes = { 331C8080294A63A400263BE5 = { @@ -469,6 +469,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -593,6 +594,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -650,6 +652,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 8e3ca5d..a55d1e3 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ Date: Sun, 5 Jan 2025 16:13:04 +0530 Subject: [PATCH 3/9] Added permission service & lat lng to task --- lib/models/task.dart | 18 ++++++++++++++++-- lib/service/permission_service.dart | 28 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 lib/service/permission_service.dart diff --git a/lib/models/task.dart b/lib/models/task.dart index 1e8727a..31c24c4 100644 --- a/lib/models/task.dart +++ b/lib/models/task.dart @@ -7,9 +7,19 @@ class Task { DateTime deadline; bool hasDeadline; Color color; + double? lat; + double? lng; - Task({required this.title, this.description = '', this.isCompleted = false, DateTime? deadline, this.hasDeadline = false,this.color = Colors.blue }) - : deadline = deadline ?? DateTime.now(); + Task({ + required this.title, + this.description = '', + this.isCompleted = false, + DateTime? deadline, + this.hasDeadline = false, + this.color = Colors.blue, + this.lat, + this.lng, + }) : deadline = deadline ?? DateTime.now(); // Convert a Task object to JSON Map toJson() { @@ -20,6 +30,8 @@ class Task { 'deadline': deadline.toIso8601String(), 'hasDeadline': hasDeadline, 'color': color.value, + 'lat': lat, + 'lng': lng, }; } @@ -32,6 +44,8 @@ class Task { deadline: DateTime.parse(json['deadline']), hasDeadline: json['hasDeadline'], color: Color(json['color']), + lat: json['lat'], + lng: json['lng'], ); } } diff --git a/lib/service/permission_service.dart b/lib/service/permission_service.dart new file mode 100644 index 0000000..21f001f --- /dev/null +++ b/lib/service/permission_service.dart @@ -0,0 +1,28 @@ +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:geolocator/geolocator.dart'; + +class PermissionService { + static Future askForLocation() async { + bool serviceEnabled = await Geolocator.isLocationServiceEnabled(); + if (!serviceEnabled) { + Fluttertoast.showToast(msg: "Enable location services."); + return false; + } + + LocationPermission permission = await Geolocator.checkPermission(); + if (permission == LocationPermission.denied) { + permission = await Geolocator.requestPermission(); + if (permission == LocationPermission.denied) { + Fluttertoast.showToast( + msg: "Grant location permission to use this feature"); + return false; + } + } else if (permission == LocationPermission.deniedForever) { + Fluttertoast.showToast( + msg: "Enable location permissions by going to Settings/Apps/Taskly"); + return false; + } + + return true; + } +} From 8dcfb83dea092178828032603e9e8732302702b6 Mon Sep 17 00:00:00 2001 From: Somye Date: Sun, 5 Jan 2025 16:21:21 +0530 Subject: [PATCH 4/9] Added button in task form screen --- ios/Podfile.lock | 70 +++++++++++++++++-- ios/Runner.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- lib/screens/taskform_screen.dart | 27 ++++++- 4 files changed, 91 insertions(+), 10 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 6320356..4b00eb2 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,15 +1,54 @@ PODS: - audioplayers_darwin (0.0.1): - Flutter + - DKImagePickerController/Core (4.3.9): + - DKImagePickerController/ImageDataManager + - DKImagePickerController/Resource + - DKImagePickerController/ImageDataManager (4.3.9) + - DKImagePickerController/PhotoGallery (4.3.9): + - DKImagePickerController/Core + - DKPhotoGallery + - DKImagePickerController/Resource (4.3.9) + - DKPhotoGallery (0.0.19): + - DKPhotoGallery/Core (= 0.0.19) + - DKPhotoGallery/Model (= 0.0.19) + - DKPhotoGallery/Preview (= 0.0.19) + - DKPhotoGallery/Resource (= 0.0.19) + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Core (0.0.19): + - DKPhotoGallery/Model + - DKPhotoGallery/Preview + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Model (0.0.19): + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Preview (0.0.19): + - DKPhotoGallery/Model + - DKPhotoGallery/Resource + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Resource (0.0.19): + - SDWebImage + - SwiftyGif + - file_picker (0.0.1): + - DKImagePickerController/PhotoGallery + - Flutter - Flutter (1.0.0) - flutter_keyboard_visibility (0.0.1): - Flutter - fluttertoast (0.0.2): - Flutter - Toast + - geolocator_apple (1.2.0): + - Flutter - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS + - SDWebImage (5.19.7): + - SDWebImage/Core (= 5.19.7) + - SDWebImage/Core (5.19.7) - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS @@ -17,32 +56,43 @@ PODS: - Flutter - FlutterMacOS - Try + - SwiftyGif (5.4.5) - Toast (4.1.1) - Try (2.1.1) DEPENDENCIES: - audioplayers_darwin (from `.symlinks/plugins/audioplayers_darwin/ios`) + - file_picker (from `.symlinks/plugins/file_picker/ios`) - Flutter (from `Flutter`) - flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`) - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) + - geolocator_apple (from `.symlinks/plugins/geolocator_apple/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - speech_to_text (from `.symlinks/plugins/speech_to_text/darwin`) SPEC REPOS: trunk: + - DKImagePickerController + - DKPhotoGallery + - SDWebImage + - SwiftyGif - Toast - Try EXTERNAL SOURCES: audioplayers_darwin: :path: ".symlinks/plugins/audioplayers_darwin/ios" + file_picker: + :path: ".symlinks/plugins/file_picker/ios" Flutter: :path: Flutter flutter_keyboard_visibility: :path: ".symlinks/plugins/flutter_keyboard_visibility/ios" fluttertoast: :path: ".symlinks/plugins/fluttertoast/ios" + geolocator_apple: + :path: ".symlinks/plugins/geolocator_apple/ios" path_provider_foundation: :path: ".symlinks/plugins/path_provider_foundation/darwin" shared_preferences_foundation: @@ -51,16 +101,22 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/speech_to_text/darwin" SPEC CHECKSUMS: - audioplayers_darwin: 877d9a4d06331c5c374595e46e16453ac7eafa40 + audioplayers_darwin: ccf9c770ee768abb07e26d90af093f7bab1c12ab + DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c + DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 + file_picker: 9b3292d7c8bc68c8a7bf8eb78f730e49c8efc517 Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069 - fluttertoast: e9a18c7be5413da53898f660530c56f35edfba9c - path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 - shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 - speech_to_text: 627d3fd2194770b51abb324ba45c2d39398f24a8 + flutter_keyboard_visibility: 4625131e43015dbbe759d9b20daaf77e0e3f6619 + fluttertoast: 76fea30fcf04176325f6864c87306927bd7d2038 + geolocator_apple: 1560c3c875af2a412242c7a923e15d0d401966ff + path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 + SDWebImage: 8a6b7b160b4d710e2a22b6900e25301075c34cb3 + shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 + speech_to_text: 9dc43a5df3cbc2813f8c7cc9bd0fbf94268ed7ac + SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e Try: 5ef669ae832617b3cee58cb2c6f99fb767a4ff96 PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796 -COCOAPODS: 1.15.2 +COCOAPODS: 1.16.2 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index c3d64fb..b97df8e 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -249,7 +249,7 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 1620; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 331C8080294A63A400263BE5 = { diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index a55d1e3..8e3ca5d 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ { var hasDeadline = false; DateTime? deadline; Color selectedColor = Colors.blue; + double? lat, lng; bool isTitleListening = false; @@ -33,6 +37,8 @@ class _TaskFormScreenState extends State { hasDeadline = widget.task?.hasDeadline ?? false; deadline = widget.task?.deadline; selectedColor = widget.task?.color ?? Colors.blue; + lat = widget.task?.lat; + lng = widget.task?.lng; } void _showColorPicker() { @@ -88,7 +94,6 @@ class _TaskFormScreenState extends State { } else { _startListening(controller); } - } @override @@ -203,7 +208,27 @@ class _TaskFormScreenState extends State { }, child: const Text('Select Deadline'), ), + const Spacing(), + ElevatedButton( + onPressed: lat != null && lng != null + ? null + : () async { + bool permission = + await PermissionService.askForLocation(); + if (!permission) return; + Position position = + await Geolocator.getCurrentPosition(); + setState(() { + Fluttertoast.showToast( + msg: + "Task will be auto-completed when you are again at this location"); + lat = position.latitude; + lng = position.longitude; + }); + }, + child: const Text("Autocomplete task at current location"), + ), const SizedBox(height: 20), ElevatedButton( onPressed: () { From 23a80e1a09d6396fafba69251edfe88bddebd899 Mon Sep 17 00:00:00 2001 From: Somye Date: Sun, 5 Jan 2025 16:24:17 +0530 Subject: [PATCH 5/9] Added icon to tasks list --- lib/screens/taskform_screen.dart | 2 ++ lib/screens/tasklist_screen.dart | 19 +++++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/lib/screens/taskform_screen.dart b/lib/screens/taskform_screen.dart index 2a71b4d..1cf48f5 100644 --- a/lib/screens/taskform_screen.dart +++ b/lib/screens/taskform_screen.dart @@ -239,6 +239,8 @@ class _TaskFormScreenState extends State { hasDeadline: hasDeadline, deadline: hasDeadline ? deadline : null, color: selectedColor, + lat: lat, + lng: lng, ); Fluttertoast.showToast( msg: editing diff --git a/lib/screens/tasklist_screen.dart b/lib/screens/tasklist_screen.dart index 2e13447..77cf342 100644 --- a/lib/screens/tasklist_screen.dart +++ b/lib/screens/tasklist_screen.dart @@ -99,12 +99,19 @@ class _TaskListScreenState extends State { ), ); }, - title: Text( - task.title, - style: TextStyle( - decoration: - task.isCompleted ? TextDecoration.lineThrough : null, - ), + title: Row( + children: [ + Text( + task.title, + style: TextStyle( + decoration: task.isCompleted + ? TextDecoration.lineThrough + : null, + ), + ), + if (task.lat != null && task.lng != null) + const Icon(Icons.pin_drop_outlined) + ], ), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, From 130dcddfe327a6b4fe3a759eb896d7b7dd44249c Mon Sep 17 00:00:00 2001 From: Somye Date: Sun, 5 Jan 2025 16:40:07 +0530 Subject: [PATCH 6/9] Added core logic --- lib/models/task.dart | 2 + lib/screens/home_screen.dart | 99 ++++++++++++++++++++----------- lib/screens/taskform_screen.dart | 10 ++-- lib/screens/tasklist_screen.dart | 2 +- lib/service/location_service.dart | 16 +++++ 5 files changed, 87 insertions(+), 42 deletions(-) create mode 100644 lib/service/location_service.dart diff --git a/lib/models/task.dart b/lib/models/task.dart index 31c24c4..c78c389 100644 --- a/lib/models/task.dart +++ b/lib/models/task.dart @@ -10,6 +10,8 @@ class Task { double? lat; double? lng; + bool get hasLocationAttached => lat != null && lng != null; + Task({ required this.title, this.description = '', diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index 7707654..acde7eb 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; +import 'package:geolocator/geolocator.dart'; import 'package:taskly/constants.dart'; import 'package:taskly/enums/taskoptions.dart'; +import 'package:taskly/service/location_service.dart'; import 'package:taskly/storage/kudos_storage.dart'; import 'package:taskly/models/kudos.dart'; import 'package:taskly/models/tip.dart'; @@ -27,6 +29,8 @@ class HomeScreen extends StatefulWidget { } class _HomeScreenState extends State { + static const int geofenceRadius = 50; + List tasks = []; Kudos kudos = Kudos(score: 0, history: []); Tip? tip; @@ -38,6 +42,25 @@ class _HomeScreenState extends State { _fetch(); _loadTasks(); _loadKudos(); + _checkCurrentLocation(); + } + + void _checkCurrentLocation() async { + Position? current = await LocationService.getCurrentLocation(); + if (current == null) return; + + List completed = tasks + .where((element) => + element.hasLocationAttached && + !element.isCompleted && + LocationService.getDistance(current.latitude, current.longitude, + element.lat!, element.lng!) < + geofenceRadius) + .toList(); + + for (Task item in completed) { + await _toggleTaskCompletion(tasks.indexOf(item), true); + } } void _fetch() async { @@ -71,7 +94,7 @@ class _HomeScreenState extends State { await TaskStorage.saveTasks(tasks); } - void _toggleTaskCompletion(int index, bool? value) async { + Future _toggleTaskCompletion(int index, bool? value) async { setState(() { tasks[index].isCompleted = value ?? false; @@ -137,14 +160,11 @@ class _HomeScreenState extends State { } else if (option == TaskOption.launchMeditationScreen) { Navigator.push(context, MaterialPageRoute(builder: (context) => const MeditationScreen())); - } - else if (option == TaskOption.toggleTipVisibility) { + } else if (option == TaskOption.toggleTipVisibility) { showtip = !showtip; - } - else if (option == TaskOption.exportToCSV) { + } else if (option == TaskOption.exportToCSV) { exportToCSV(tasks); } - }); } @@ -162,39 +182,47 @@ class _HomeScreenState extends State { await TaskStorage.saveTasks(tasks); } } -void exportToCSV(List tasks) async { - // Prepare CSV data - List> rows = []; - // Add header - rows.add(["Title", "Description", "Is Completed","Has Deadline","Deadline"]); + void exportToCSV(List tasks) async { + // Prepare CSV data + List> rows = []; - // Add data rows - for (var task in tasks) { - rows.add([task.title, task.description, task.isCompleted,task.hasDeadline,'${task.deadline.day}/${task.deadline.month}/${task.deadline.year}']); - } + // Add header + rows.add( + ["Title", "Description", "Is Completed", "Has Deadline", "Deadline"]); - // Convert to CSV string - String csv = const ListToCsvConverter().convert(rows); + // Add data rows + for (var task in tasks) { + rows.add([ + task.title, + task.description, + task.isCompleted, + task.hasDeadline, + '${task.deadline.day}/${task.deadline.month}/${task.deadline.year}' + ]); + } - // Open directory picker - String? directory = await FilePicker.platform.getDirectoryPath(); + // Convert to CSV string + String csv = const ListToCsvConverter().convert(rows); - if (directory == null) { - // User canceled the picker - print("Export canceled."); - return; - } + // Open directory picker + String? directory = await FilePicker.platform.getDirectoryPath(); - // Create the file path - final path = "$directory/tasks.csv"; + if (directory == null) { + // User canceled the picker + print("Export canceled."); + return; + } - // Write the CSV file - final file = File(path); - await file.writeAsString(csv); + // Create the file path + final path = "$directory/tasks.csv"; - print("File saved at: $path"); -} + // Write the CSV file + final file = File(path); + await file.writeAsString(csv); + + print("File saved at: $path"); + } void _loadKudos() async { Kudos loadedKudos = await KudosStorage.loadKudos(); @@ -238,7 +266,9 @@ void exportToCSV(List tasks) async { ), PopupMenuItem( value: TaskOption.toggleTipVisibility, - child: showtip ? const Text("Hide tip of the day") : const Text("Show tip of the day"), + child: showtip + ? const Text("Hide tip of the day") + : const Text("Show tip of the day"), ), const PopupMenuItem( value: TaskOption.exportToCSV, @@ -265,9 +295,8 @@ void exportToCSV(List tasks) async { child: TipOfDayCard(tip: tip), ), secondChild: Container(), - crossFadeState: showtip - ? CrossFadeState.showFirst - : CrossFadeState.showSecond, + crossFadeState: + showtip ? CrossFadeState.showFirst : CrossFadeState.showSecond, duration: const Duration(seconds: 1), ), tasks.isEmpty diff --git a/lib/screens/taskform_screen.dart b/lib/screens/taskform_screen.dart index 1cf48f5..b05841c 100644 --- a/lib/screens/taskform_screen.dart +++ b/lib/screens/taskform_screen.dart @@ -3,7 +3,7 @@ import 'package:fluttertoast/fluttertoast.dart'; import 'package:flutter_colorpicker/flutter_colorpicker.dart'; import 'package:geolocator/geolocator.dart'; import 'package:taskly/models/task.dart'; -import 'package:taskly/service/permission_service.dart'; +import 'package:taskly/service/location_service.dart'; import 'package:taskly/service/speech_service.dart'; import 'package:taskly/utils/date_utils.dart'; import 'package:taskly/widgets/spacing.dart'; @@ -213,12 +213,10 @@ class _TaskFormScreenState extends State { onPressed: lat != null && lng != null ? null : () async { - bool permission = - await PermissionService.askForLocation(); - if (!permission) return; + Position? position = + await LocationService.getCurrentLocation(); + if (position == null) return; - Position position = - await Geolocator.getCurrentPosition(); setState(() { Fluttertoast.showToast( msg: diff --git a/lib/screens/tasklist_screen.dart b/lib/screens/tasklist_screen.dart index 77cf342..8a98632 100644 --- a/lib/screens/tasklist_screen.dart +++ b/lib/screens/tasklist_screen.dart @@ -109,7 +109,7 @@ class _TaskListScreenState extends State { : null, ), ), - if (task.lat != null && task.lng != null) + if (task.hasLocationAttached) const Icon(Icons.pin_drop_outlined) ], ), diff --git a/lib/service/location_service.dart b/lib/service/location_service.dart new file mode 100644 index 0000000..9ab31ff --- /dev/null +++ b/lib/service/location_service.dart @@ -0,0 +1,16 @@ +import 'package:geolocator/geolocator.dart'; +import 'package:taskly/service/permission_service.dart'; + +class LocationService { + static Future getCurrentLocation() async { + bool granted = await PermissionService.askForLocation(); + if (!granted) return null; + + return Geolocator.getCurrentPosition(); + } + + static double getDistance( + double lat1, double lng1, double lat2, double lng2) { + return Geolocator.distanceBetween(lat1, lng1, lat2, lng2); + } +} From e0661d81561af38d008777a82d7a6d738f7a8628 Mon Sep 17 00:00:00 2001 From: Somye Date: Sun, 5 Jan 2025 16:43:42 +0530 Subject: [PATCH 7/9] Added option to detach location --- lib/screens/taskform_screen.dart | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/screens/taskform_screen.dart b/lib/screens/taskform_screen.dart index b05841c..88d87a3 100644 --- a/lib/screens/taskform_screen.dart +++ b/lib/screens/taskform_screen.dart @@ -227,6 +227,15 @@ class _TaskFormScreenState extends State { }, child: const Text("Autocomplete task at current location"), ), + if (lat != null && lng != null) + ElevatedButton( + onPressed: () { + setState(() { + lat = lng = null; + }); + }, + child: const Text("Detach location from task"), + ), const SizedBox(height: 20), ElevatedButton( onPressed: () { From ee4993d942b6568ce0612176eea6c0d76bf9992d Mon Sep 17 00:00:00 2001 From: Somye Date: Sun, 5 Jan 2025 16:54:24 +0530 Subject: [PATCH 8/9] Reverted developer team in ios --- ios/Runner.xcodeproj/project.pbxproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index b97df8e..66e1f60 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -505,7 +505,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = STL7VW4HH6; + DEVELOPMENT_TEAM = AT4J799SCP; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -690,7 +690,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = STL7VW4HH6; + DEVELOPMENT_TEAM = AT4J799SCP; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -713,7 +713,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = STL7VW4HH6; + DEVELOPMENT_TEAM = AT4J799SCP; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( From c393a9704c949d1e38fe70a01dbe851deda891b4 Mon Sep 17 00:00:00 2001 From: Somye Date: Fri, 17 Jan 2025 12:28:18 +0530 Subject: [PATCH 9/9] Merge --- lib/screens/task_box.dart | 2 +- pubspec.yaml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/screens/task_box.dart b/lib/screens/task_box.dart index f13d99c..14aa03c 100644 --- a/lib/screens/task_box.dart +++ b/lib/screens/task_box.dart @@ -158,7 +158,7 @@ class _TaskBoxWidgetState extends State { ), IconButton( icon: const Icon(Icons.share_rounded), - onPressed: onShare, + onPressed: widget.onShare, ), IconButton( icon: const Icon(Icons.edit, color: Colors.blue), diff --git a/pubspec.yaml b/pubspec.yaml index b8a3693..987df78 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -54,7 +54,8 @@ dependencies: flutter_confetti: ^0.3.4 permission_handler: ^11.3.1 choice: ^2.3.2 - share_plus: ^10.1.3 geolocator: ^13.0.2 + share_plus: ^10.1.3 + geolocator: ^13.0.2 dev_dependencies: