@entropy-softworks/ui 2026.8.22 → 2026.8.23
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LockOverlay.d.ts","sourceRoot":"","sources":["../../../src/components/auth/LockOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"LockOverlay.d.ts","sourceRoot":"","sources":["../../../src/components/auth/LockOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAiBnD,UAAU,gBAAgB;IACxB;;;OAGG;IACH,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACrD,4CAA4C;IAC5C,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;;;;;;;OAaG;IACH,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAChD;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,SAAS,EACT,cAAc,EACd,iBAAiB,GAClB,EAAE,gBAAgB,qBA8KlB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect,
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
2
|
import { Platform, Pressable, View } from "react-native";
|
|
3
3
|
import { Ionicons } from "@expo/vector-icons";
|
|
4
4
|
import Toast from "react-native-toast-message";
|
|
@@ -23,8 +23,20 @@ export function LockOverlay({ onUnlock, onSignOut, successMessage, onBiometricUn
|
|
|
23
23
|
const [loading, setLoading] = useState(false);
|
|
24
24
|
const [biometricState, setBiometricState] = useState("idle");
|
|
25
25
|
const [error, setError] = useState("");
|
|
26
|
-
const hasAutoPrompted = useRef(false);
|
|
27
26
|
const pulse = useSharedValue(1);
|
|
27
|
+
// Fires only on explicit tap of the fingerprint icon below — NOT
|
|
28
|
+
// automatically on mount (that was here briefly). On Android, a
|
|
29
|
+
// passkey/WebAuthn ceremony goes through the OS's Credential Manager,
|
|
30
|
+
// which surfaces EVERY registered credential provider on the device —
|
|
31
|
+
// including other password managers like Bitwarden if one is set as
|
|
32
|
+
// an autofill/credential provider. Firing that automatically on every
|
|
33
|
+
// single mount raced against Bitwarden's own autofill prompt for this
|
|
34
|
+
// app, the two fighting each other: dismiss one, the other reopens
|
|
35
|
+
// immediately, with vault's own UI never getting a chance to paint
|
|
36
|
+
// underneath — reported as a black screen that wouldn't go away, on
|
|
37
|
+
// 2026-08-17. Requiring an explicit tap avoids ever entering that
|
|
38
|
+
// credential-provider arbitration unless the user actually asked for
|
|
39
|
+
// it just now.
|
|
28
40
|
const triggerBiometricUnlock = React.useCallback(async () => {
|
|
29
41
|
if (!onBiometricUnlock) {
|
|
30
42
|
return;
|
|
@@ -37,17 +49,6 @@ export function LockOverlay({ onUnlock, onSignOut, successMessage, onBiometricUn
|
|
|
37
49
|
setBiometricState("idle");
|
|
38
50
|
}
|
|
39
51
|
}, [onBiometricUnlock]);
|
|
40
|
-
// Fires once, automatically, the moment this screen can offer it — no
|
|
41
|
-
// button to tap first. A stale-closure-safe ref guard (not a `[]]`
|
|
42
|
-
// dependency array alone) because triggerBiometricUnlock's identity
|
|
43
|
-
// can change across the caller's own re-renders before the first
|
|
44
|
-
// prompt has actually happened.
|
|
45
|
-
useEffect(() => {
|
|
46
|
-
if (onBiometricUnlock && !hasAutoPrompted.current) {
|
|
47
|
-
hasAutoPrompted.current = true;
|
|
48
|
-
void triggerBiometricUnlock();
|
|
49
|
-
}
|
|
50
|
-
}, [onBiometricUnlock, triggerBiometricUnlock]);
|
|
51
52
|
useEffect(() => {
|
|
52
53
|
if (biometricState === "prompting") {
|
|
53
54
|
pulse.value = withRepeat(withTiming(1.12, { duration: 650, easing: Easing.inOut(Easing.ease) }), -1, true);
|
|
@@ -111,7 +112,7 @@ export function LockOverlay({ onUnlock, onSignOut, successMessage, onBiometricUn
|
|
|
111
112
|
<Ionicons name="finger-print" size={44} color={isDark ? "#FFFFFF" : "#000000"}/>
|
|
112
113
|
</Animated.View>
|
|
113
114
|
<MutedText className="mt-2 text-xs">
|
|
114
|
-
{biometricState === "prompting" ? "Authenticating…" : "Tap to
|
|
115
|
+
{biometricState === "prompting" ? "Authenticating…" : "Tap to unlock"}
|
|
115
116
|
</MutedText>
|
|
116
117
|
</Pressable>
|
|
117
118
|
<View className="mb-3 w-full flex-row items-center gap-3">
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LockOverlay.jsx","sourceRoot":"","sources":["../../../src/components/auth/LockOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"LockOverlay.jsx","sourceRoot":"","sources":["../../../src/components/auth/LockOverlay.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect,
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
2
|
import { Platform, Pressable, View } from "react-native";
|
|
3
3
|
import { Ionicons } from "@expo/vector-icons";
|
|
4
4
|
import Toast from "react-native-toast-message";
|
|
@@ -62,9 +62,21 @@ export function LockOverlay({
|
|
|
62
62
|
const [loading, setLoading] = useState(false);
|
|
63
63
|
const [biometricState, setBiometricState] = useState<"idle" | "prompting">("idle");
|
|
64
64
|
const [error, setError] = useState("");
|
|
65
|
-
const hasAutoPrompted = useRef(false);
|
|
66
65
|
const pulse = useSharedValue(1);
|
|
67
66
|
|
|
67
|
+
// Fires only on explicit tap of the fingerprint icon below — NOT
|
|
68
|
+
// automatically on mount (that was here briefly). On Android, a
|
|
69
|
+
// passkey/WebAuthn ceremony goes through the OS's Credential Manager,
|
|
70
|
+
// which surfaces EVERY registered credential provider on the device —
|
|
71
|
+
// including other password managers like Bitwarden if one is set as
|
|
72
|
+
// an autofill/credential provider. Firing that automatically on every
|
|
73
|
+
// single mount raced against Bitwarden's own autofill prompt for this
|
|
74
|
+
// app, the two fighting each other: dismiss one, the other reopens
|
|
75
|
+
// immediately, with vault's own UI never getting a chance to paint
|
|
76
|
+
// underneath — reported as a black screen that wouldn't go away, on
|
|
77
|
+
// 2026-08-17. Requiring an explicit tap avoids ever entering that
|
|
78
|
+
// credential-provider arbitration unless the user actually asked for
|
|
79
|
+
// it just now.
|
|
68
80
|
const triggerBiometricUnlock = React.useCallback(async () => {
|
|
69
81
|
if (!onBiometricUnlock) {
|
|
70
82
|
return;
|
|
@@ -77,18 +89,6 @@ export function LockOverlay({
|
|
|
77
89
|
}
|
|
78
90
|
}, [onBiometricUnlock]);
|
|
79
91
|
|
|
80
|
-
// Fires once, automatically, the moment this screen can offer it — no
|
|
81
|
-
// button to tap first. A stale-closure-safe ref guard (not a `[]]`
|
|
82
|
-
// dependency array alone) because triggerBiometricUnlock's identity
|
|
83
|
-
// can change across the caller's own re-renders before the first
|
|
84
|
-
// prompt has actually happened.
|
|
85
|
-
useEffect(() => {
|
|
86
|
-
if (onBiometricUnlock && !hasAutoPrompted.current) {
|
|
87
|
-
hasAutoPrompted.current = true;
|
|
88
|
-
void triggerBiometricUnlock();
|
|
89
|
-
}
|
|
90
|
-
}, [onBiometricUnlock, triggerBiometricUnlock]);
|
|
91
|
-
|
|
92
92
|
useEffect(() => {
|
|
93
93
|
if (biometricState === "prompting") {
|
|
94
94
|
pulse.value = withRepeat(
|
|
@@ -170,7 +170,7 @@ export function LockOverlay({
|
|
|
170
170
|
<Ionicons name="finger-print" size={44} color={isDark ? "#FFFFFF" : "#000000"} />
|
|
171
171
|
</Animated.View>
|
|
172
172
|
<MutedText className="mt-2 text-xs">
|
|
173
|
-
{biometricState === "prompting" ? "Authenticating…" : "Tap to
|
|
173
|
+
{biometricState === "prompting" ? "Authenticating…" : "Tap to unlock"}
|
|
174
174
|
</MutedText>
|
|
175
175
|
</Pressable>
|
|
176
176
|
<View className="mb-3 w-full flex-row items-center gap-3">
|