@pinwheel/react-native-pinwheel 2.3.17 → 2.5.0-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +64 -0
- package/README.md +6 -9
- package/RNPinwheelSDK.podspec +18 -0
- package/android/build.gradle +50 -0
- package/android/src/main/AndroidManifest.xml +6 -0
- package/android/src/main/java/com/underdog_tech/react/PinwheelPackage.kt +16 -0
- package/android/src/main/java/com/underdog_tech/react/PinwheelViewManager.kt +213 -0
- package/android/src/main/java/com/underdog_tech/react/RNTPinwheelEvents.kt +51 -0
- package/{lib/constants.d.ts → constants.d.ts} +1 -1
- package/{lib/constants.js → constants.js} +1 -1
- package/{lib/index.d.ts → index.d.ts} +11 -11
- package/index.js +52 -0
- package/ios/RNTPinwheelEvents.h +9 -0
- package/ios/RNTPinwheelEvents.m +62 -0
- package/ios/RNTPinwheelManager.m +21 -0
- package/ios/RNTPinwheelView.h +12 -0
- package/ios/RNTPinwheelView.m +65 -0
- package/package.json +5 -18
- package/pinwheel-view.d.ts +6 -0
- package/pinwheel-view.js +2 -0
- package/pinwheel-wrapper.android.d.ts +4 -0
- package/pinwheel-wrapper.android.js +28 -0
- package/pinwheel-wrapper.ios.d.ts +4 -0
- package/pinwheel-wrapper.ios.js +17 -0
- package/lib/index.js +0 -122
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## 2.4.x Releases
|
|
6
|
+
|
|
7
|
+
### [2.4.0](https://github.com/underdog-tech/react-native-pinwheel/releases/tag/2.4.0)
|
|
8
|
+
|
|
9
|
+
- Removing `overrides` from main package.
|
|
10
|
+
- Updating example app to use newest ReactNative versions.
|
|
11
|
+
- Changing devDependencies to use newest React Native Webview (for typing).
|
|
12
|
+
|
|
13
|
+
## 2.3.x Releases
|
|
14
|
+
|
|
15
|
+
- `2.3.x` Releases - [2.3.4](#234) | [2.3.5](#235) | [2.3.6](#236) | [2.3.10](#2310) | [2.3.12](#2312) | [2.3.13](#2313) | [2.3.14](#2314) | [2.3.17](#2317)
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
### [2.3.17](https://github.com/underdog-tech/react-native-pinwheel/releases/tag/2.3.17)
|
|
20
|
+
|
|
21
|
+
Export `ScreenTransition` event payload type for the `screen_transition` event.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### [2.3.14](https://github.com/underdog-tech/react-native-pinwheel/releases/tag/2.3.14)
|
|
25
|
+
|
|
26
|
+
Remove `hermes-engine` and `shell-quote` sub-dependencies from package-lock files.
|
|
27
|
+
|
|
28
|
+
### [2.3.13](https://github.com/underdog-tech/react-native-pinwheel/releases/tag/2.3.13)
|
|
29
|
+
|
|
30
|
+
Bump `hermes-engine` and `shell-quote` sub-dependency package.
|
|
31
|
+
|
|
32
|
+
### [2.3.12](https://github.com/underdog-tech/react-native-pinwheel/releases/tag/2.3.12)
|
|
33
|
+
|
|
34
|
+
Add CircleCI scripting and local scripts.
|
|
35
|
+
- Add `npm run dev` script.
|
|
36
|
+
- Remove need for hardcoding api secret in code to run locally.
|
|
37
|
+
|
|
38
|
+
### [2.3.10](https://github.com/underdog-tech/react-native-pinwheel/releases/tag/2.3.10)
|
|
39
|
+
|
|
40
|
+
Use node 16.7.0 instead of 12.16.1 to install dependencies.
|
|
41
|
+
|
|
42
|
+
### [2.3.6](https://github.com/underdog-tech/react-native-pinwheel/releases/tag/2.3.6)
|
|
43
|
+
|
|
44
|
+
N/A
|
|
45
|
+
|
|
46
|
+
### [2.3.5](https://github.com/underdog-tech/react-native-pinwheel/releases/tag/2.3.5)
|
|
47
|
+
|
|
48
|
+
N/A
|
|
49
|
+
|
|
50
|
+
### [2.3.4](https://github.com/underdog-tech/react-native-pinwheel/releases/tag/2.3.4)
|
|
51
|
+
|
|
52
|
+
#### Added
|
|
53
|
+
|
|
54
|
+
- Export `EventPayload` type.
|
|
55
|
+
- Export `PinwheelError` type.
|
|
56
|
+
- Export `PinwheelErrorType` type.
|
|
57
|
+
- Export `EmptyPayloadObject` type as `Record<string, never>`.
|
|
58
|
+
|
|
59
|
+
##### Updated
|
|
60
|
+
|
|
61
|
+
- `EventPayload` is no longer a union containing `{}`. It now contains `Record<string, never>` instead due to [this behavior](https://github.com/Microsoft/TypeScript/wiki/FAQ#why-are-all-types-assignable-to-empty-interfaces).
|
|
62
|
+
- Mark exported `Error` type as **@deprecated** because it collides with the built-in javascript `Error` object. Replaced with `PinwheelError`.
|
|
63
|
+
- Mark exported `ErrorType` type as **@deprecated** because the new naming convention is prefixing with "`PinwheelError`". Replaced with `PinwheelErrorType`.
|
|
64
|
+
- Update `onExit` type to be `(error: PinwheelError | Record<string, never>)` to be accurate with current functionality.
|
package/README.md
CHANGED
|
@@ -28,17 +28,14 @@ You may want to run the example app locally to get started.
|
|
|
28
28
|
###### Failed to build iOS project. We ran "xcodebuild" command but it exited with error code 65
|
|
29
29
|
- Try downloading Xcode 14.2 from https://developer.apple.com/download/all/?q=xcode
|
|
30
30
|
|
|
31
|
+
###### Failed to locate 'git', requesting installation of command line developer tools
|
|
32
|
+
For this or other errors related to command line developer tools:
|
|
33
|
+
- Make sure you have Command Line Tools for Xcode 14.2 installed
|
|
34
|
+
- Open Xcode > Click Xcode in the app menu > Settings > Locations > Command Line Tools dropdown and set the correct location
|
|
31
35
|
|
|
32
36
|
## Installation
|
|
33
37
|
|
|
34
|
-
1. Install
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
$ npm install --save react-native-webview
|
|
38
|
-
$ cd ios && pod install
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
2. Install Pinwheel React Native SDK
|
|
38
|
+
1. Install Pinwheel React Native SDK
|
|
42
39
|
|
|
43
40
|
```bash
|
|
44
41
|
$ npm install --save @pinwheel/react-native-pinwheel
|
|
@@ -50,7 +47,7 @@ $ npm install --save @pinwheel/react-native-pinwheel
|
|
|
50
47
|
|
|
51
48
|
To initialize Link Modal, a short-lived link token will need to be generated first. Your server can generate the link token by sending a POST request to the /v1/link_tokens endpoint. DO NOT ever send this request from the client side and publicly expose your api_secret.
|
|
52
49
|
|
|
53
|
-
The link token returned is valid for
|
|
50
|
+
The link token returned is valid for one hour, after which it expires and can no longer be used to initialize Link. The expiration time is returned as a unix timestamp.
|
|
54
51
|
|
|
55
52
|
### Pinwheel Component
|
|
56
53
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Pod::Spec.new do |s|
|
|
2
|
+
s.name = "RNPinwheelSDK"
|
|
3
|
+
s.version = "2.5.0-alpha"
|
|
4
|
+
s.summary = "React Native plugin for Pinwheel's SDK"
|
|
5
|
+
s.description = <<-DESC
|
|
6
|
+
An open source React Native plugin for calling Pinwheel's native SDKs to manage payroll data.
|
|
7
|
+
DESC
|
|
8
|
+
s.homepage = "https://github.com/underdog-tech/react-native-pinwheel"
|
|
9
|
+
s.license = { :file => 'LICENSE' }
|
|
10
|
+
s.author = { 'Pinwheel' => 'info@pinwheelapi.com' }
|
|
11
|
+
s.platform = :ios, "12.0"
|
|
12
|
+
s.source = { :path => 'ios' }
|
|
13
|
+
s.source_files = "ios/**/*.{h,m}"
|
|
14
|
+
s.public_header_files = 'ios/**/*.h'
|
|
15
|
+
s.requires_arc = true
|
|
16
|
+
s.dependency "React"
|
|
17
|
+
s.dependency 'PinwheelSDK', '2.4.3'
|
|
18
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
def kotlin_version = rootProject.ext.has('kotlinVersion') ? rootProject.ext.get('kotlinVersion') : '1.7.22'
|
|
3
|
+
|
|
4
|
+
repositories {
|
|
5
|
+
google()
|
|
6
|
+
mavenCentral()
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
dependencies {
|
|
10
|
+
classpath 'com.android.tools.build:gradle:7.2.2'
|
|
11
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
apply plugin: 'com.android.library'
|
|
16
|
+
apply plugin: 'kotlin-android'
|
|
17
|
+
|
|
18
|
+
def MIN_PW_SDK_VERSION = '2.4.1'
|
|
19
|
+
|
|
20
|
+
android {
|
|
21
|
+
compileSdkVersion 33
|
|
22
|
+
|
|
23
|
+
defaultConfig {
|
|
24
|
+
minSdkVersion 24
|
|
25
|
+
targetSdkVersion 33
|
|
26
|
+
versionCode 1
|
|
27
|
+
versionName "1.0"
|
|
28
|
+
}
|
|
29
|
+
compileOptions {
|
|
30
|
+
sourceCompatibility = 1.8
|
|
31
|
+
targetCompatibility = 1.8
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
sourceSets {
|
|
35
|
+
main.java.srcDirs += 'src/main/java'
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
rootProject.allprojects {
|
|
40
|
+
repositories {
|
|
41
|
+
google()
|
|
42
|
+
mavenCentral()
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
dependencies {
|
|
47
|
+
def pwVersion = rootProject.hasProperty('pwVersion') ? rootProject.pwVersion : MIN_PW_SDK_VERSION
|
|
48
|
+
implementation 'com.facebook.react:react-native:+'
|
|
49
|
+
implementation "com.getpinwheel:pinwheel-android:$pwVersion"
|
|
50
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package com.underdog_tech.react
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage
|
|
4
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
5
|
+
import com.facebook.react.bridge.NativeModule
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager
|
|
7
|
+
|
|
8
|
+
class PinwheelPackage : ReactPackage {
|
|
9
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
10
|
+
return listOf(RNTPinwheelEvents(reactContext)).toMutableList()
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
override fun createViewManagers(
|
|
14
|
+
reactContext: ReactApplicationContext
|
|
15
|
+
) = listOf(PinwheelViewManager(reactContext))
|
|
16
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
package com.underdog_tech.react
|
|
2
|
+
|
|
3
|
+
import android.view.Choreographer
|
|
4
|
+
import android.view.View
|
|
5
|
+
import android.view.ViewGroup
|
|
6
|
+
import android.widget.FrameLayout
|
|
7
|
+
import androidx.fragment.app.FragmentActivity
|
|
8
|
+
import com.facebook.react.bridge.Arguments
|
|
9
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
10
|
+
import com.facebook.react.bridge.ReadableArray
|
|
11
|
+
import com.facebook.react.bridge.WritableMap
|
|
12
|
+
import com.facebook.react.bridge.WritableNativeMap
|
|
13
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
14
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
15
|
+
import com.facebook.react.uimanager.ViewGroupManager
|
|
16
|
+
import com.facebook.react.uimanager.annotations.ReactPropGroup
|
|
17
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
18
|
+
import com.underdog_tech.pinwheel_android.PinwheelFragment
|
|
19
|
+
import com.underdog_tech.pinwheel_android.PinwheelEventListener
|
|
20
|
+
import com.underdog_tech.pinwheel_android.model.PinwheelEventType
|
|
21
|
+
import com.underdog_tech.pinwheel_android.model.PinwheelEventPayload
|
|
22
|
+
import com.underdog_tech.pinwheel_android.model.PinwheelAmount
|
|
23
|
+
import com.underdog_tech.pinwheel_android.model.PinwheelTarget
|
|
24
|
+
import com.underdog_tech.pinwheel_android.model.PinwheelAllocation
|
|
25
|
+
import com.underdog_tech.pinwheel_android.model.PinwheelParams
|
|
26
|
+
import com.underdog_tech.pinwheel_android.model.PinwheelResult
|
|
27
|
+
import com.underdog_tech.pinwheel_android.model.PinwheelError
|
|
28
|
+
import com.underdog_tech.pinwheel_android.model.PinwheelSelectedEmployerPayload
|
|
29
|
+
import com.underdog_tech.pinwheel_android.model.PinwheelSelectedPlatformPayload
|
|
30
|
+
import com.underdog_tech.pinwheel_android.model.PinwheelLoginPayload
|
|
31
|
+
import com.underdog_tech.pinwheel_android.model.PinwheelLoginAttemptPayload
|
|
32
|
+
import com.underdog_tech.pinwheel_android.model.PinwheelDDFormCreatePayload
|
|
33
|
+
import com.underdog_tech.pinwheel_android.model.PinwheelScreenTransitionPayload
|
|
34
|
+
import com.underdog_tech.pinwheel_android.model.PinwheelInputAmountPayload
|
|
35
|
+
|
|
36
|
+
fun PinwheelTarget.toWritableMap(): WritableMap {
|
|
37
|
+
return Arguments.createMap().apply {
|
|
38
|
+
putString("accountType", this@toWritableMap.accountType)
|
|
39
|
+
putString("accountName", this@toWritableMap.accountName)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
fun PinwheelAllocation.toWritableMap(): WritableMap {
|
|
44
|
+
return Arguments.createMap().apply {
|
|
45
|
+
putString("type", this@toWritableMap.type)
|
|
46
|
+
this@toWritableMap.value?.let { putDouble("value", it.toDouble()) }
|
|
47
|
+
putMap("target", this@toWritableMap.target?.toWritableMap())
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
fun PinwheelParams.toWritableMap(): WritableMap {
|
|
52
|
+
return Arguments.createMap().apply {
|
|
53
|
+
putMap("amount", this@toWritableMap.amount?.toWritableMap())
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
fun PinwheelEventPayload.toWritableMap(): WritableMap = when (this) {
|
|
58
|
+
is PinwheelAmount -> Arguments.createMap().apply {
|
|
59
|
+
putDouble("value", this@toWritableMap.value.toDouble())
|
|
60
|
+
putString("unit", this@toWritableMap.unit)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
is PinwheelInputAmountPayload -> Arguments.createMap().apply {
|
|
64
|
+
putString("action", this@toWritableMap.action)
|
|
65
|
+
putMap("allocation", this@toWritableMap.allocation?.toWritableMap())
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
is PinwheelResult -> Arguments.createMap().apply {
|
|
69
|
+
putString("accountId", this@toWritableMap.accountId)
|
|
70
|
+
putString("platformId", this@toWritableMap.platformId)
|
|
71
|
+
putString("job", this@toWritableMap.job)
|
|
72
|
+
putMap("params", this@toWritableMap.params?.toWritableMap())
|
|
73
|
+
}
|
|
74
|
+
is PinwheelError -> Arguments.createMap().apply {
|
|
75
|
+
putString("type", this@toWritableMap.type)
|
|
76
|
+
putString("code", this@toWritableMap.code)
|
|
77
|
+
putString("message", this@toWritableMap.message)
|
|
78
|
+
putBoolean("pendingRetry", this@toWritableMap.pendingRetry)
|
|
79
|
+
}
|
|
80
|
+
is PinwheelSelectedEmployerPayload -> Arguments.createMap().apply {
|
|
81
|
+
putString("selectedEmployerId", this@toWritableMap.selectedEmployerId)
|
|
82
|
+
putString("selectedEmployerName", this@toWritableMap.selectedEmployerName)
|
|
83
|
+
}
|
|
84
|
+
is PinwheelSelectedPlatformPayload -> Arguments.createMap().apply {
|
|
85
|
+
putString("selectedPlatformId", this@toWritableMap.selectedPlatformId)
|
|
86
|
+
putString("selectedPlatformName", this@toWritableMap.selectedPlatformName)
|
|
87
|
+
}
|
|
88
|
+
is PinwheelLoginPayload -> Arguments.createMap().apply {
|
|
89
|
+
putString("accountId", this@toWritableMap.accountId)
|
|
90
|
+
putString("platformId", this@toWritableMap.platformId)
|
|
91
|
+
}
|
|
92
|
+
is PinwheelLoginAttemptPayload -> Arguments.createMap().apply {
|
|
93
|
+
putString("platformId", this@toWritableMap.platformId)
|
|
94
|
+
}
|
|
95
|
+
is PinwheelDDFormCreatePayload -> Arguments.createMap().apply {
|
|
96
|
+
putString("url", this@toWritableMap.url)
|
|
97
|
+
}
|
|
98
|
+
is PinwheelScreenTransitionPayload -> Arguments.createMap().apply {
|
|
99
|
+
putString("screenName", this@toWritableMap.screenName)
|
|
100
|
+
putString("selectedEmployerId", this@toWritableMap.selectedEmployerId)
|
|
101
|
+
putString("selectedEmployerName", this@toWritableMap.selectedEmployerName)
|
|
102
|
+
putString("selectedPlatformId", this@toWritableMap.selectedPlatformId)
|
|
103
|
+
putString("selectedPlatformName", this@toWritableMap.selectedPlatformName)
|
|
104
|
+
}
|
|
105
|
+
else -> throw IllegalArgumentException("Unsupported PinwheelEventPayload type")
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
class PinwheelViewManager(
|
|
109
|
+
private val reactContext: ReactApplicationContext
|
|
110
|
+
) : ViewGroupManager<FrameLayout>(), PinwheelEventListener {
|
|
111
|
+
private var propWidth: Int? = reactContext.resources.displayMetrics.widthPixels
|
|
112
|
+
private var propHeight: Int? = reactContext.resources.displayMetrics.heightPixels
|
|
113
|
+
private var token: String? = null
|
|
114
|
+
|
|
115
|
+
override fun getName() = REACT_CLASS
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Return a FrameLayout which will later hold the Fragment
|
|
119
|
+
*/
|
|
120
|
+
override fun createViewInstance(reactContext: ThemedReactContext): FrameLayout {
|
|
121
|
+
return FrameLayout(reactContext)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Map the "create" command to an integer
|
|
126
|
+
*/
|
|
127
|
+
override fun getCommandsMap() = mapOf("create" to COMMAND_CREATE)
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Handle "create" command (called from JS) and call createFragment method
|
|
131
|
+
*/
|
|
132
|
+
override fun receiveCommand(
|
|
133
|
+
root: FrameLayout,
|
|
134
|
+
commandId: String,
|
|
135
|
+
args: ReadableArray?
|
|
136
|
+
) {
|
|
137
|
+
super.receiveCommand(root, commandId, args)
|
|
138
|
+
val reactNativeViewId = requireNotNull(args).getInt(0)
|
|
139
|
+
|
|
140
|
+
when (commandId.toInt()) {
|
|
141
|
+
COMMAND_CREATE -> createFragment(root, reactNativeViewId)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
@ReactPropGroup(names = ["width", "height"], customType = "Style")
|
|
146
|
+
fun setStyle(view: FrameLayout, index: Int, value: Int) {
|
|
147
|
+
if (index == 0) propWidth = value
|
|
148
|
+
if (index == 1) propHeight = value
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@ReactProp(name="token")
|
|
152
|
+
fun setToken(view: FrameLayout, token: String) {
|
|
153
|
+
this.token = token
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Replace your React Native view with a custom fragment
|
|
158
|
+
*/
|
|
159
|
+
fun createFragment(root: FrameLayout, reactNativeViewId: Int) {
|
|
160
|
+
val parentView = root.findViewById<ViewGroup>(reactNativeViewId)
|
|
161
|
+
setupLayout(parentView)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
this.token?.let {
|
|
165
|
+
val pinwheelFragment = PinwheelFragment.newInstance(it, "react native")
|
|
166
|
+
pinwheelFragment.pinwheelEventListener = this
|
|
167
|
+
val activity = reactContext.currentActivity as FragmentActivity
|
|
168
|
+
activity.supportFragmentManager
|
|
169
|
+
.beginTransaction()
|
|
170
|
+
.replace(reactNativeViewId, pinwheelFragment, reactNativeViewId.toString())
|
|
171
|
+
.commit()
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
fun setupLayout(view: View) {
|
|
176
|
+
Choreographer.getInstance().postFrameCallback(object: Choreographer.FrameCallback {
|
|
177
|
+
override fun doFrame(frameTimeNanos: Long) {
|
|
178
|
+
manuallyLayoutChildren(view)
|
|
179
|
+
view.viewTreeObserver.dispatchOnGlobalLayout()
|
|
180
|
+
Choreographer.getInstance().postFrameCallback(this)
|
|
181
|
+
}
|
|
182
|
+
})
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
override fun onEvent(eventName: PinwheelEventType, payload: PinwheelEventPayload?) {
|
|
186
|
+
val params = WritableNativeMap()
|
|
187
|
+
params.putString("name", eventName.toString())
|
|
188
|
+
params.putMap("payload", payload?.toWritableMap())
|
|
189
|
+
reactContext
|
|
190
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
191
|
+
.emit("PINWHEEL_EVENT", params)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Layout all children properly
|
|
196
|
+
*/
|
|
197
|
+
private fun manuallyLayoutChildren(view: View) {
|
|
198
|
+
// propWidth and propHeight coming from react-native props
|
|
199
|
+
val width = requireNotNull(propWidth)
|
|
200
|
+
val height = requireNotNull(propHeight)
|
|
201
|
+
|
|
202
|
+
view.measure(
|
|
203
|
+
View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
|
|
204
|
+
View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY))
|
|
205
|
+
|
|
206
|
+
view.layout(0, 0, width, height)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
companion object {
|
|
210
|
+
private const val REACT_CLASS = "RNTPinwheel"
|
|
211
|
+
private const val COMMAND_CREATE = 1
|
|
212
|
+
}
|
|
213
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
package com.underdog_tech.react
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
5
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
6
|
+
import com.facebook.react.bridge.ReactMethod
|
|
7
|
+
import com.facebook.react.bridge.WritableMap
|
|
8
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
9
|
+
|
|
10
|
+
class RNTPinwheelEvents(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
|
|
11
|
+
companion object {
|
|
12
|
+
private const val EVENT_KEY = "PINWHEEL_EVENT"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
override fun getName(): String {
|
|
16
|
+
return "RNTPinwheelEvents"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@ReactMethod
|
|
20
|
+
fun anExposedMethod() {
|
|
21
|
+
val currentContext = reactApplicationContext
|
|
22
|
+
val eventName = "PINWHEEL_EVENT"
|
|
23
|
+
val params: WritableMap = Arguments.createMap().apply {
|
|
24
|
+
putString("type", "myEventType")
|
|
25
|
+
}
|
|
26
|
+
sendEvent(currentContext, eventName, params)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
fun sendEvent(reactContext: ReactApplicationContext, eventName: String, params: WritableMap?) {
|
|
30
|
+
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java).emit(eventName, params)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private var listenerCount = 0
|
|
34
|
+
|
|
35
|
+
@ReactMethod
|
|
36
|
+
fun addListener(eventName: String) {
|
|
37
|
+
if (listenerCount == 0) {
|
|
38
|
+
// Set up any upstream listeners or background tasks as necessary
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
listenerCount += 1
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@ReactMethod
|
|
45
|
+
fun removeListeners(count: Int) {
|
|
46
|
+
listenerCount -= count
|
|
47
|
+
if (listenerCount == 0) {
|
|
48
|
+
// Remove upstream listeners, stop unnecessary background tasks
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Importing package.json here causes a problem with the folder structure when we npm pack and publish.
|
|
3
3
|
*/
|
|
4
|
-
export declare const VERSION = "2.
|
|
4
|
+
export declare const VERSION = "2.5.0-alpha";
|
|
5
5
|
export declare const LINK_PAGE_URL = "https://cdn.getpinwheel.com/link-v2.3.0.html";
|
|
6
6
|
export declare const PINWHEEL_DOMAIN = "getpinwheel.com";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Importing package.json here causes a problem with the folder structure when we npm pack and publish.
|
|
3
3
|
*/
|
|
4
|
-
export const VERSION = '2.
|
|
4
|
+
export const VERSION = '2.5.0-alpha';
|
|
5
5
|
export const LINK_PAGE_URL = 'https://cdn.getpinwheel.com/link-v2.3.0.html';
|
|
6
6
|
export const PINWHEEL_DOMAIN = 'getpinwheel.com';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import React from 'react';
|
|
2
2
|
export declare const PINWHEEL_MESSAGE_TYPES: {
|
|
3
3
|
PINWHEEL_EXIT: string;
|
|
4
4
|
PINWHEEL_MODAL_CLOSE: string;
|
|
@@ -6,7 +6,7 @@ export declare const PINWHEEL_MESSAGE_TYPES: {
|
|
|
6
6
|
PINWHEEL_SUCCESS: string;
|
|
7
7
|
PINWHEEL_EVENT: string;
|
|
8
8
|
};
|
|
9
|
-
export
|
|
9
|
+
export type LinkResult = {
|
|
10
10
|
accountId: string;
|
|
11
11
|
platformId: string;
|
|
12
12
|
job: string;
|
|
@@ -17,7 +17,7 @@ export declare type LinkResult = {
|
|
|
17
17
|
};
|
|
18
18
|
};
|
|
19
19
|
};
|
|
20
|
-
export
|
|
20
|
+
export type ScreenTransition = {
|
|
21
21
|
screenName: string;
|
|
22
22
|
selectedEmployerId?: string;
|
|
23
23
|
selectedEmployerName?: string;
|
|
@@ -28,21 +28,21 @@ export declare type ScreenTransition = {
|
|
|
28
28
|
* @deprecated This type will be removed in version 2.4. Use the renamed type `PinwheelErrorType`
|
|
29
29
|
* instead.
|
|
30
30
|
*/
|
|
31
|
-
export
|
|
32
|
-
export
|
|
31
|
+
export type ErrorType = 'clientError' | 'systemError' | 'userActionRequired' | 'platformError' | 'invalidAccountsConfiguration' | 'invalidUserInput' | 'invalidLinkToken';
|
|
32
|
+
export type PinwheelErrorType = ErrorType;
|
|
33
33
|
/**
|
|
34
34
|
* @deprecated The type should not be used as it clashes with the native JS `Error` object.
|
|
35
35
|
* You should use `PinwheelError` instead. `Error` will be removed in version 2.4
|
|
36
36
|
*/
|
|
37
|
-
export
|
|
37
|
+
export type Error = {
|
|
38
38
|
type: PinwheelErrorType;
|
|
39
39
|
code: string;
|
|
40
40
|
message: string;
|
|
41
41
|
pendingRetry: boolean;
|
|
42
42
|
};
|
|
43
|
-
export
|
|
44
|
-
export
|
|
45
|
-
export
|
|
43
|
+
export type PinwheelError = Error;
|
|
44
|
+
export type EmptyPayloadObject = Record<string, never>;
|
|
45
|
+
export type EventPayload = {
|
|
46
46
|
selectedEmployerId: string;
|
|
47
47
|
selectedEmployerName: string;
|
|
48
48
|
} | {
|
|
@@ -55,7 +55,7 @@ export declare type EventPayload = {
|
|
|
55
55
|
accountId: string;
|
|
56
56
|
platformId: string;
|
|
57
57
|
} | ScreenTransition | PinwheelError | EmptyPayloadObject | undefined;
|
|
58
|
-
|
|
58
|
+
type PinwheelProps = {
|
|
59
59
|
linkToken: string;
|
|
60
60
|
onLogin?: (result: {
|
|
61
61
|
accountId: string;
|
|
@@ -69,5 +69,5 @@ declare type PinwheelProps = {
|
|
|
69
69
|
onExit?: (error: PinwheelError | EmptyPayloadObject) => void;
|
|
70
70
|
onEvent?: (eventName: string, payload: EventPayload) => void;
|
|
71
71
|
};
|
|
72
|
-
declare const _default: ({ linkToken, onLogin, onLoginAttempt, onSuccess, onError, onExit, onEvent }: PinwheelProps) => JSX.Element;
|
|
72
|
+
declare const _default: ({ linkToken, onLogin, onLoginAttempt, onSuccess, onError, onExit, onEvent }: PinwheelProps) => React.JSX.Element;
|
|
73
73
|
export default _default;
|
package/index.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
// @ts-ignore-next-line
|
|
3
|
+
import Pinwheel from './pinwheel-wrapper';
|
|
4
|
+
import { SafeAreaView, StyleSheet } from 'react-native';
|
|
5
|
+
const styles = StyleSheet.create({
|
|
6
|
+
container: {
|
|
7
|
+
flex: 1,
|
|
8
|
+
},
|
|
9
|
+
});
|
|
10
|
+
export const PINWHEEL_MESSAGE_TYPES = {
|
|
11
|
+
PINWHEEL_EXIT: 'PINWHEEL_EXIT',
|
|
12
|
+
PINWHEEL_MODAL_CLOSE: 'PINWHEEL_MODAL_CLOSE',
|
|
13
|
+
PINWHEEL_LOAD_COMPLETE: 'PINWHEEL_LOAD_COMPLETE',
|
|
14
|
+
PINWHEEL_SUCCESS: 'PINWHEEL_SUCCESS',
|
|
15
|
+
PINWHEEL_EVENT: 'PINWHEEL_EVENT',
|
|
16
|
+
};
|
|
17
|
+
export default ({ linkToken, onLogin, onLoginAttempt, onSuccess, onError, onExit, onEvent }) => {
|
|
18
|
+
const handleEvent = (event) => {
|
|
19
|
+
if (!event) {
|
|
20
|
+
// first event is always an empty string
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const { name, payload } = event;
|
|
24
|
+
onEvent && onEvent(name, payload);
|
|
25
|
+
switch (name.toLowerCase()) {
|
|
26
|
+
case 'exit':
|
|
27
|
+
// console.log(`case: exit, onExit: ${onExit}`);
|
|
28
|
+
onExit && onExit(payload);
|
|
29
|
+
break;
|
|
30
|
+
case 'success':
|
|
31
|
+
// console.log(`case: success, onSuccess: ${onSuccess}`);
|
|
32
|
+
onSuccess && onSuccess(payload);
|
|
33
|
+
break;
|
|
34
|
+
case 'login':
|
|
35
|
+
// console.log(`case: login, onLogin: ${onLogin}`);
|
|
36
|
+
onLogin && onLogin(payload);
|
|
37
|
+
break;
|
|
38
|
+
case 'login_attempt':
|
|
39
|
+
// console.log(`case: login_attempt, onLoginAttempt: ${onLoginAttempt}`);
|
|
40
|
+
onLoginAttempt && onLoginAttempt(payload);
|
|
41
|
+
break;
|
|
42
|
+
case 'error':
|
|
43
|
+
// console.log(`case: error, onError: ${onError}`);
|
|
44
|
+
onError && onError(payload);
|
|
45
|
+
break;
|
|
46
|
+
default:
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
return (<SafeAreaView style={styles.container}>
|
|
50
|
+
{linkToken && <Pinwheel token={linkToken} style={{ flex: 1 }} onEvent={handleEvent}/>}
|
|
51
|
+
</SafeAreaView>);
|
|
52
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#import "RNTPinwheelEvents.h"
|
|
2
|
+
|
|
3
|
+
@implementation RNTPinwheelEvents
|
|
4
|
+
{
|
|
5
|
+
bool hasListeners; // This is an instance variable declaration.
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
RCT_EXPORT_MODULE();
|
|
9
|
+
+ (BOOL)requiresMainQueueSetup {
|
|
10
|
+
return NO; // change this to NO if you don't need the main thread
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
+ (instancetype)sharedInstance {
|
|
14
|
+
static RNTPinwheelEvents *sharedInstance = nil;
|
|
15
|
+
static dispatch_once_t onceToken;
|
|
16
|
+
dispatch_once(&onceToken, ^{
|
|
17
|
+
sharedInstance = [[super allocWithZone:NULL] init];
|
|
18
|
+
});
|
|
19
|
+
return sharedInstance;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
+ (id)allocWithZone:(struct _NSZone *)zone {
|
|
23
|
+
return [self sharedInstance];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
- (id)copyWithZone:(NSZone *)zone {
|
|
27
|
+
return self;
|
|
28
|
+
}
|
|
29
|
+
// Overriding the default init to make sure it's not used directly
|
|
30
|
+
- (instancetype)init {
|
|
31
|
+
if (self = [super init]) {
|
|
32
|
+
// Custom initialization if needed
|
|
33
|
+
}
|
|
34
|
+
return self;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Will be called when this module's first listener is added.
|
|
38
|
+
-(void)startObserving {
|
|
39
|
+
NSLog(@"startObserving called");
|
|
40
|
+
hasListeners = YES;
|
|
41
|
+
// Set up any upstream listeners or background tasks as necessary
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Will be called when this module's last listener is removed, or on dealloc.
|
|
45
|
+
-(void)stopObserving {
|
|
46
|
+
NSLog(@"stopObserving called");
|
|
47
|
+
hasListeners = NO;
|
|
48
|
+
// Remove upstream listeners, stop unnecessary background tasks
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
- (void)handlePinwheelEvent:(NSDictionary<NSString *, id> *)payload
|
|
52
|
+
{
|
|
53
|
+
if (hasListeners) {// Only send events if anyone is listening
|
|
54
|
+
[self sendEventWithName:@"PINWHEEL_EVENT" body:payload];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
- (NSArray<NSString *> *)supportedEvents {
|
|
59
|
+
return @[@"PINWHEEL_EVENT"]; // Add more event names here.
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#import <React/RCTViewManager.h>
|
|
2
|
+
#import "RNTPinwheelView.h"
|
|
3
|
+
|
|
4
|
+
@interface RNTPinwheelManager : RCTViewManager
|
|
5
|
+
|
|
6
|
+
@end
|
|
7
|
+
|
|
8
|
+
@implementation RNTPinwheelManager : RCTViewManager
|
|
9
|
+
|
|
10
|
+
RCT_EXPORT_MODULE(RNTPinwheelManager);
|
|
11
|
+
|
|
12
|
+
- (UIView *)view
|
|
13
|
+
{
|
|
14
|
+
RNTPinwheelView *pv = [[RNTPinwheelView alloc] init];
|
|
15
|
+
return pv;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
RCT_EXPORT_VIEW_PROPERTY(token, NSString);
|
|
19
|
+
|
|
20
|
+
@end
|
|
21
|
+
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#import <UIKit/UIKit.h>
|
|
2
|
+
#import <PinwheelSDK/PinwheelSDK-Swift.h>
|
|
3
|
+
#import "RNTPinwheelEvents.h"
|
|
4
|
+
|
|
5
|
+
@interface RNTPinwheelView : UIView <PinwheelWrapperDelegate>
|
|
6
|
+
|
|
7
|
+
@property (nonatomic, strong) PinwheelWrapperVC *pinwheelWrapperVC;
|
|
8
|
+
@property (nonatomic, assign) NSString *token;
|
|
9
|
+
|
|
10
|
+
- (instancetype)initWithFrame:(CGRect)frame token:(NSString *)token;
|
|
11
|
+
|
|
12
|
+
@end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#import "RNTPinwheelView.h"
|
|
2
|
+
|
|
3
|
+
@implementation RNTPinwheelView
|
|
4
|
+
|
|
5
|
+
- (instancetype)initWithFrame:(CGRect)frame {
|
|
6
|
+
if ((self = [super initWithFrame:frame])) {
|
|
7
|
+
[self initPinwheelWrapperVC];
|
|
8
|
+
}
|
|
9
|
+
return self;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
- (instancetype)initWithFrame:(CGRect)frame token:(NSString *)token {
|
|
13
|
+
if ((self = [super initWithFrame:frame])) {
|
|
14
|
+
_token = token;
|
|
15
|
+
}
|
|
16
|
+
return self;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
- (void)initPinwheelWrapperVC {
|
|
20
|
+
if (self.token != nil && self.pinwheelWrapperVC == nil) {
|
|
21
|
+
self.pinwheelWrapperVC = [[PinwheelWrapperVC alloc] initWithToken:self.token delegate:self sdk:@"react native"];
|
|
22
|
+
[self addSubview:self.pinwheelWrapperVC.view];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
- (void)setToken:(NSString *)newToken {
|
|
27
|
+
if (![_token isEqualToString:newToken]) {
|
|
28
|
+
_token = newToken;
|
|
29
|
+
[self initPinwheelWrapperVC];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
- (void)layoutSubviews
|
|
34
|
+
{
|
|
35
|
+
[super layoutSubviews];
|
|
36
|
+
self.pinwheelWrapperVC.view.frame = self.bounds;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
- (void)onEventWithName:(NSString *)name event:(NSDictionary<NSString *, id> *)event {
|
|
40
|
+
NSLog(@"%@", name);
|
|
41
|
+
NSDictionary *dataToSend = @{@"name": name, @"payload": event};
|
|
42
|
+
[RNTPinwheelEvents.sharedInstance handlePinwheelEvent:dataToSend];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
- (void)onExit:(NSDictionary<NSString *, id> *)error {
|
|
46
|
+
NSLog(@"%@", error);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
- (void)onSuccess:(NSDictionary<NSString *, id> *)result {
|
|
50
|
+
NSLog(@"%@", result);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
- (void)onLogin:(NSDictionary<NSString *, id> *)result {
|
|
54
|
+
NSLog(@"%@", result);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
- (void)onLoginAttempt:(NSDictionary<NSString *, id> *)result {
|
|
58
|
+
NSLog(@"%@", result);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
- (void)onError:(NSDictionary<NSString *, id> *)error {
|
|
62
|
+
NSLog(@"%@", error);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@end
|
package/package.json
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pinwheel/react-native-pinwheel",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0-alpha",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Pinwheel React Native SDK",
|
|
6
|
-
"main": "
|
|
7
|
-
"types": "
|
|
8
|
-
"files": [
|
|
9
|
-
"lib/**/*"
|
|
10
|
-
],
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"types": "index.d.ts",
|
|
11
8
|
"scripts": {
|
|
12
9
|
"build": "tsc",
|
|
13
10
|
"bump-pkg-version": "./scripts/bump-pkg-version.sh",
|
|
@@ -17,20 +14,10 @@
|
|
|
17
14
|
"license": "MIT",
|
|
18
15
|
"peerDependencies": {
|
|
19
16
|
"react": "^16.13.1 || ^17 || ^18",
|
|
20
|
-
"react-native": "*"
|
|
21
|
-
"react-native-webview": "^10.10.0 || ^11.0.0"
|
|
17
|
+
"react-native": "*"
|
|
22
18
|
},
|
|
23
19
|
"devDependencies": {
|
|
24
|
-
"@types/react-native": "^0.
|
|
25
|
-
"react-native-webview": "^11.0.0",
|
|
20
|
+
"@types/react-native": "^0.72.2",
|
|
26
21
|
"typescript": "^4.0.3"
|
|
27
|
-
},
|
|
28
|
-
"overrides": {
|
|
29
|
-
"react-native": {
|
|
30
|
-
"hermes-engine": "0.11.0"
|
|
31
|
-
},
|
|
32
|
-
"@react-native-community/cli-tools": {
|
|
33
|
-
"shell-quote": "^1.7.4"
|
|
34
|
-
}
|
|
35
22
|
}
|
|
36
23
|
}
|
package/pinwheel-view.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import { UIManager, findNodeHandle, NativeEventEmitter, NativeModules } from 'react-native';
|
|
3
|
+
import { RNTPinwheel } from './pinwheel-view';
|
|
4
|
+
const createFragment = (viewId) => {
|
|
5
|
+
UIManager.dispatchViewManagerCommand(viewId,
|
|
6
|
+
// we are calling the 'create' command
|
|
7
|
+
// @ts-ignore
|
|
8
|
+
UIManager.RNTPinwheel.Commands.create.toString(), [viewId]);
|
|
9
|
+
};
|
|
10
|
+
const RNTPinwheelView = (props) => {
|
|
11
|
+
const ref = useRef(null);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
setTimeout(() => {
|
|
14
|
+
const viewId = findNodeHandle(ref.current);
|
|
15
|
+
if (viewId) {
|
|
16
|
+
createFragment(viewId);
|
|
17
|
+
}
|
|
18
|
+
// events
|
|
19
|
+
const { RNTPinwheelEvents } = NativeModules;
|
|
20
|
+
const eventEmitter = new NativeEventEmitter(RNTPinwheelEvents);
|
|
21
|
+
const eventListener = eventEmitter.addListener('PINWHEEL_EVENT', (event) => {
|
|
22
|
+
props.onEvent(event);
|
|
23
|
+
});
|
|
24
|
+
}, 10);
|
|
25
|
+
}, []);
|
|
26
|
+
return <RNTPinwheel {...props} onEvent={(event) => { console.log `rawbee: ${JSON.stringify(event)}`; }} ref={ref}/>;
|
|
27
|
+
};
|
|
28
|
+
export default RNTPinwheelView;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { NativeEventEmitter, NativeModules } from 'react-native';
|
|
3
|
+
import { RNTPinwheel } from './pinwheel-view';
|
|
4
|
+
const RNTPinwheelView = (props) => {
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
const { RNTPinwheelEvents } = NativeModules;
|
|
7
|
+
const eventEmitter = new NativeEventEmitter(RNTPinwheelEvents);
|
|
8
|
+
const eventListener = eventEmitter.addListener('PINWHEEL_EVENT', (event) => {
|
|
9
|
+
props.onEvent(event);
|
|
10
|
+
});
|
|
11
|
+
return () => {
|
|
12
|
+
eventListener.remove();
|
|
13
|
+
};
|
|
14
|
+
}, []);
|
|
15
|
+
return <RNTPinwheel {...props}/>;
|
|
16
|
+
};
|
|
17
|
+
export default RNTPinwheelView;
|
package/lib/index.js
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { WebView } from 'react-native-webview';
|
|
3
|
-
import { Linking, Platform, SafeAreaView, StyleSheet } from 'react-native';
|
|
4
|
-
import { LINK_PAGE_URL, PINWHEEL_DOMAIN, VERSION } from './constants';
|
|
5
|
-
const styles = StyleSheet.create({
|
|
6
|
-
container: {
|
|
7
|
-
flex: 1,
|
|
8
|
-
},
|
|
9
|
-
});
|
|
10
|
-
export const PINWHEEL_MESSAGE_TYPES = {
|
|
11
|
-
PINWHEEL_EXIT: 'PINWHEEL_EXIT',
|
|
12
|
-
PINWHEEL_MODAL_CLOSE: 'PINWHEEL_MODAL_CLOSE',
|
|
13
|
-
PINWHEEL_LOAD_COMPLETE: 'PINWHEEL_LOAD_COMPLETE',
|
|
14
|
-
PINWHEEL_SUCCESS: 'PINWHEEL_SUCCESS',
|
|
15
|
-
PINWHEEL_EVENT: 'PINWHEEL_EVENT',
|
|
16
|
-
};
|
|
17
|
-
export default ({ linkToken, onLogin, onLoginAttempt, onSuccess, onError, onExit, onEvent }) => {
|
|
18
|
-
const handleEvent = (event) => {
|
|
19
|
-
if (!event) {
|
|
20
|
-
// first event is always an empty string
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
let eventData;
|
|
24
|
-
try {
|
|
25
|
-
eventData = JSON.parse(event.nativeEvent.data);
|
|
26
|
-
}
|
|
27
|
-
catch (_error) {
|
|
28
|
-
let error = _error;
|
|
29
|
-
console.error(error);
|
|
30
|
-
onExit && onExit(error);
|
|
31
|
-
onError && onError(error);
|
|
32
|
-
onEvent && onEvent('error', error);
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
const { type, eventName, payload } = eventData;
|
|
36
|
-
if (type === 'PINWHEEL_EVENT') {
|
|
37
|
-
onEvent && onEvent(eventName, payload);
|
|
38
|
-
switch (eventName) {
|
|
39
|
-
case 'exit':
|
|
40
|
-
onExit && onExit(payload);
|
|
41
|
-
break;
|
|
42
|
-
case 'success':
|
|
43
|
-
onSuccess && onSuccess(payload);
|
|
44
|
-
break;
|
|
45
|
-
case 'login':
|
|
46
|
-
onLogin && onLogin(payload);
|
|
47
|
-
break;
|
|
48
|
-
case 'login_attempt':
|
|
49
|
-
onLoginAttempt && onLoginAttempt(payload);
|
|
50
|
-
break;
|
|
51
|
-
case 'error':
|
|
52
|
-
onError && onError(payload);
|
|
53
|
-
break;
|
|
54
|
-
default:
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
const now = Date.now();
|
|
59
|
-
const [major, minor, patch] = VERSION.split('.').map(x => Number(x));
|
|
60
|
-
const runFirst = `
|
|
61
|
-
const uuidKey = 'pinwheel-uuid';
|
|
62
|
-
const localStorage = window.localStorage;
|
|
63
|
-
let uuid = localStorage.getItem(uuidKey);
|
|
64
|
-
if(!uuid) {
|
|
65
|
-
uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
|
66
|
-
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
|
|
67
|
-
return v.toString(16);
|
|
68
|
-
});
|
|
69
|
-
localStorage.setItem(uuidKey, uuid);
|
|
70
|
-
}
|
|
71
|
-
try {
|
|
72
|
-
window.addEventListener('message', event => {
|
|
73
|
-
window.ReactNativeWebView.postMessage(JSON.stringify(event.data))
|
|
74
|
-
});
|
|
75
|
-
window.postMessage(
|
|
76
|
-
{
|
|
77
|
-
type: 'PINWHEEL_INIT',
|
|
78
|
-
payload: {
|
|
79
|
-
platform: "${Platform.OS}",
|
|
80
|
-
sdk: 'react native',
|
|
81
|
-
version: {
|
|
82
|
-
major: ${major},
|
|
83
|
-
minor: ${minor},
|
|
84
|
-
patch: ${patch}
|
|
85
|
-
},
|
|
86
|
-
initializationOptions: {
|
|
87
|
-
hasOnSuccess: ${!!onSuccess},
|
|
88
|
-
hasOnEvent: ${!!onEvent},
|
|
89
|
-
hasOnExit: ${!!onExit},
|
|
90
|
-
hasOnError: ${!!onError},
|
|
91
|
-
hasOnLogin: ${!!onLogin},
|
|
92
|
-
},
|
|
93
|
-
linkToken: '${linkToken}',
|
|
94
|
-
uniqueUserId: uuid,
|
|
95
|
-
initializationTimestamp: ${now}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
);
|
|
99
|
-
} catch (err) {
|
|
100
|
-
console.error(err);
|
|
101
|
-
}
|
|
102
|
-
true;
|
|
103
|
-
`;
|
|
104
|
-
return (<SafeAreaView style={styles.container}>
|
|
105
|
-
<WebView source={{ uri: LINK_PAGE_URL }} onMessage={handleEvent} injectedJavaScript={runFirst} onShouldStartLoadWithRequest={(request) => {
|
|
106
|
-
const targetURL = request.url;
|
|
107
|
-
const isLinkPage = targetURL.includes(PINWHEEL_DOMAIN);
|
|
108
|
-
if (!isLinkPage) {
|
|
109
|
-
Linking.canOpenURL(targetURL).then(supported => {
|
|
110
|
-
if (supported) {
|
|
111
|
-
Linking.openURL(targetURL).then(() => { });
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
console.warn('Don\'t know how to open URL: ' + targetURL);
|
|
115
|
-
}
|
|
116
|
-
return false;
|
|
117
|
-
}).catch(err => console.error('An error occurred ', err));
|
|
118
|
-
}
|
|
119
|
-
return isLinkPage;
|
|
120
|
-
}}/>
|
|
121
|
-
</SafeAreaView>);
|
|
122
|
-
};
|