Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stage 3 #3

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

<application
android:name=".MainApplication"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.szymonchmalonboarding;

import android.annotation.SuppressLint
import android.content.pm.PackageManager
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import androidx.core.content.ContextCompat.getSystemService
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.Promise
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod

import com.facebook.react.modules.core.PermissionAwareActivity
import com.facebook.react.modules.core.PermissionListener

interface GetPermissionCallback {
fun handle(granted: Boolean)
}

class LocationModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
private var requestCode = 0;

override fun getName() = "LocationModule";

@SuppressLint("MissingPermission")
@ReactMethod
fun getLocation(promise: Promise) {
val locationManager = getSystemService(this.reactApplicationContext.applicationContext, LocationManager::class.java) as LocationManager

getPermission(object: GetPermissionCallback {
override fun handle(granted: Boolean) {
if (!granted) {
promise.reject("no_permission", "Location permission denied")
return
}

val locationListener = object :LocationListener {
override fun onLocationChanged(location: Location) {
val readableValueMap = Arguments.createMap()
readableValueMap.putDouble("lat", location.latitude)
readableValueMap.putDouble("lng", location.longitude)
promise.resolve(readableValueMap)

locationManager.removeUpdates(this)
}

override fun onLocationChanged(locations: List<Location?>) {
onLocationChanged(locations.last()!!)
}

}


locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
0L,
0f,
locationListener as LocationListener
)
}
})

}

private fun getPermission(callback: GetPermissionCallback) {
val activity = reactApplicationContext.currentActivity as PermissionAwareActivity;

if (activity.checkSelfPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED){
callback.handle(true);
return
}

activity.requestPermissions(
arrayOf(android.Manifest.permission.ACCESS_COARSE_LOCATION),
requestCode,
object: PermissionListener {
override fun onRequestPermissionsResult(
p0: Int,
p1: Array<out String>?,
p2: IntArray?
): Boolean {
if (p0 == PackageManager.PERMISSION_GRANTED) {
callback.handle(true)
} else {
callback.handle(false)
}

return true
}
}
)

requestCode++;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class MainApplication : Application(), ReactApplication {
object : DefaultReactNativeHost(this) {
override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply {
add(MyAppPackage())
// Packages that cannot be autolinked yet can be added manually here, for example:
// add(MyReactNativePackage())
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.szymonchmalonboarding;

import android.view.View
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ReactShadowNode
import com.facebook.react.uimanager.ViewManager

class MyAppPackage : ReactPackage {

override fun createViewManagers(
reactContext: ReactApplicationContext
): MutableList<ViewManager<View, ReactShadowNode<*>>> = mutableListOf()

override fun createNativeModules(
reactContext: ReactApplicationContext
): MutableList<NativeModule> = listOf(LocationModule(reactContext)).toMutableList()
}
2 changes: 1 addition & 1 deletion ios/.xcode.env
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
# Customize the NODE_BINARY variable here.
# For example, to use nvm with brew, add the following line
# . "$(brew --prefix nvm)/nvm.sh" --no-use
export NODE_BINARY=$(command -v node)
export NODE_BINARY=/opt/homebrew/bin/node
8 changes: 8 additions & 0 deletions ios/RCTLocationModule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#import <React/RCTBridgeModule.h>
#import <CoreLocation/CoreLocation.h>

@interface RCTLocationModule : NSObject <RCTBridgeModule, CLLocationManagerDelegate>
@property (nonatomic, strong) CLLocationManager *locationManager;
@property (nonatomic, copy) RCTPromiseResolveBlock resolveBlock;
@property (nonatomic, copy) RCTPromiseRejectBlock rejectBlock;
@end
70 changes: 70 additions & 0 deletions ios/RCTLocationModule.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#import "RCTLocationModule.h"

@implementation RCTLocationModule

RCT_EXPORT_METHOD(getLocation:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
{
self.resolveBlock = resolve;
self.rejectBlock = reject;

if ([CLLocationManager locationServicesEnabled]) {
dispatch_async(dispatch_get_main_queue(), ^{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;

CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
if (status == kCLAuthorizationStatusNotDetermined) {
[self.locationManager requestWhenInUseAuthorization];
} else if (status == kCLAuthorizationStatusDenied || status == kCLAuthorizationStatusRestricted) {
reject(@"no_permission", @"Location permission denied", nil);
return;
} else {
[self.locationManager startUpdatingLocation];
}
});
} else {
reject(@"no_location_services", @"Location services were disabled", nil);
}
}

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status == kCLAuthorizationStatusAuthorizedAlways) {
[self.locationManager startUpdatingLocation];
} else if (status == kCLAuthorizationStatusDenied || status == kCLAuthorizationStatusRestricted) {
if (self.rejectBlock) {
self.rejectBlock(@"no_permission", @"Location permission denied", nil);
self.resolveBlock = nil;
self.rejectBlock = nil;
}
}
}

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
CLLocation* location = [locations lastObject];
if (location) {
NSDictionary* locationData = @{
@"lat": @(location.coordinate.latitude),
@"lng": @(location.coordinate.longitude)
};
if (self.resolveBlock) {
self.resolveBlock(locationData);
self.resolveBlock = nil;
self.rejectBlock = nil;
}
[self.locationManager stopUpdatingLocation];
}
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
if (self.rejectBlock) {
self.rejectBlock(@"location_error", @"Failed to get location", error);
self.resolveBlock = nil;
self.rejectBlock = nil;
}
}

RCT_EXPORT_MODULE();

@end
4 changes: 4 additions & 0 deletions ios/SzymonChmalOnboarding-Bridging-Header.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//

24 changes: 14 additions & 10 deletions ios/SzymonChmalOnboarding.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
7699B88040F8A987B510C191 /* libPods-SzymonChmalOnboarding-SzymonChmalOnboardingTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-SzymonChmalOnboarding-SzymonChmalOnboardingTests.a */; };
7987D3182C636B3B0008EC69 /* RCTLocationModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 7987D3172C636B3B0008EC69 /* RCTLocationModule.m */; };
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
BF6369CD67B82A0211DAA5A7 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 89ED16A7E4D8C9FFA24ACD9F /* PrivacyInfo.xcprivacy */; };
/* End PBXBuildFile section */
Expand Down Expand Up @@ -43,9 +44,12 @@
5709B34CF0A7D63546082F79 /* Pods-SzymonChmalOnboarding.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SzymonChmalOnboarding.release.xcconfig"; path = "Target Support Files/Pods-SzymonChmalOnboarding/Pods-SzymonChmalOnboarding.release.xcconfig"; sourceTree = "<group>"; };
5B7EB9410499542E8C5724F5 /* Pods-SzymonChmalOnboarding-SzymonChmalOnboardingTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SzymonChmalOnboarding-SzymonChmalOnboardingTests.debug.xcconfig"; path = "Target Support Files/Pods-SzymonChmalOnboarding-SzymonChmalOnboardingTests/Pods-SzymonChmalOnboarding-SzymonChmalOnboardingTests.debug.xcconfig"; sourceTree = "<group>"; };
5DCACB8F33CDC322A6C60F78 /* libPods-SzymonChmalOnboarding.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SzymonChmalOnboarding.a"; sourceTree = BUILT_PRODUCTS_DIR; };
79130B9B2C636EB400DC0F52 /* SzymonChmalOnboarding-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SzymonChmalOnboarding-Bridging-Header.h"; sourceTree = "<group>"; };
7987D3162C636AFB0008EC69 /* RCTLocationModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTLocationModule.h; sourceTree = "<group>"; };
7987D3172C636B3B0008EC69 /* RCTLocationModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RCTLocationModule.m; sourceTree = "<group>"; };
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = SzymonChmalOnboarding/LaunchScreen.storyboard; sourceTree = "<group>"; };
89C6BE57DB24E9ADA2F236DE /* Pods-SzymonChmalOnboarding-SzymonChmalOnboardingTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SzymonChmalOnboarding-SzymonChmalOnboardingTests.release.xcconfig"; path = "Target Support Files/Pods-SzymonChmalOnboarding-SzymonChmalOnboardingTests/Pods-SzymonChmalOnboarding-SzymonChmalOnboardingTests.release.xcconfig"; sourceTree = "<group>"; };
89ED16A7E4D8C9FFA24ACD9F /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = SzymonChmalOnboarding/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
89ED16A7E4D8C9FFA24ACD9F /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = SzymonChmalOnboarding/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -97,6 +101,9 @@
13B07FB71A68108700A75B9A /* main.m */,
13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */,
89ED16A7E4D8C9FFA24ACD9F /* PrivacyInfo.xcprivacy */,
7987D3162C636AFB0008EC69 /* RCTLocationModule.h */,
7987D3172C636B3B0008EC69 /* RCTLocationModule.m */,
79130B9B2C636EB400DC0F52 /* SzymonChmalOnboarding-Bridging-Header.h */,
);
name = SzymonChmalOnboarding;
sourceTree = "<group>";
Expand Down Expand Up @@ -211,7 +218,7 @@
TestTargetID = 13B07F861A680F5B00A75B9A;
};
13B07F861A680F5B00A75B9A = {
LastSwiftMigration = 1120;
LastSwiftMigration = 1540;
};
};
};
Expand Down Expand Up @@ -400,6 +407,7 @@
files = (
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
7987D3182C636B3B0008EC69 /* RCTLocationModule.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -486,6 +494,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SzymonChmalOnboarding;
SWIFT_OBJC_BRIDGING_HEADER = "SzymonChmalOnboarding-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
Expand All @@ -512,6 +521,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SzymonChmalOnboarding;
SWIFT_OBJC_BRIDGING_HEADER = "SzymonChmalOnboarding-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
Expand Down Expand Up @@ -590,10 +600,7 @@
"-DFOLLY_CFG_NO_COROUTINES=1",
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
);
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
OTHER_LDFLAGS = "$(inherited) ";
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
USE_HERMES = true;
Expand Down Expand Up @@ -665,10 +672,7 @@
"-DFOLLY_CFG_NO_COROUTINES=1",
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
);
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
OTHER_LDFLAGS = "$(inherited) ";
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
USE_HERMES = true;
Expand Down
2 changes: 1 addition & 1 deletion ios/SzymonChmalOnboarding/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<true/>
</dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<string>Show the weather at your current location.</string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
Expand Down
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions src/modules/location/api/getCurrentLocation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {NativeModules} from 'react-native';
import {Position} from '../model/Position.ts';

export const getCurrentLocation = (): Promise<Position> => {
return NativeModules.LocationModule.getLocation();
};
Loading