@algorandfoundation/react-native-passkey-autofill 1.0.0-canary.7 → 1.0.0-canary.9
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 +14 -0
- package/README.md +25 -0
- package/android/src/main/AndroidManifest.xml +8 -2
- package/android/src/main/java/co/algorand/passkeyautofill/CreatePasskeyActivity.kt +8 -0
- package/android/src/main/java/co/algorand/passkeyautofill/GetPasskeyActivity.kt +8 -0
- package/android/src/main/java/co/algorand/passkeyautofill/ReactNativePasskeyAutofillModule.kt +14 -0
- package/android/src/main/res/values/styles.xml +10 -0
- package/app.plugin.js +2 -2
- package/build/ReactNativePasskeyAutofill.types.d.ts +8 -1
- package/build/ReactNativePasskeyAutofill.types.d.ts.map +1 -1
- package/build/ReactNativePasskeyAutofill.types.js.map +1 -1
- package/ios/ReactNativePasskeyAutofillModule.swift +2 -0
- package/package.json +1 -1
- package/src/ReactNativePasskeyAutofill.types.ts +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [1.0.0-canary.9](https://github.com/algorandfoundation/react-native-passkey-autofill/compare/v1.0.0-canary.8...v1.0.0-canary.9) (2026-03-30)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* x logins, refactor example views to be dialogs ([e7a1ccf](https://github.com/algorandfoundation/react-native-passkey-autofill/commit/e7a1ccf91f88b5c369ff3082f06d538fc8b3db89))
|
|
7
|
+
|
|
8
|
+
# [1.0.0-canary.8](https://github.com/algorandfoundation/react-native-passkey-autofill/compare/v1.0.0-canary.7...v1.0.0-canary.8) (2026-03-27)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* passkey added and authenticated events ([b9871f4](https://github.com/algorandfoundation/react-native-passkey-autofill/commit/b9871f475a9a633ae98d30a702ef2814ec8ae5e0))
|
|
14
|
+
|
|
1
15
|
# [1.0.0-canary.7](https://github.com/algorandfoundation/react-native-passkey-autofill/compare/v1.0.0-canary.6...v1.0.0-canary.7) (2026-03-24)
|
|
2
16
|
|
|
3
17
|
|
package/README.md
CHANGED
|
@@ -66,6 +66,31 @@ await ReactNativePasskeyAutofill.configureIntentActions(
|
|
|
66
66
|
await ReactNativePasskeyAutofill.clearCredentials();
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
+
## Events
|
|
70
|
+
|
|
71
|
+
You can listen for events emitted by the native module when a passkey is successfully added or authenticated.
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
import ReactNativePasskeyAutofill from '@algorandfoundation/react-native-passkey-autofill';
|
|
75
|
+
import { useEffect } from 'react';
|
|
76
|
+
|
|
77
|
+
// ... inside a component or hook
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
const addedSubscription = ReactNativePasskeyAutofill.addListener('onPasskeyAdded', (event) => {
|
|
80
|
+
console.log('Passkey added successfully:', event.success);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const authSubscription = ReactNativePasskeyAutofill.addListener('onPasskeyAuthenticated', (event) => {
|
|
84
|
+
console.log('Passkey authenticated successfully:', event.success);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
return () => {
|
|
88
|
+
addedSubscription.remove();
|
|
89
|
+
authSubscription.remove();
|
|
90
|
+
};
|
|
91
|
+
}, []);
|
|
92
|
+
```
|
|
93
|
+
|
|
69
94
|
## 🧪 Testing
|
|
70
95
|
|
|
71
96
|
The project is set up with a comprehensive testing approach covering both JavaScript and Native (Kotlin) sides.
|
|
@@ -15,13 +15,19 @@
|
|
|
15
15
|
android:name="android.credentials.provider"
|
|
16
16
|
android:resource="@xml/provider" />
|
|
17
17
|
</service>
|
|
18
|
-
<activity android:name=".GetPasskeyActivity"
|
|
18
|
+
<activity android:name="co.algorand.passkeyautofill.GetPasskeyActivity"
|
|
19
|
+
android:exported="true"
|
|
20
|
+
android:launchMode="singleTop"
|
|
21
|
+
android:theme="@style/Theme.PasskeyAutofill.Dialog">
|
|
19
22
|
<intent-filter>
|
|
20
23
|
<action android:name="co.algorand.passkeyautofill.GET_PASSKEY"/>
|
|
21
24
|
<category android:name="android.intent.category.DEFAULT"/>
|
|
22
25
|
</intent-filter>
|
|
23
26
|
</activity>
|
|
24
|
-
<activity android:name=".CreatePasskeyActivity"
|
|
27
|
+
<activity android:name="co.algorand.passkeyautofill.CreatePasskeyActivity"
|
|
28
|
+
android:exported="true"
|
|
29
|
+
android:launchMode="singleTop"
|
|
30
|
+
android:theme="@style/Theme.PasskeyAutofill.Dialog">
|
|
25
31
|
<intent-filter>
|
|
26
32
|
<action android:name="co.algorand.passkeyautofill.CREATE_PASSKEY"/>
|
|
27
33
|
<category android:name="android.intent.category.DEFAULT"/>
|
|
@@ -205,6 +205,11 @@ class CreatePasskeyActivity : AppCompatActivity() {
|
|
|
205
205
|
layout.addView(cancelButton)
|
|
206
206
|
|
|
207
207
|
setContentView(layout)
|
|
208
|
+
|
|
209
|
+
// Ensure the activity is focusable and can receive touches
|
|
210
|
+
layout.isFocusable = true
|
|
211
|
+
layout.isFocusableInTouchMode = true
|
|
212
|
+
layout.requestFocus()
|
|
208
213
|
}
|
|
209
214
|
|
|
210
215
|
@SuppressLint("RestrictedApi")
|
|
@@ -301,6 +306,9 @@ class CreatePasskeyActivity : AppCompatActivity() {
|
|
|
301
306
|
)
|
|
302
307
|
|
|
303
308
|
setResult(Activity.RESULT_OK, resultIntent)
|
|
309
|
+
ReactNativePasskeyAutofillModule.instance?.sendEvent("onPasskeyAdded", Bundle().apply {
|
|
310
|
+
putBoolean("success", true)
|
|
311
|
+
})
|
|
304
312
|
} catch (e: Exception) {
|
|
305
313
|
Log.e(TAG, "Error during passkey creation", e)
|
|
306
314
|
setResult(Activity.RESULT_CANCELED)
|
|
@@ -193,6 +193,11 @@ class GetPasskeyActivity : AppCompatActivity() {
|
|
|
193
193
|
layout.addView(cancelButton)
|
|
194
194
|
|
|
195
195
|
setContentView(layout)
|
|
196
|
+
|
|
197
|
+
// Ensure the activity is focusable and can receive touches
|
|
198
|
+
layout.isFocusable = true
|
|
199
|
+
layout.isFocusableInTouchMode = true
|
|
200
|
+
layout.requestFocus()
|
|
196
201
|
}
|
|
197
202
|
|
|
198
203
|
@SuppressLint("RestrictedApi")
|
|
@@ -309,6 +314,9 @@ class GetPasskeyActivity : AppCompatActivity() {
|
|
|
309
314
|
)
|
|
310
315
|
|
|
311
316
|
setResult(Activity.RESULT_OK, resultIntent)
|
|
317
|
+
ReactNativePasskeyAutofillModule.instance?.sendEvent("onPasskeyAuthenticated", Bundle().apply {
|
|
318
|
+
putBoolean("success", true)
|
|
319
|
+
})
|
|
312
320
|
} catch (e: Exception) {
|
|
313
321
|
Log.e(TAG, "Error during passkey assertion", e)
|
|
314
322
|
setResult(Activity.RESULT_CANCELED)
|
package/android/src/main/java/co/algorand/passkeyautofill/ReactNativePasskeyAutofillModule.kt
CHANGED
|
@@ -12,6 +12,10 @@ import java.security.Security
|
|
|
12
12
|
class ReactNativePasskeyAutofillModule : Module() {
|
|
13
13
|
private val credentialRepository = CredentialRepository()
|
|
14
14
|
|
|
15
|
+
companion object {
|
|
16
|
+
var instance: ReactNativePasskeyAutofillModule? = null
|
|
17
|
+
}
|
|
18
|
+
|
|
15
19
|
init {
|
|
16
20
|
Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME)
|
|
17
21
|
Security.addProvider(BouncyCastleProvider())
|
|
@@ -26,6 +30,16 @@ class ReactNativePasskeyAutofillModule : Module() {
|
|
|
26
30
|
// The module will be accessible from `requireNativeModule('ReactNativeLiquidAuth')` in JavaScript.
|
|
27
31
|
Name("ReactNativePasskeyAutofill")
|
|
28
32
|
|
|
33
|
+
OnCreate {
|
|
34
|
+
instance = this@ReactNativePasskeyAutofillModule
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
OnDestroy {
|
|
38
|
+
instance = null
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
Events("onPasskeyAdded", "onPasskeyAuthenticated")
|
|
42
|
+
|
|
29
43
|
AsyncFunction("setMasterKey") { secret: String ->
|
|
30
44
|
val context = (appContext.reactContext ?: appContext.hostingRuntimeContext) as? Context
|
|
31
45
|
if (context != null) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<resources>
|
|
2
|
+
<style name="Theme.PasskeyAutofill.Dialog" parent="Theme.AppCompat.Light.Dialog.MinWidth">
|
|
3
|
+
<item name="android:windowIsTranslucent">true</item>
|
|
4
|
+
<item name="android:windowBackground">@android:color/transparent</item>
|
|
5
|
+
<item name="android:windowContentOverlay">@null</item>
|
|
6
|
+
<item name="android:windowNoTitle">true</item>
|
|
7
|
+
<item name="android:windowIsFloating">true</item>
|
|
8
|
+
<item name="android:backgroundDimEnabled">true</item>
|
|
9
|
+
</style>
|
|
10
|
+
</resources>
|
package/app.plugin.js
CHANGED
|
@@ -231,13 +231,13 @@ const withPasskeyAutofill = (config, props = {}) => {
|
|
|
231
231
|
if (config.modResults.contents.includes("dP256Android-release")) {
|
|
232
232
|
return config;
|
|
233
233
|
}
|
|
234
|
-
const libsDir =
|
|
234
|
+
const libsDir = "../../android/libs";
|
|
235
235
|
config.modResults.contents = config.modResults.contents.replace(
|
|
236
236
|
/allprojects\s*{[\s\n]*repositories\s*{/,
|
|
237
237
|
`allprojects {
|
|
238
238
|
repositories {
|
|
239
239
|
flatDir {
|
|
240
|
-
dirs "${libsDir}"
|
|
240
|
+
dirs "$rootDir/${libsDir}"
|
|
241
241
|
}`
|
|
242
242
|
);
|
|
243
243
|
return config;
|
|
@@ -1,2 +1,9 @@
|
|
|
1
|
-
export type ReactNativePasskeyAutofillModuleEvents = {
|
|
1
|
+
export type ReactNativePasskeyAutofillModuleEvents = {
|
|
2
|
+
onPasskeyAdded: (event: {
|
|
3
|
+
success: boolean;
|
|
4
|
+
}) => void;
|
|
5
|
+
onPasskeyAuthenticated: (event: {
|
|
6
|
+
success: boolean;
|
|
7
|
+
}) => void;
|
|
8
|
+
};
|
|
2
9
|
//# sourceMappingURL=ReactNativePasskeyAutofill.types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReactNativePasskeyAutofill.types.d.ts","sourceRoot":"","sources":["../src/ReactNativePasskeyAutofill.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sCAAsC,GAAG,
|
|
1
|
+
{"version":3,"file":"ReactNativePasskeyAutofill.types.d.ts","sourceRoot":"","sources":["../src/ReactNativePasskeyAutofill.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sCAAsC,GAAG;IACnD,cAAc,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IACtD,sBAAsB,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;CAC/D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReactNativePasskeyAutofill.types.js","sourceRoot":"","sources":["../src/ReactNativePasskeyAutofill.types.ts"],"names":[],"mappings":"","sourcesContent":["export type ReactNativePasskeyAutofillModuleEvents = {\n
|
|
1
|
+
{"version":3,"file":"ReactNativePasskeyAutofill.types.js","sourceRoot":"","sources":["../src/ReactNativePasskeyAutofill.types.ts"],"names":[],"mappings":"","sourcesContent":["export type ReactNativePasskeyAutofillModuleEvents = {\n onPasskeyAdded: (event: { success: boolean }) => void;\n onPasskeyAuthenticated: (event: { success: boolean }) => void;\n};\n"]}
|
|
@@ -10,6 +10,8 @@ public class ReactNativePasskeyAutofillModule: Module {
|
|
|
10
10
|
// The module will be accessible from `requireNativeModule('ReactNativePasskeyAutofill')` in JavaScript.
|
|
11
11
|
Name("ReactNativePasskeyAutofill")
|
|
12
12
|
|
|
13
|
+
Events("onPasskeyAdded", "onPasskeyAuthenticated")
|
|
14
|
+
|
|
13
15
|
AsyncFunction("setMasterKey") { (secret: String) in
|
|
14
16
|
// TODO: Implement for iOS
|
|
15
17
|
}
|
package/package.json
CHANGED