@runhuman/sensor 0.2.5 → 0.3.1
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/dist/index.d.mts +29 -5
- package/dist/index.d.ts +29 -5
- package/dist/index.js +160 -44
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +149 -43
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -52,6 +52,7 @@ interface SessionManagerConfig {
|
|
|
52
52
|
}
|
|
53
53
|
declare class SessionManager {
|
|
54
54
|
private state;
|
|
55
|
+
private _disabled;
|
|
55
56
|
private sessionId;
|
|
56
57
|
private activeJobId;
|
|
57
58
|
private pollTimer;
|
|
@@ -66,6 +67,8 @@ declare class SessionManager {
|
|
|
66
67
|
getSnapshot(): SessionState;
|
|
67
68
|
getSessionId(): string | null;
|
|
68
69
|
getActiveJobId(): string | null;
|
|
70
|
+
/** True when the API rejected the session (e.g. subscription tier). Hides the overlay. */
|
|
71
|
+
isDisabled(): boolean;
|
|
69
72
|
/**
|
|
70
73
|
* Subscribe to state changes. Returns an unsubscribe function.
|
|
71
74
|
* Compatible with React's useSyncExternalStore.
|
|
@@ -168,20 +171,40 @@ declare class Runhuman {
|
|
|
168
171
|
* After calling destroy(), you can call init() again.
|
|
169
172
|
*/
|
|
170
173
|
destroy(): Promise<void>;
|
|
171
|
-
/** Access the session manager (used by <
|
|
174
|
+
/** Access the session manager (used by <RunhumanProvider /> for reactive state) */
|
|
172
175
|
getSessionManager(): SessionManager;
|
|
173
|
-
/** Access the API client (used by <
|
|
176
|
+
/** Access the API client (used by <RunhumanProvider /> for short code resolution) */
|
|
174
177
|
getApiClient(): ApiClient;
|
|
175
178
|
private log;
|
|
176
179
|
}
|
|
177
180
|
|
|
178
181
|
type OverlayPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
179
|
-
interface
|
|
182
|
+
interface RunhumanProviderProps {
|
|
180
183
|
children: React.ReactNode;
|
|
184
|
+
/** API key for authentication (e.g., 'rh_...') */
|
|
185
|
+
apiKey: string;
|
|
186
|
+
/** Set to false to disable the sensor entirely (e.g., in production). Default: true */
|
|
187
|
+
enabled?: boolean;
|
|
181
188
|
/** Corner for the overlay UI (default: 'bottom-right') */
|
|
182
189
|
position?: OverlayPosition;
|
|
190
|
+
/** Base URL of the Runhuman API (defaults to production) */
|
|
191
|
+
baseUrl?: string;
|
|
192
|
+
/** Job ID if known upfront (e.g., from deep link params at app launch) */
|
|
193
|
+
jobId?: string;
|
|
194
|
+
/** Target platform (defaults to 'react-native') */
|
|
195
|
+
platform?: TelemetryPlatform;
|
|
196
|
+
/** How often to flush buffered events in ms (default: 5000) */
|
|
197
|
+
flushIntervalMs?: number;
|
|
198
|
+
/** How often to poll for job status in ms (default: 10000) */
|
|
199
|
+
pollIntervalMs?: number;
|
|
200
|
+
/** Max events in the ring buffer before FIFO eviction (default: 1000) */
|
|
201
|
+
maxBufferSize?: number;
|
|
202
|
+
/** Enable deep link activation (default: true) */
|
|
203
|
+
enableDeepLinks?: boolean;
|
|
204
|
+
/** Log debug info to console (default: false) */
|
|
205
|
+
debug?: boolean;
|
|
183
206
|
}
|
|
184
|
-
declare function
|
|
207
|
+
declare function RunhumanProvider({ children, apiKey, enabled, position, baseUrl, jobId, platform, flushIntervalMs, pollIntervalMs, maxBufferSize, enableDeepLinks, debug, }: RunhumanProviderProps): react_jsx_runtime.JSX.Element;
|
|
185
208
|
|
|
186
209
|
/**
|
|
187
210
|
* React hook for subscribing to sensor state changes.
|
|
@@ -192,6 +215,7 @@ interface SensorState {
|
|
|
192
215
|
state: SessionState;
|
|
193
216
|
activeJobId: string | null;
|
|
194
217
|
sessionId: string | null;
|
|
218
|
+
disabled: boolean;
|
|
195
219
|
}
|
|
196
220
|
/**
|
|
197
221
|
* Subscribe to the sensor's session state.
|
|
@@ -199,4 +223,4 @@ interface SensorState {
|
|
|
199
223
|
*/
|
|
200
224
|
declare function useSensorState(): SensorState;
|
|
201
225
|
|
|
202
|
-
export { ApiClient, type OverlayPosition, Runhuman, type RunhumanConfig,
|
|
226
|
+
export { ApiClient, type OverlayPosition, Runhuman, type RunhumanConfig, RunhumanProvider, type RunhumanProviderProps, type SensorState, type SessionState, useSensorState };
|
package/dist/index.d.ts
CHANGED
|
@@ -52,6 +52,7 @@ interface SessionManagerConfig {
|
|
|
52
52
|
}
|
|
53
53
|
declare class SessionManager {
|
|
54
54
|
private state;
|
|
55
|
+
private _disabled;
|
|
55
56
|
private sessionId;
|
|
56
57
|
private activeJobId;
|
|
57
58
|
private pollTimer;
|
|
@@ -66,6 +67,8 @@ declare class SessionManager {
|
|
|
66
67
|
getSnapshot(): SessionState;
|
|
67
68
|
getSessionId(): string | null;
|
|
68
69
|
getActiveJobId(): string | null;
|
|
70
|
+
/** True when the API rejected the session (e.g. subscription tier). Hides the overlay. */
|
|
71
|
+
isDisabled(): boolean;
|
|
69
72
|
/**
|
|
70
73
|
* Subscribe to state changes. Returns an unsubscribe function.
|
|
71
74
|
* Compatible with React's useSyncExternalStore.
|
|
@@ -168,20 +171,40 @@ declare class Runhuman {
|
|
|
168
171
|
* After calling destroy(), you can call init() again.
|
|
169
172
|
*/
|
|
170
173
|
destroy(): Promise<void>;
|
|
171
|
-
/** Access the session manager (used by <
|
|
174
|
+
/** Access the session manager (used by <RunhumanProvider /> for reactive state) */
|
|
172
175
|
getSessionManager(): SessionManager;
|
|
173
|
-
/** Access the API client (used by <
|
|
176
|
+
/** Access the API client (used by <RunhumanProvider /> for short code resolution) */
|
|
174
177
|
getApiClient(): ApiClient;
|
|
175
178
|
private log;
|
|
176
179
|
}
|
|
177
180
|
|
|
178
181
|
type OverlayPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
179
|
-
interface
|
|
182
|
+
interface RunhumanProviderProps {
|
|
180
183
|
children: React.ReactNode;
|
|
184
|
+
/** API key for authentication (e.g., 'rh_...') */
|
|
185
|
+
apiKey: string;
|
|
186
|
+
/** Set to false to disable the sensor entirely (e.g., in production). Default: true */
|
|
187
|
+
enabled?: boolean;
|
|
181
188
|
/** Corner for the overlay UI (default: 'bottom-right') */
|
|
182
189
|
position?: OverlayPosition;
|
|
190
|
+
/** Base URL of the Runhuman API (defaults to production) */
|
|
191
|
+
baseUrl?: string;
|
|
192
|
+
/** Job ID if known upfront (e.g., from deep link params at app launch) */
|
|
193
|
+
jobId?: string;
|
|
194
|
+
/** Target platform (defaults to 'react-native') */
|
|
195
|
+
platform?: TelemetryPlatform;
|
|
196
|
+
/** How often to flush buffered events in ms (default: 5000) */
|
|
197
|
+
flushIntervalMs?: number;
|
|
198
|
+
/** How often to poll for job status in ms (default: 10000) */
|
|
199
|
+
pollIntervalMs?: number;
|
|
200
|
+
/** Max events in the ring buffer before FIFO eviction (default: 1000) */
|
|
201
|
+
maxBufferSize?: number;
|
|
202
|
+
/** Enable deep link activation (default: true) */
|
|
203
|
+
enableDeepLinks?: boolean;
|
|
204
|
+
/** Log debug info to console (default: false) */
|
|
205
|
+
debug?: boolean;
|
|
183
206
|
}
|
|
184
|
-
declare function
|
|
207
|
+
declare function RunhumanProvider({ children, apiKey, enabled, position, baseUrl, jobId, platform, flushIntervalMs, pollIntervalMs, maxBufferSize, enableDeepLinks, debug, }: RunhumanProviderProps): react_jsx_runtime.JSX.Element;
|
|
185
208
|
|
|
186
209
|
/**
|
|
187
210
|
* React hook for subscribing to sensor state changes.
|
|
@@ -192,6 +215,7 @@ interface SensorState {
|
|
|
192
215
|
state: SessionState;
|
|
193
216
|
activeJobId: string | null;
|
|
194
217
|
sessionId: string | null;
|
|
218
|
+
disabled: boolean;
|
|
195
219
|
}
|
|
196
220
|
/**
|
|
197
221
|
* Subscribe to the sensor's session state.
|
|
@@ -199,4 +223,4 @@ interface SensorState {
|
|
|
199
223
|
*/
|
|
200
224
|
declare function useSensorState(): SensorState;
|
|
201
225
|
|
|
202
|
-
export { ApiClient, type OverlayPosition, Runhuman, type RunhumanConfig,
|
|
226
|
+
export { ApiClient, type OverlayPosition, Runhuman, type RunhumanConfig, RunhumanProvider, type RunhumanProviderProps, type SensorState, type SessionState, useSensorState };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,13 +17,21 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
21
31
|
var index_exports = {};
|
|
22
32
|
__export(index_exports, {
|
|
23
33
|
Runhuman: () => Runhuman,
|
|
24
|
-
|
|
34
|
+
RunhumanProvider: () => RunhumanProvider,
|
|
25
35
|
useSensorState: () => useSensorState
|
|
26
36
|
});
|
|
27
37
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -185,6 +195,10 @@ var apiRoutes = {
|
|
|
185
195
|
jobs: defineRoute("/jobs"),
|
|
186
196
|
/** Get/update/delete specific job */
|
|
187
197
|
job: defineRoute("/jobs/:jobId"),
|
|
198
|
+
/** Cancel a job */
|
|
199
|
+
jobCancel: defineRoute("/jobs/:jobId/cancel"),
|
|
200
|
+
/** Create a GitHub issue from an extracted finding (user-initiated) */
|
|
201
|
+
jobCreateIssue: defineRoute("/jobs/:jobId/create-issue"),
|
|
188
202
|
/** Get job status (for polling) */
|
|
189
203
|
jobStatus: defineRoute("/jobs/:jobId/status"),
|
|
190
204
|
/** Get individual job artifact by type */
|
|
@@ -303,6 +317,8 @@ var apiRoutes = {
|
|
|
303
317
|
githubLink: defineRoute("/github/link"),
|
|
304
318
|
/** List issues for a repo (by owner/repo) */
|
|
305
319
|
githubIssuesByRepo: defineRoute("/github/issues/:owner/:repo"),
|
|
320
|
+
/** Get a single issue for a repo (by owner/repo/issueNumber) */
|
|
321
|
+
githubIssueByRepo: defineRoute("/github/issues/:owner/:repo/:issueNumber"),
|
|
306
322
|
/** List issues (by projectId query param) */
|
|
307
323
|
githubIssues: defineRoute("/github/issues"),
|
|
308
324
|
/** Get a single issue */
|
|
@@ -457,8 +473,10 @@ var apiRoutes = {
|
|
|
457
473
|
organizationJobs: defineRoute("/organizations/:organizationId/jobs"),
|
|
458
474
|
/** Transfer organization ownership */
|
|
459
475
|
organizationTransferOwnership: defineRoute("/organizations/:organizationId/transfer-ownership"),
|
|
460
|
-
/**
|
|
476
|
+
/** List/create organization API keys */
|
|
461
477
|
organizationApiKeys: defineRoute("/organizations/:organizationId/api-keys"),
|
|
478
|
+
/** Get/revoke/delete a specific organization API key */
|
|
479
|
+
organizationApiKey: defineRoute("/organizations/:organizationId/api-keys/:keyId"),
|
|
462
480
|
/** Get GitHub installations for an organization */
|
|
463
481
|
organizationGitHubInstallations: defineRoute("/organizations/:organizationId/github/installations"),
|
|
464
482
|
/** Get/delete specific GitHub installation for an organization */
|
|
@@ -567,7 +585,7 @@ var ApiClient = class {
|
|
|
567
585
|
return this.get(apiRoutes.telemetrySessionStatus.build({ jobId }));
|
|
568
586
|
}
|
|
569
587
|
async resolveShortCode(code) {
|
|
570
|
-
const normalized = code.
|
|
588
|
+
const normalized = code.toUpperCase().trim();
|
|
571
589
|
try {
|
|
572
590
|
return await this.get(
|
|
573
591
|
apiRoutes.telemetryShortCodeResolve.build({ code: normalized })
|
|
@@ -842,6 +860,7 @@ var InterceptorManager = class {
|
|
|
842
860
|
var SessionManager = class {
|
|
843
861
|
constructor(config) {
|
|
844
862
|
this.state = "idle";
|
|
863
|
+
this._disabled = false;
|
|
845
864
|
this.sessionId = null;
|
|
846
865
|
this.activeJobId = null;
|
|
847
866
|
this.pollTimer = null;
|
|
@@ -864,6 +883,10 @@ var SessionManager = class {
|
|
|
864
883
|
getActiveJobId() {
|
|
865
884
|
return this.activeJobId;
|
|
866
885
|
}
|
|
886
|
+
/** True when the API rejected the session (e.g. subscription tier). Hides the overlay. */
|
|
887
|
+
isDisabled() {
|
|
888
|
+
return this._disabled;
|
|
889
|
+
}
|
|
867
890
|
/**
|
|
868
891
|
* Subscribe to state changes. Returns an unsubscribe function.
|
|
869
892
|
* Compatible with React's useSyncExternalStore.
|
|
@@ -948,12 +971,22 @@ var SessionManager = class {
|
|
|
948
971
|
async startSession() {
|
|
949
972
|
this.setState("active");
|
|
950
973
|
const now = /* @__PURE__ */ new Date();
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
974
|
+
let response;
|
|
975
|
+
try {
|
|
976
|
+
response = await this.config.apiClient.createSession({
|
|
977
|
+
jobId: this.activeJobId,
|
|
978
|
+
platform: this.config.platform,
|
|
979
|
+
sdkVersion: this.config.sdkVersion,
|
|
980
|
+
clientStartTime: now.toISOString()
|
|
981
|
+
});
|
|
982
|
+
} catch (error) {
|
|
983
|
+
const is403 = error instanceof Error && error.message.includes("403");
|
|
984
|
+
this.log(is403 ? "Subscription not eligible \u2014 disabling sensor" : "Session creation failed", { error });
|
|
985
|
+
if (is403) this._disabled = true;
|
|
986
|
+
this.activeJobId = null;
|
|
987
|
+
this.setState("idle");
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
957
990
|
this.sessionId = response.sessionId;
|
|
958
991
|
const sessionStartTime = now.getTime();
|
|
959
992
|
this.log("Session started", {
|
|
@@ -1161,11 +1194,11 @@ var Runhuman = class _Runhuman {
|
|
|
1161
1194
|
_Runhuman.instance = null;
|
|
1162
1195
|
this.log("Destroyed");
|
|
1163
1196
|
}
|
|
1164
|
-
/** Access the session manager (used by <
|
|
1197
|
+
/** Access the session manager (used by <RunhumanProvider /> for reactive state) */
|
|
1165
1198
|
getSessionManager() {
|
|
1166
1199
|
return this.sessionManager;
|
|
1167
1200
|
}
|
|
1168
|
-
/** Access the API client (used by <
|
|
1201
|
+
/** Access the API client (used by <RunhumanProvider /> for short code resolution) */
|
|
1169
1202
|
getApiClient() {
|
|
1170
1203
|
return this.apiClient;
|
|
1171
1204
|
}
|
|
@@ -1176,13 +1209,14 @@ var Runhuman = class _Runhuman {
|
|
|
1176
1209
|
}
|
|
1177
1210
|
};
|
|
1178
1211
|
|
|
1179
|
-
// src/overlay/
|
|
1212
|
+
// src/overlay/RunhumanProvider.tsx
|
|
1213
|
+
var import_react5 = require("react");
|
|
1180
1214
|
var import_react_native4 = require("react-native");
|
|
1181
1215
|
|
|
1182
1216
|
// src/overlay/use-sensor-state.ts
|
|
1183
1217
|
var import_react = require("react");
|
|
1184
1218
|
var import_react2 = require("react");
|
|
1185
|
-
var IDLE_STATE = { state: "idle", activeJobId: null, sessionId: null };
|
|
1219
|
+
var IDLE_STATE = { state: "idle", activeJobId: null, sessionId: null, disabled: false };
|
|
1186
1220
|
function tryGetInstance() {
|
|
1187
1221
|
try {
|
|
1188
1222
|
return Runhuman.getInstance();
|
|
@@ -1218,11 +1252,12 @@ function useSensorState() {
|
|
|
1218
1252
|
const state = sm.getSnapshot();
|
|
1219
1253
|
const activeJobId = sm.getActiveJobId();
|
|
1220
1254
|
const sessionId = sm.getSessionId();
|
|
1255
|
+
const disabled = sm.isDisabled();
|
|
1221
1256
|
const prev = cached.current;
|
|
1222
|
-
if (prev.state === state && prev.activeJobId === activeJobId && prev.sessionId === sessionId) {
|
|
1257
|
+
if (prev.state === state && prev.activeJobId === activeJobId && prev.sessionId === sessionId && prev.disabled === disabled) {
|
|
1223
1258
|
return prev;
|
|
1224
1259
|
}
|
|
1225
|
-
cached.current = { state, activeJobId, sessionId };
|
|
1260
|
+
cached.current = { state, activeJobId, sessionId, disabled };
|
|
1226
1261
|
return cached.current;
|
|
1227
1262
|
}, []);
|
|
1228
1263
|
return (0, import_react2.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
@@ -1263,6 +1298,11 @@ var overlayStyles = import_react_native.StyleSheet.create({
|
|
|
1263
1298
|
fontWeight: "600",
|
|
1264
1299
|
marginBottom: 8
|
|
1265
1300
|
},
|
|
1301
|
+
inputRow: {
|
|
1302
|
+
flexDirection: "row",
|
|
1303
|
+
alignItems: "center",
|
|
1304
|
+
gap: 6
|
|
1305
|
+
},
|
|
1266
1306
|
input: {
|
|
1267
1307
|
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
|
1268
1308
|
borderRadius: 8,
|
|
@@ -1276,9 +1316,25 @@ var overlayStyles = import_react_native.StyleSheet.create({
|
|
|
1276
1316
|
padding: 10,
|
|
1277
1317
|
textAlign: "center"
|
|
1278
1318
|
},
|
|
1319
|
+
inputFlex: {
|
|
1320
|
+
flex: 1
|
|
1321
|
+
},
|
|
1279
1322
|
inputError: {
|
|
1280
1323
|
borderColor: BRAND_RED
|
|
1281
1324
|
},
|
|
1325
|
+
pasteButton: {
|
|
1326
|
+
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
|
1327
|
+
borderRadius: 8,
|
|
1328
|
+
borderWidth: 1,
|
|
1329
|
+
borderColor: OVERLAY_BORDER,
|
|
1330
|
+
paddingVertical: 10,
|
|
1331
|
+
paddingHorizontal: 8
|
|
1332
|
+
},
|
|
1333
|
+
pasteButtonText: {
|
|
1334
|
+
color: "rgba(255, 255, 255, 0.6)",
|
|
1335
|
+
fontSize: 11,
|
|
1336
|
+
fontWeight: "600"
|
|
1337
|
+
},
|
|
1282
1338
|
submitButton: {
|
|
1283
1339
|
backgroundColor: BRAND_BLUE,
|
|
1284
1340
|
borderRadius: 8,
|
|
@@ -1345,6 +1401,14 @@ var overlayStyles = import_react_native.StyleSheet.create({
|
|
|
1345
1401
|
}
|
|
1346
1402
|
});
|
|
1347
1403
|
|
|
1404
|
+
// src/overlay/clipboard.ts
|
|
1405
|
+
var ReactNative = __toESM(require("react-native"));
|
|
1406
|
+
var RN = ReactNative;
|
|
1407
|
+
var clipboard = RN["Clipboard"];
|
|
1408
|
+
async function getClipboardText() {
|
|
1409
|
+
return clipboard.getString();
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1348
1412
|
// src/overlay/CodeEntryPanel.tsx
|
|
1349
1413
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
1350
1414
|
function CodeEntryPanel({ position }) {
|
|
@@ -1357,38 +1421,55 @@ function CodeEntryPanel({ position }) {
|
|
|
1357
1421
|
if (!trimmed) return;
|
|
1358
1422
|
setResolving(true);
|
|
1359
1423
|
setError(null);
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1424
|
+
try {
|
|
1425
|
+
const instance = Runhuman.getInstance();
|
|
1426
|
+
const result = await instance.getApiClient().resolveShortCode(trimmed);
|
|
1427
|
+
if (result) {
|
|
1428
|
+
await instance.activate(result.jobId);
|
|
1429
|
+
} else {
|
|
1430
|
+
setError("Invalid or expired code");
|
|
1431
|
+
setResolving(false);
|
|
1432
|
+
}
|
|
1433
|
+
} catch (err) {
|
|
1434
|
+
const message = err instanceof Error ? err.message : "Activation failed";
|
|
1435
|
+
setError(message);
|
|
1366
1436
|
setResolving(false);
|
|
1367
1437
|
}
|
|
1368
1438
|
};
|
|
1439
|
+
const handlePaste = async () => {
|
|
1440
|
+
const text = await getClipboardText();
|
|
1441
|
+
const trimmed = text.trim().toUpperCase().slice(0, 6);
|
|
1442
|
+
if (trimmed) {
|
|
1443
|
+
setCode(trimmed);
|
|
1444
|
+
setError(null);
|
|
1445
|
+
}
|
|
1446
|
+
};
|
|
1369
1447
|
if (minimized) {
|
|
1370
1448
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Pressable, { style: [overlayStyles.fab, overlayStyles[position]], onPress: () => setMinimized(false), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: overlayStyles.fabText, children: "RH" }) });
|
|
1371
1449
|
}
|
|
1372
1450
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: [overlayStyles.panel, overlayStyles[position]], children: [
|
|
1373
1451
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Pressable, { style: overlayStyles.minimizeButton, onPress: () => setMinimized(true), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: overlayStyles.minimizeText, children: "-" }) }),
|
|
1374
1452
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: overlayStyles.panelTitle, children: "Runhuman Sensor" }),
|
|
1375
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1453
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: overlayStyles.inputRow, children: [
|
|
1454
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1455
|
+
import_react_native2.TextInput,
|
|
1456
|
+
{
|
|
1457
|
+
style: [error ? { ...overlayStyles.input, ...overlayStyles.inputError } : overlayStyles.input, overlayStyles.inputFlex],
|
|
1458
|
+
value: code,
|
|
1459
|
+
onChangeText: (text) => {
|
|
1460
|
+
setCode(text.toUpperCase());
|
|
1461
|
+
setError(null);
|
|
1462
|
+
},
|
|
1463
|
+
placeholder: "XXXX",
|
|
1464
|
+
placeholderTextColor: "rgba(255,255,255,0.3)",
|
|
1465
|
+
autoCapitalize: "characters",
|
|
1466
|
+
maxLength: 6,
|
|
1467
|
+
editable: !resolving,
|
|
1468
|
+
onSubmitEditing: handleSubmit
|
|
1469
|
+
}
|
|
1470
|
+
),
|
|
1471
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Pressable, { style: overlayStyles.pasteButton, onPress: handlePaste, disabled: resolving, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: overlayStyles.pasteButtonText, children: "Paste" }) })
|
|
1472
|
+
] }),
|
|
1392
1473
|
error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: overlayStyles.errorText, children: error }) : null,
|
|
1393
1474
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1394
1475
|
import_react_native2.Pressable,
|
|
@@ -1431,7 +1512,7 @@ function ActiveIndicator({ state, position }) {
|
|
|
1431
1512
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.Animated.View, { style: [overlayStyles.indicator, overlayStyles[position], colorStyle, { opacity: pulse }] });
|
|
1432
1513
|
}
|
|
1433
1514
|
|
|
1434
|
-
// src/overlay/
|
|
1515
|
+
// src/overlay/RunhumanProvider.tsx
|
|
1435
1516
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1436
1517
|
var positionMap = {
|
|
1437
1518
|
"top-left": "topLeft",
|
|
@@ -1439,13 +1520,48 @@ var positionMap = {
|
|
|
1439
1520
|
"bottom-left": "bottomLeft",
|
|
1440
1521
|
"bottom-right": "bottomRight"
|
|
1441
1522
|
};
|
|
1442
|
-
function
|
|
1443
|
-
|
|
1523
|
+
function RunhumanProvider({
|
|
1524
|
+
children,
|
|
1525
|
+
apiKey,
|
|
1526
|
+
enabled = true,
|
|
1527
|
+
position = "bottom-right",
|
|
1528
|
+
baseUrl,
|
|
1529
|
+
jobId,
|
|
1530
|
+
platform,
|
|
1531
|
+
flushIntervalMs,
|
|
1532
|
+
pollIntervalMs,
|
|
1533
|
+
maxBufferSize,
|
|
1534
|
+
enableDeepLinks,
|
|
1535
|
+
debug
|
|
1536
|
+
}) {
|
|
1537
|
+
const initializedRef = (0, import_react5.useRef)(false);
|
|
1538
|
+
(0, import_react5.useEffect)(() => {
|
|
1539
|
+
if (!enabled || initializedRef.current) return;
|
|
1540
|
+
initializedRef.current = true;
|
|
1541
|
+
const config = {
|
|
1542
|
+
apiKey,
|
|
1543
|
+
baseUrl,
|
|
1544
|
+
jobId,
|
|
1545
|
+
platform,
|
|
1546
|
+
flushIntervalMs,
|
|
1547
|
+
pollIntervalMs,
|
|
1548
|
+
maxBufferSize,
|
|
1549
|
+
enableDeepLinks,
|
|
1550
|
+
debug
|
|
1551
|
+
};
|
|
1552
|
+
Runhuman.init(config);
|
|
1553
|
+
return () => {
|
|
1554
|
+
initializedRef.current = false;
|
|
1555
|
+
Runhuman.getInstance().destroy();
|
|
1556
|
+
};
|
|
1557
|
+
}, [enabled]);
|
|
1558
|
+
const { state, activeJobId, disabled } = useSensorState();
|
|
1559
|
+
const showOverlay = enabled && !disabled;
|
|
1444
1560
|
const posKey = positionMap[position];
|
|
1445
1561
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native4.View, { style: styles.container, children: [
|
|
1446
1562
|
children,
|
|
1447
|
-
state === "idle" && !activeJobId ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CodeEntryPanel, { position: posKey }) : null,
|
|
1448
|
-
state !== "idle" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ActiveIndicator, { state, position: posKey }) : null
|
|
1563
|
+
showOverlay && state === "idle" && !activeJobId ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CodeEntryPanel, { position: posKey }) : null,
|
|
1564
|
+
showOverlay && state !== "idle" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ActiveIndicator, { state, position: posKey }) : null
|
|
1449
1565
|
] });
|
|
1450
1566
|
}
|
|
1451
1567
|
var styles = import_react_native4.StyleSheet.create({
|
|
@@ -1456,7 +1572,7 @@ var styles = import_react_native4.StyleSheet.create({
|
|
|
1456
1572
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1457
1573
|
0 && (module.exports = {
|
|
1458
1574
|
Runhuman,
|
|
1459
|
-
|
|
1575
|
+
RunhumanProvider,
|
|
1460
1576
|
useSensorState
|
|
1461
1577
|
});
|
|
1462
1578
|
//# sourceMappingURL=index.js.map
|