@entropy-softworks/ui 2026.8.18 → 2026.8.20
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/lib/components/auth/LockOverlay.d.ts.map +1 -1
- package/lib/components/auth/LockOverlay.jsx +10 -2
- package/lib/components/auth/LockOverlay.jsx.map +1 -1
- package/lib/utils/fetch.d.ts.map +1 -1
- package/lib/utils/fetch.js +37 -1
- package/lib/utils/fetch.js.map +1 -1
- package/package.json +1 -1
- package/src/components/auth/LockOverlay.tsx +9 -2
- package/src/utils/fetch.ts +38 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LockOverlay.d.ts","sourceRoot":"","sources":["../../../src/components/auth/LockOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAQxC,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;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"LockOverlay.d.ts","sourceRoot":"","sources":["../../../src/components/auth/LockOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAQxC,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;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,EAAE,gBAAgB,qBAqGpF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useState } from "react";
|
|
2
|
-
import { View } from "react-native";
|
|
2
|
+
import { Platform, View } from "react-native";
|
|
3
3
|
import Toast from "react-native-toast-message";
|
|
4
4
|
import { Button } from "../../components/button";
|
|
5
5
|
import { PasswordInput } from "../../components/input";
|
|
@@ -68,7 +68,15 @@ export function LockOverlay({ onUnlock, onSignOut, successMessage }) {
|
|
|
68
68
|
if (error) {
|
|
69
69
|
setError("");
|
|
70
70
|
}
|
|
71
|
-
}} placeholder="Master password" error={error}
|
|
71
|
+
}} placeholder="Master password" error={error}
|
|
72
|
+
// Web: autofocus on a login-style page is expected desktop
|
|
73
|
+
// UX. Native: this overlay mounts unconditionally at app
|
|
74
|
+
// launch (and can be visible under the OTA install overlay,
|
|
75
|
+
// before the user has done anything at all), so autofocus
|
|
76
|
+
// pops the on-screen keyboard immediately and unprompted —
|
|
77
|
+
// reported as a real annoyance on 2026-08-17. Unlock should
|
|
78
|
+
// wait for an explicit tap on the field.
|
|
79
|
+
autoFocus={Platform.OS === "web"} returnKeyType="done" onSubmitEditing={handleUnlock} accessibilityLabel="Master password" testID="lock-password-input"/>
|
|
72
80
|
<Button className="w-full" onPress={handleUnlock} isLoading={loading} accessibilityLabel="Unlock" accessibilityRole="button" testID="lock-unlock-button">
|
|
73
81
|
Unlock
|
|
74
82
|
</Button>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LockOverlay.jsx","sourceRoot":"","sources":["../../../src/components/auth/LockOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"LockOverlay.jsx","sourceRoot":"","sources":["../../../src/components/auth/LockOverlay.tsx"],"names":[],"mappings":"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"}
|
package/lib/utils/fetch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":"AAqCA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,WAAgB,EACzB,SAAS,SAAQ,GAChB,OAAO,CAAC,QAAQ,CAAC,CAanB"}
|
package/lib/utils/fetch.js
CHANGED
|
@@ -1,3 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Combines multiple AbortSignals into one that aborts when any input does.
|
|
3
|
+
* Prefers the native `AbortSignal.any` where present (modern browsers);
|
|
4
|
+
* falls back to manual event-listener wiring where it isn't.
|
|
5
|
+
*
|
|
6
|
+
* That fallback is load-bearing, not defensive padding: React Native
|
|
7
|
+
* doesn't provide a native AbortController at all — `setUpXHR.js` installs
|
|
8
|
+
* one from the third-party `abort-controller` npm package (pinned at
|
|
9
|
+
* v3.0.0 in this tree), which predates `AbortSignal.any` entering the
|
|
10
|
+
* WHATWG spec. Calling it unconditionally on native evaluates to invoking
|
|
11
|
+
* `undefined` as a function, which Hermes reports as the unhelpfully
|
|
12
|
+
* generic "undefined is not a function" — confirmed for real on
|
|
13
|
+
* 2026-08-17, the first time a native call site (a vault item detail
|
|
14
|
+
* screen, via its own cancellation AbortSignal) exercised the
|
|
15
|
+
* `signals.length > 1` branch this function has always had; every
|
|
16
|
+
* previous native caller only ever supplied the internal timeout signal,
|
|
17
|
+
* so `AbortSignal.any` had simply never been reached before.
|
|
18
|
+
*/
|
|
19
|
+
function combineSignals(signals) {
|
|
20
|
+
if (signals.length === 1) {
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length checked
|
|
22
|
+
return signals[0];
|
|
23
|
+
}
|
|
24
|
+
if (typeof AbortSignal.any === "function") {
|
|
25
|
+
return AbortSignal.any([...signals]);
|
|
26
|
+
}
|
|
27
|
+
const combined = new AbortController();
|
|
28
|
+
for (const s of signals) {
|
|
29
|
+
if (s.aborted) {
|
|
30
|
+
combined.abort();
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
s.addEventListener("abort", () => combined.abort(), { once: true });
|
|
34
|
+
}
|
|
35
|
+
return combined.signal;
|
|
36
|
+
}
|
|
1
37
|
/**
|
|
2
38
|
* `fetch` with a timeout abort signal merged onto the caller's own signal.
|
|
3
39
|
* The default timeout is 15s. Pass `Infinity` to disable the timeout
|
|
@@ -19,7 +55,7 @@ export function fetchWithTimeout(url, options = {}, timeoutMs = 15000) {
|
|
|
19
55
|
? setTimeout(() => controller.abort(), timeoutMs)
|
|
20
56
|
: null;
|
|
21
57
|
const signals = [controller.signal, options.signal].filter((s) => s != null);
|
|
22
|
-
const combinedSignal =
|
|
58
|
+
const combinedSignal = combineSignals(signals);
|
|
23
59
|
return fetch(url, { ...options, signal: combinedSignal }).finally(() => {
|
|
24
60
|
if (id !== null) {
|
|
25
61
|
clearTimeout(id);
|
package/lib/utils/fetch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,gBAAgB,CAC9B,GAAW,EACX,UAAuB,EAAE,EACzB,SAAS,GAAG,KAAK;IAEjB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,EAAE,GACN,SAAS,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;QACzC,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC;QACjD,CAAC,CAAC,IAAI,CAAC;IACX,MAAM,OAAO,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAoB,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;IAC/F,MAAM,cAAc,GAAG,
|
|
1
|
+
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAS,cAAc,CAAC,OAA+B;IACrD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,sFAAsF;QACtF,OAAO,OAAO,CAAC,CAAC,CAAE,CAAC;IACrB,CAAC;IACD,IAAI,OAAO,WAAW,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;QAC1C,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IACvC,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,eAAe,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;YACd,QAAQ,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM;QACR,CAAC;QACD,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,QAAQ,CAAC,MAAM,CAAC;AACzB,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,gBAAgB,CAC9B,GAAW,EACX,UAAuB,EAAE,EACzB,SAAS,GAAG,KAAK;IAEjB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,EAAE,GACN,SAAS,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;QACzC,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC;QACjD,CAAC,CAAC,IAAI,CAAC;IACX,MAAM,OAAO,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAoB,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;IAC/F,MAAM,cAAc,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IAC/C,OAAO,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;QACrE,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YAChB,YAAY,CAAC,EAAE,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useState } from "react";
|
|
2
|
-
import { View } from "react-native";
|
|
2
|
+
import { Platform, View } from "react-native";
|
|
3
3
|
import Toast from "react-native-toast-message";
|
|
4
4
|
import { Button } from "../../components/button";
|
|
5
5
|
import { PasswordInput } from "../../components/input";
|
|
@@ -90,7 +90,14 @@ export function LockOverlay({ onUnlock, onSignOut, successMessage }: LockOverlay
|
|
|
90
90
|
}}
|
|
91
91
|
placeholder="Master password"
|
|
92
92
|
error={error}
|
|
93
|
-
|
|
93
|
+
// Web: autofocus on a login-style page is expected desktop
|
|
94
|
+
// UX. Native: this overlay mounts unconditionally at app
|
|
95
|
+
// launch (and can be visible under the OTA install overlay,
|
|
96
|
+
// before the user has done anything at all), so autofocus
|
|
97
|
+
// pops the on-screen keyboard immediately and unprompted —
|
|
98
|
+
// reported as a real annoyance on 2026-08-17. Unlock should
|
|
99
|
+
// wait for an explicit tap on the field.
|
|
100
|
+
autoFocus={Platform.OS === "web"}
|
|
94
101
|
returnKeyType="done"
|
|
95
102
|
onSubmitEditing={handleUnlock}
|
|
96
103
|
accessibilityLabel="Master password"
|
package/src/utils/fetch.ts
CHANGED
|
@@ -1,3 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Combines multiple AbortSignals into one that aborts when any input does.
|
|
3
|
+
* Prefers the native `AbortSignal.any` where present (modern browsers);
|
|
4
|
+
* falls back to manual event-listener wiring where it isn't.
|
|
5
|
+
*
|
|
6
|
+
* That fallback is load-bearing, not defensive padding: React Native
|
|
7
|
+
* doesn't provide a native AbortController at all — `setUpXHR.js` installs
|
|
8
|
+
* one from the third-party `abort-controller` npm package (pinned at
|
|
9
|
+
* v3.0.0 in this tree), which predates `AbortSignal.any` entering the
|
|
10
|
+
* WHATWG spec. Calling it unconditionally on native evaluates to invoking
|
|
11
|
+
* `undefined` as a function, which Hermes reports as the unhelpfully
|
|
12
|
+
* generic "undefined is not a function" — confirmed for real on
|
|
13
|
+
* 2026-08-17, the first time a native call site (a vault item detail
|
|
14
|
+
* screen, via its own cancellation AbortSignal) exercised the
|
|
15
|
+
* `signals.length > 1` branch this function has always had; every
|
|
16
|
+
* previous native caller only ever supplied the internal timeout signal,
|
|
17
|
+
* so `AbortSignal.any` had simply never been reached before.
|
|
18
|
+
*/
|
|
19
|
+
function combineSignals(signals: readonly AbortSignal[]): AbortSignal {
|
|
20
|
+
if (signals.length === 1) {
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length checked
|
|
22
|
+
return signals[0]!;
|
|
23
|
+
}
|
|
24
|
+
if (typeof AbortSignal.any === "function") {
|
|
25
|
+
return AbortSignal.any([...signals]);
|
|
26
|
+
}
|
|
27
|
+
const combined = new AbortController();
|
|
28
|
+
for (const s of signals) {
|
|
29
|
+
if (s.aborted) {
|
|
30
|
+
combined.abort();
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
s.addEventListener("abort", () => combined.abort(), { once: true });
|
|
34
|
+
}
|
|
35
|
+
return combined.signal;
|
|
36
|
+
}
|
|
37
|
+
|
|
1
38
|
/**
|
|
2
39
|
* `fetch` with a timeout abort signal merged onto the caller's own signal.
|
|
3
40
|
* The default timeout is 15s. Pass `Infinity` to disable the timeout
|
|
@@ -24,7 +61,7 @@ export function fetchWithTimeout(
|
|
|
24
61
|
? setTimeout(() => controller.abort(), timeoutMs)
|
|
25
62
|
: null;
|
|
26
63
|
const signals = [controller.signal, options.signal].filter((s): s is AbortSignal => s != null);
|
|
27
|
-
const combinedSignal =
|
|
64
|
+
const combinedSignal = combineSignals(signals);
|
|
28
65
|
return fetch(url, { ...options, signal: combinedSignal }).finally(() => {
|
|
29
66
|
if (id !== null) {
|
|
30
67
|
clearTimeout(id);
|