@appilots/sdk 0.11.1 → 0.13.0
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/control-transformer.js +69 -0
- package/dist/.build-meta.json +3 -3
- package/dist/{chunk-X4MPSZL3.js → chunk-AJDHZRBN.js} +1180 -487
- package/dist/{chunk-DRXUBLGY.js → chunk-ALJGKORS.js} +8 -8
- package/dist/{chunk-PQZ64CCE.mjs → chunk-HRWBK35Y.mjs} +6007 -527
- package/dist/{chunk-LLH7QCSX.mjs → chunk-L3SY3Q4K.mjs} +1 -1
- package/dist/{chunk-GSHE45YX.mjs → chunk-UYBKXULM.mjs} +903 -223
- package/dist/{chunk-KZ2BLMS4.js → chunk-UZ2D4BVX.js} +6026 -525
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.js +11 -11
- package/dist/hooks/index.mjs +2 -2
- package/dist/{index-C01Spw6F.d.mts → index-CI4jmSoP.d.mts} +136 -549
- package/dist/{index-C01Spw6F.d.ts → index-CI4jmSoP.d.ts} +136 -549
- package/dist/index.d.mts +1472 -76
- package/dist/index.d.ts +1472 -76
- package/dist/index.js +1100 -673
- package/dist/index.mjs +933 -565
- package/dist/navigation/index.d.mts +64 -7
- package/dist/navigation/index.d.ts +64 -7
- package/dist/navigation/index.js +13 -13
- package/dist/navigation/index.mjs +2 -2
- package/metro.d.ts +3 -5
- package/metro.js +46 -5
- package/package.json +16 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkUZ2D4BVX_js = require('./chunk-UZ2D4BVX.js');
|
|
4
4
|
var React = require('react');
|
|
5
5
|
var reactNative = require('react-native');
|
|
6
6
|
|
|
@@ -8,6 +8,261 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
|
8
8
|
|
|
9
9
|
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
10
10
|
|
|
11
|
+
// src/i18n/bundles/pt-BR.ts
|
|
12
|
+
var ptBR = {
|
|
13
|
+
chatTitle: "Assistente Appilots",
|
|
14
|
+
clearButton: "Limpar",
|
|
15
|
+
inputPlaceholder: "Digite uma mensagem...",
|
|
16
|
+
emptyTitle: "Como posso ajudar?",
|
|
17
|
+
emptySubtitle: "Navego, preencho formul\xE1rios e executo a\xE7\xF5es neste app.",
|
|
18
|
+
thinking: "Pensando...",
|
|
19
|
+
statusAnalyzing: "Analisando a tela...",
|
|
20
|
+
statusWaitingApp: "Aguardando o app responder...",
|
|
21
|
+
statusAdjusting: "Ajustando o plano...",
|
|
22
|
+
poweredBy: "Powered by Appilots",
|
|
23
|
+
approve: "Aprovar",
|
|
24
|
+
reject: "Rejeitar",
|
|
25
|
+
cancelledByUser: "Cancelado pelo usu\xE1rio",
|
|
26
|
+
confirmDestructiveTitle: "A\xE7\xE3o destrutiva",
|
|
27
|
+
confirmTitle: "Confirma\xE7\xE3o necess\xE1ria",
|
|
28
|
+
confirmMessage: 'Tem certeza que deseja "{action}"?',
|
|
29
|
+
confirmDestructiveApprove: "Sim, executar",
|
|
30
|
+
confirmApprove: "Confirmar",
|
|
31
|
+
confirmCancel: "Cancelar",
|
|
32
|
+
confirmThisAction: "esta a\xE7\xE3o",
|
|
33
|
+
unknownAction: "A\xE7\xE3o desconhecida",
|
|
34
|
+
somethingWentWrong: "Algo deu errado",
|
|
35
|
+
openChatA11y: "Abrir chat do assistente",
|
|
36
|
+
closeChatA11y: "Fechar chat do assistente",
|
|
37
|
+
stopGeneratingA11y: "Parar gera\xE7\xE3o",
|
|
38
|
+
talkToHumanA11y: "Falar com um atendente humano",
|
|
39
|
+
humanAgentLabel: "Atendente",
|
|
40
|
+
escalationRequested: "Certo! Chamei um atendente humano. Voc\xEA pode continuar usando o app normalmente enquanto isso.",
|
|
41
|
+
escalationConnected: "Um atendente entrou na conversa.",
|
|
42
|
+
escalationResolved: "O atendimento humano foi encerrado. Voltei a te ajudar por aqui.",
|
|
43
|
+
escalationOffer: "Se preferir, posso chamar uma pessoa para ajudar.",
|
|
44
|
+
escalationOfferChip: "Falar com um atendente",
|
|
45
|
+
escalationPendingBanner: "Aguardando um atendente...",
|
|
46
|
+
escalationActiveBanner: "Voc\xEA est\xE1 falando com um atendente",
|
|
47
|
+
pillWorking: "Trabalhando...",
|
|
48
|
+
pillExpandA11y: "Abrir a conversa do assistente",
|
|
49
|
+
pillStopA11y: "Parar o assistente",
|
|
50
|
+
missionPause: "Pausar",
|
|
51
|
+
missionResume: "Retomar tarefa",
|
|
52
|
+
missionCancel: "Cancelar tarefa",
|
|
53
|
+
missionPaused: "Pausada",
|
|
54
|
+
pillDone: "Pronto \u2014 toque para ver",
|
|
55
|
+
micStartA11y: "Segurar para falar",
|
|
56
|
+
micStopA11y: "Soltar para enviar",
|
|
57
|
+
micListening: "Ouvindo..."
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// src/i18n/bundles/en.ts
|
|
61
|
+
var en = {
|
|
62
|
+
chatTitle: "Appilots Assistant",
|
|
63
|
+
clearButton: "Clear",
|
|
64
|
+
inputPlaceholder: "Type a message...",
|
|
65
|
+
emptyTitle: "How can I help?",
|
|
66
|
+
emptySubtitle: "I navigate, fill forms, and run actions in this app.",
|
|
67
|
+
thinking: "Thinking...",
|
|
68
|
+
statusAnalyzing: "Reading the screen...",
|
|
69
|
+
statusWaitingApp: "Waiting for the app...",
|
|
70
|
+
statusAdjusting: "Adjusting the plan...",
|
|
71
|
+
poweredBy: "Powered by Appilots",
|
|
72
|
+
approve: "Approve",
|
|
73
|
+
reject: "Reject",
|
|
74
|
+
cancelledByUser: "Cancelled by user",
|
|
75
|
+
confirmDestructiveTitle: "Destructive action",
|
|
76
|
+
confirmTitle: "Confirmation needed",
|
|
77
|
+
confirmMessage: 'Are you sure you want to "{action}"?',
|
|
78
|
+
confirmDestructiveApprove: "Yes, do it",
|
|
79
|
+
confirmApprove: "Confirm",
|
|
80
|
+
confirmCancel: "Cancel",
|
|
81
|
+
confirmThisAction: "this action",
|
|
82
|
+
unknownAction: "Unknown action",
|
|
83
|
+
somethingWentWrong: "Something went wrong",
|
|
84
|
+
openChatA11y: "Open assistant chat",
|
|
85
|
+
closeChatA11y: "Close assistant chat",
|
|
86
|
+
stopGeneratingA11y: "Stop generating",
|
|
87
|
+
talkToHumanA11y: "Talk to a human agent",
|
|
88
|
+
humanAgentLabel: "Agent",
|
|
89
|
+
escalationRequested: "Done! I've called a human agent. You can keep using the app normally in the meantime.",
|
|
90
|
+
escalationConnected: "A human agent joined the conversation.",
|
|
91
|
+
escalationResolved: "The human handoff has ended. I'm back to help you here.",
|
|
92
|
+
escalationOffer: "If you prefer, I can bring in a person to help.",
|
|
93
|
+
escalationOfferChip: "Talk to a human",
|
|
94
|
+
escalationPendingBanner: "Waiting for a human agent...",
|
|
95
|
+
escalationActiveBanner: "You're talking to a human agent",
|
|
96
|
+
pillWorking: "Working...",
|
|
97
|
+
pillExpandA11y: "Open the assistant conversation",
|
|
98
|
+
pillStopA11y: "Stop the assistant",
|
|
99
|
+
missionPause: "Pause",
|
|
100
|
+
missionResume: "Resume task",
|
|
101
|
+
missionCancel: "Cancel task",
|
|
102
|
+
missionPaused: "Paused",
|
|
103
|
+
pillDone: "Done \u2014 tap to read",
|
|
104
|
+
micStartA11y: "Hold to talk",
|
|
105
|
+
micStopA11y: "Release to send",
|
|
106
|
+
micListening: "Listening..."
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// src/i18n/bundles/es.ts
|
|
110
|
+
var es = {
|
|
111
|
+
chatTitle: "Asistente Appilots",
|
|
112
|
+
clearButton: "Limpiar",
|
|
113
|
+
inputPlaceholder: "Escribe un mensaje...",
|
|
114
|
+
emptyTitle: "\xBFEn qu\xE9 puedo ayudarte?",
|
|
115
|
+
emptySubtitle: "Navego, relleno formularios y ejecuto acciones en esta app.",
|
|
116
|
+
thinking: "Pensando...",
|
|
117
|
+
statusAnalyzing: "Analizando la pantalla...",
|
|
118
|
+
statusWaitingApp: "Esperando a la app...",
|
|
119
|
+
statusAdjusting: "Ajustando el plan...",
|
|
120
|
+
poweredBy: "Hecho con Appilots",
|
|
121
|
+
approve: "Aprobar",
|
|
122
|
+
reject: "Rechazar",
|
|
123
|
+
cancelledByUser: "Cancelado por el usuario",
|
|
124
|
+
confirmDestructiveTitle: "Acci\xF3n destructiva",
|
|
125
|
+
confirmTitle: "Confirmaci\xF3n necesaria",
|
|
126
|
+
confirmMessage: '\xBFSeguro que quieres "{action}"?',
|
|
127
|
+
confirmDestructiveApprove: "S\xED, ejecutar",
|
|
128
|
+
confirmApprove: "Confirmar",
|
|
129
|
+
confirmCancel: "Cancelar",
|
|
130
|
+
confirmThisAction: "esta acci\xF3n",
|
|
131
|
+
unknownAction: "Acci\xF3n desconocida",
|
|
132
|
+
somethingWentWrong: "Algo sali\xF3 mal",
|
|
133
|
+
openChatA11y: "Abrir chat del asistente",
|
|
134
|
+
closeChatA11y: "Cerrar chat del asistente",
|
|
135
|
+
stopGeneratingA11y: "Detener generaci\xF3n",
|
|
136
|
+
talkToHumanA11y: "Hablar con un agente humano",
|
|
137
|
+
humanAgentLabel: "Agente",
|
|
138
|
+
escalationRequested: "\xA1Listo! Llam\xE9 a un agente humano. Mientras tanto puedes seguir usando la app con normalidad.",
|
|
139
|
+
escalationConnected: "Un agente humano se uni\xF3 a la conversaci\xF3n.",
|
|
140
|
+
escalationResolved: "La atenci\xF3n humana termin\xF3. Vuelvo a ayudarte por aqu\xED.",
|
|
141
|
+
escalationOffer: "Si prefieres, puedo llamar a una persona para ayudarte.",
|
|
142
|
+
escalationOfferChip: "Hablar con un agente",
|
|
143
|
+
escalationPendingBanner: "Esperando a un agente...",
|
|
144
|
+
escalationActiveBanner: "Est\xE1s hablando con un agente humano",
|
|
145
|
+
pillWorking: "Trabajando...",
|
|
146
|
+
pillExpandA11y: "Abrir la conversaci\xF3n del asistente",
|
|
147
|
+
pillStopA11y: "Detener el asistente",
|
|
148
|
+
missionPause: "Pausar",
|
|
149
|
+
missionResume: "Reanudar tarea",
|
|
150
|
+
missionCancel: "Cancelar tarea",
|
|
151
|
+
missionPaused: "Pausada",
|
|
152
|
+
pillDone: "Listo \u2014 toca para ver",
|
|
153
|
+
micStartA11y: "Mantener para hablar",
|
|
154
|
+
micStopA11y: "Soltar para enviar",
|
|
155
|
+
micListening: "Escuchando..."
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// src/i18n/bundles/fr.ts
|
|
159
|
+
var fr = {
|
|
160
|
+
chatTitle: "Assistant Appilots",
|
|
161
|
+
clearButton: "Effacer",
|
|
162
|
+
inputPlaceholder: "\xC9crivez un message\u2026",
|
|
163
|
+
emptyTitle: "Comment puis-je vous aider ?",
|
|
164
|
+
emptySubtitle: "Je navigue, remplis les formulaires et effectue des actions dans cette application.",
|
|
165
|
+
thinking: "R\xE9flexion en cours\u2026",
|
|
166
|
+
statusAnalyzing: "Lecture de l\u2019\xE9cran\u2026",
|
|
167
|
+
statusWaitingApp: "En attente de l\u2019application\u2026",
|
|
168
|
+
statusAdjusting: "Ajustement du plan\u2026",
|
|
169
|
+
poweredBy: "Propuls\xE9 par Appilots",
|
|
170
|
+
approve: "Approuver",
|
|
171
|
+
reject: "Refuser",
|
|
172
|
+
cancelledByUser: "Annul\xE9 par l\u2019utilisateur",
|
|
173
|
+
confirmDestructiveTitle: "Action destructive",
|
|
174
|
+
confirmTitle: "Confirmation requise",
|
|
175
|
+
confirmMessage: "Voulez-vous vraiment \xAB {action} \xBB ?",
|
|
176
|
+
confirmDestructiveApprove: "Oui, ex\xE9cuter",
|
|
177
|
+
confirmApprove: "Confirmer",
|
|
178
|
+
confirmCancel: "Annuler",
|
|
179
|
+
confirmThisAction: "cette action",
|
|
180
|
+
unknownAction: "Action inconnue",
|
|
181
|
+
somethingWentWrong: "Une erreur est survenue",
|
|
182
|
+
openChatA11y: "Ouvrir la conversation avec l\u2019assistant",
|
|
183
|
+
closeChatA11y: "Fermer la conversation",
|
|
184
|
+
stopGeneratingA11y: "Arr\xEAter la g\xE9n\xE9ration",
|
|
185
|
+
talkToHumanA11y: "Parler \xE0 un conseiller",
|
|
186
|
+
humanAgentLabel: "Conseiller",
|
|
187
|
+
escalationRequested: "J\u2019ai contact\xE9 un conseiller. Vous pouvez continuer \xE0 utiliser l\u2019application en attendant.",
|
|
188
|
+
escalationConnected: "Un conseiller a rejoint la conversation.",
|
|
189
|
+
escalationResolved: "L\u2019intervention du conseiller est termin\xE9e. Je peux \xE0 nouveau vous aider.",
|
|
190
|
+
escalationOffer: "Si vous pr\xE9f\xE9rez, je peux faire appel \xE0 un conseiller.",
|
|
191
|
+
escalationOfferChip: "Parler \xE0 un conseiller",
|
|
192
|
+
escalationPendingBanner: "En attente d\u2019un conseiller\u2026",
|
|
193
|
+
escalationActiveBanner: "Vous discutez avec un conseiller",
|
|
194
|
+
pillWorking: "En cours\u2026",
|
|
195
|
+
pillExpandA11y: "Ouvrir la conversation avec l\u2019assistant",
|
|
196
|
+
pillStopA11y: "Arr\xEAter l\u2019assistant",
|
|
197
|
+
missionPause: "Mettre en pause",
|
|
198
|
+
missionResume: "Reprendre la t\xE2che",
|
|
199
|
+
missionCancel: "Annuler la t\xE2che",
|
|
200
|
+
missionPaused: "En pause",
|
|
201
|
+
pillDone: "Termin\xE9 \u2014 touchez pour lire",
|
|
202
|
+
micStartA11y: "Maintenez pour parler",
|
|
203
|
+
micStopA11y: "Rel\xE2chez pour envoyer",
|
|
204
|
+
micListening: "\xC9coute en cours\u2026"
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
// src/i18n/I18nProvider.tsx
|
|
208
|
+
var BUNDLES = {
|
|
209
|
+
"pt-BR": ptBR,
|
|
210
|
+
en,
|
|
211
|
+
es,
|
|
212
|
+
fr
|
|
213
|
+
};
|
|
214
|
+
var DEFAULT_LOCALE = "en";
|
|
215
|
+
function detectDeviceLocale() {
|
|
216
|
+
try {
|
|
217
|
+
let raw;
|
|
218
|
+
if (reactNative.Platform.OS === "ios") {
|
|
219
|
+
const manager = reactNative.NativeModules?.SettingsManager;
|
|
220
|
+
const settings = manager?.getConstants?.()?.settings ?? manager?.settings;
|
|
221
|
+
const languages = Array.isArray(settings?.AppleLanguages) ? settings.AppleLanguages : [];
|
|
222
|
+
for (const language of languages) {
|
|
223
|
+
const locale = chunkUZ2D4BVX_js.normalizeAppilotsLocale(language);
|
|
224
|
+
if (locale) return locale;
|
|
225
|
+
}
|
|
226
|
+
raw = settings?.AppleLocale;
|
|
227
|
+
} else if (reactNative.Platform.OS === "android") {
|
|
228
|
+
const manager = reactNative.NativeModules?.I18nManager;
|
|
229
|
+
raw = manager?.getConstants?.()?.localeIdentifier ?? manager?.localeIdentifier;
|
|
230
|
+
}
|
|
231
|
+
if (!raw || typeof raw !== "string") return null;
|
|
232
|
+
return chunkUZ2D4BVX_js.normalizeAppilotsLocale(raw) ?? null;
|
|
233
|
+
} catch {
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
function resolveLocale(prop) {
|
|
238
|
+
if (prop && BUNDLES[prop]) return prop;
|
|
239
|
+
const detected = detectDeviceLocale();
|
|
240
|
+
if (detected && BUNDLES[detected]) return detected;
|
|
241
|
+
return DEFAULT_LOCALE;
|
|
242
|
+
}
|
|
243
|
+
var I18nContext = React.createContext(null);
|
|
244
|
+
function AppilotsI18nProvider({ locale, overrides, children }) {
|
|
245
|
+
const value = React.useMemo(() => {
|
|
246
|
+
const resolved = resolveLocale(locale ?? null);
|
|
247
|
+
const merged = overrides ? { ...BUNDLES[resolved], ...overrides } : BUNDLES[resolved];
|
|
248
|
+
return {
|
|
249
|
+
locale: resolved,
|
|
250
|
+
strings: merged,
|
|
251
|
+
t: (key) => merged[key]
|
|
252
|
+
};
|
|
253
|
+
}, [locale, overrides]);
|
|
254
|
+
return /* @__PURE__ */ React__default.default.createElement(I18nContext.Provider, { value }, children);
|
|
255
|
+
}
|
|
256
|
+
function useAppilotsI18n() {
|
|
257
|
+
const ctx = React.useContext(I18nContext);
|
|
258
|
+
if (ctx) return ctx;
|
|
259
|
+
return {
|
|
260
|
+
locale: DEFAULT_LOCALE,
|
|
261
|
+
strings: BUNDLES[DEFAULT_LOCALE],
|
|
262
|
+
t: (key) => BUNDLES[DEFAULT_LOCALE][key]
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
11
266
|
// src/introspection/captureSnapshot.ts
|
|
12
267
|
function normalizeSliderKey(value) {
|
|
13
268
|
return (value ?? "").toLowerCase().replace(/^slider[-_]/, "");
|
|
@@ -23,9 +278,9 @@ function fiberSliderMatches(fiber, registryId, registryLabel) {
|
|
|
23
278
|
function reconcileSliders(snapshot) {
|
|
24
279
|
const fiberSliders = snapshot.sliders;
|
|
25
280
|
const out = [];
|
|
26
|
-
for (const { id, kind } of
|
|
281
|
+
for (const { id, kind } of chunkUZ2D4BVX_js.componentRegistry.snapshot()) {
|
|
27
282
|
if (kind !== "slider") continue;
|
|
28
|
-
const entry =
|
|
283
|
+
const entry = chunkUZ2D4BVX_js.componentRegistry.getSlider(id);
|
|
29
284
|
if (!entry) continue;
|
|
30
285
|
const fiber = fiberSliders.find((s) => fiberSliderMatches(s, id, entry.label));
|
|
31
286
|
const visible = !!fiber || typeof entry.screen === "string" && entry.screen === snapshot.route;
|
|
@@ -53,7 +308,7 @@ function normalizeFieldKey(value) {
|
|
|
53
308
|
}
|
|
54
309
|
function canonicalizeRegisteredFields(snapshot) {
|
|
55
310
|
const claimed = /* @__PURE__ */ new Set();
|
|
56
|
-
for (const { id, kind, label } of
|
|
311
|
+
for (const { id, kind, label } of chunkUZ2D4BVX_js.componentRegistry.snapshot()) {
|
|
57
312
|
if (kind !== "field") continue;
|
|
58
313
|
if (snapshot.inputs.some((input) => input.id === id)) continue;
|
|
59
314
|
const registryLabel = (label ?? "").toLowerCase();
|
|
@@ -72,7 +327,7 @@ function canonicalizeRegisteredFields(snapshot) {
|
|
|
72
327
|
}
|
|
73
328
|
}
|
|
74
329
|
function mergeRegisteredLists(snapshot) {
|
|
75
|
-
const registered =
|
|
330
|
+
const registered = chunkUZ2D4BVX_js.listRegistry.snapshot();
|
|
76
331
|
if (registered.length === 0) return;
|
|
77
332
|
const byId = /* @__PURE__ */ new Map();
|
|
78
333
|
for (const list of snapshot.lists) {
|
|
@@ -80,20 +335,35 @@ function mergeRegisteredLists(snapshot) {
|
|
|
80
335
|
}
|
|
81
336
|
for (const entry of registered) {
|
|
82
337
|
if (entry.kind === "scroll") continue;
|
|
338
|
+
const existing = byId.get(entry.id);
|
|
339
|
+
if (!existing && !(entry.screen && entry.screen === snapshot.route)) continue;
|
|
83
340
|
const metrics = entry.getScrollMetrics?.();
|
|
84
341
|
const scrollFacts = metrics ? {
|
|
85
342
|
scrollOffsetY: Math.max(0, Math.round(metrics.offset)),
|
|
86
343
|
canScrollUp: metrics.offset > 8,
|
|
87
344
|
canScrollDown: metrics.offset + metrics.visibleLength < metrics.contentLength - 8
|
|
88
345
|
} : void 0;
|
|
89
|
-
const existing = byId.get(entry.id);
|
|
90
346
|
if (existing) {
|
|
91
347
|
existing.itemCount = existing.itemCount ?? entry.itemCount;
|
|
348
|
+
existing.totalItemCount = existing.totalItemCount ?? entry.totalItemCount;
|
|
92
349
|
existing.refreshing = existing.refreshing ?? entry.refreshing;
|
|
93
350
|
existing.empty = existing.empty ?? entry.empty;
|
|
94
351
|
existing.label = existing.label ?? entry.label;
|
|
95
352
|
existing.source = existing.source ?? "auto-tracked";
|
|
96
353
|
existing.visibleItemCount = existing.items.length;
|
|
354
|
+
const viewport = entry.measureViewport?.();
|
|
355
|
+
if (viewport && viewport.width > 0 && viewport.height > 0) {
|
|
356
|
+
let measured = 0;
|
|
357
|
+
let inViewport = 0;
|
|
358
|
+
for (const item of existing.items) {
|
|
359
|
+
const rect = chunkUZ2D4BVX_js.rectForNode(item);
|
|
360
|
+
if (!rect) continue;
|
|
361
|
+
measured++;
|
|
362
|
+
item.onScreen = rect.width > 0 && rect.height > 0 && rect.x < viewport.x + viewport.width && rect.x + rect.width > viewport.x && rect.y < viewport.y + viewport.height && rect.y + rect.height > viewport.y;
|
|
363
|
+
if (item.onScreen) inViewport++;
|
|
364
|
+
}
|
|
365
|
+
if (measured === existing.items.length) existing.viewportItemCount = inViewport;
|
|
366
|
+
}
|
|
97
367
|
if (entry.dataPreview && entry.dataPreview.length > 0) {
|
|
98
368
|
existing.dataPreview = entry.dataPreview;
|
|
99
369
|
}
|
|
@@ -110,6 +380,7 @@ function mergeRegisteredLists(snapshot) {
|
|
|
110
380
|
containerType: entry.component,
|
|
111
381
|
source: "registry",
|
|
112
382
|
itemCount: entry.itemCount,
|
|
383
|
+
totalItemCount: entry.totalItemCount,
|
|
113
384
|
visibleItemCount: 0,
|
|
114
385
|
refreshing: entry.refreshing,
|
|
115
386
|
empty: entry.empty,
|
|
@@ -121,7 +392,7 @@ function mergeRegisteredLists(snapshot) {
|
|
|
121
392
|
}
|
|
122
393
|
}
|
|
123
394
|
function mergeRegisteredScrollables(snapshot) {
|
|
124
|
-
const registered =
|
|
395
|
+
const registered = chunkUZ2D4BVX_js.listRegistry.snapshot().filter((e) => e.kind === "scroll");
|
|
125
396
|
if (registered.length === 0) return;
|
|
126
397
|
const listsById = /* @__PURE__ */ new Map();
|
|
127
398
|
for (const list of snapshot.lists) {
|
|
@@ -154,7 +425,7 @@ function mergeRegisteredScrollables(snapshot) {
|
|
|
154
425
|
if (out.length > 0) snapshot.scrollables = out;
|
|
155
426
|
}
|
|
156
427
|
function mergeNativeDialog(snapshot) {
|
|
157
|
-
const dialog =
|
|
428
|
+
const dialog = chunkUZ2D4BVX_js.getOpenNativeDialog();
|
|
158
429
|
if (!dialog) return;
|
|
159
430
|
snapshot.nativeDialog = {
|
|
160
431
|
id: dialog.id,
|
|
@@ -169,21 +440,58 @@ function mergeNativeDialog(snapshot) {
|
|
|
169
440
|
}
|
|
170
441
|
var MIN_FIBERS_FOR_BLINDNESS = 200;
|
|
171
442
|
function recordBlindWalk() {
|
|
172
|
-
const walk =
|
|
443
|
+
const walk = chunkUZ2D4BVX_js.getLastWalkDiagnostics();
|
|
173
444
|
if (!walk) return;
|
|
174
445
|
if (walk.visitedFibers < MIN_FIBERS_FOR_BLINDNESS) return;
|
|
175
|
-
if (
|
|
176
|
-
|
|
446
|
+
if (chunkUZ2D4BVX_js.totalDetectorHits(walk.detectors) > 0) return;
|
|
447
|
+
chunkUZ2D4BVX_js.recordIntrospectionFailure("walk-recognized-nothing", null);
|
|
448
|
+
}
|
|
449
|
+
function mergeRegisteredFieldValues(snapshot) {
|
|
450
|
+
const present = new Set(snapshot.inputs.map((i) => normalizeFieldKey(i.id)));
|
|
451
|
+
const onScreenIds = [
|
|
452
|
+
...snapshot.buttons.map((b) => (b.id ?? "").toLowerCase()),
|
|
453
|
+
...snapshot.toggles.map((t) => (t.id ?? "").toLowerCase())
|
|
454
|
+
].filter(Boolean);
|
|
455
|
+
const onScreenLabels = new Set(
|
|
456
|
+
[...snapshot.buttons.map((b) => b.label), ...snapshot.texts].filter((l) => !!l).map((l) => l.toLowerCase())
|
|
457
|
+
);
|
|
458
|
+
for (const { id, kind, screen, label } of chunkUZ2D4BVX_js.componentRegistry.snapshot()) {
|
|
459
|
+
if (kind !== "field") continue;
|
|
460
|
+
const key = normalizeFieldKey(id);
|
|
461
|
+
if (!key || present.has(key)) continue;
|
|
462
|
+
const entry = chunkUZ2D4BVX_js.componentRegistry.getField(id);
|
|
463
|
+
if (!entry) continue;
|
|
464
|
+
const fieldType = entry.fieldType ?? "";
|
|
465
|
+
if (fieldType === "text" || fieldType === "") continue;
|
|
466
|
+
const declaresRoute = typeof screen === "string" && screen === snapshot.route;
|
|
467
|
+
if (screen && !declaresRoute && !chunkUZ2D4BVX_js.getActiveRouteNames().includes(screen)) continue;
|
|
468
|
+
const idEvidence = onScreenIds.some((candidate) => candidate.split(/[^a-z0-9]+/).includes(key));
|
|
469
|
+
const labelEvidence = !!entry.label && onScreenLabels.has(entry.label.toLowerCase());
|
|
470
|
+
if (!declaresRoute && !idEvidence && !labelEvidence) continue;
|
|
471
|
+
let value;
|
|
472
|
+
try {
|
|
473
|
+
value = String(entry.getValue() ?? "");
|
|
474
|
+
} catch {
|
|
475
|
+
continue;
|
|
476
|
+
}
|
|
477
|
+
snapshot.inputs.push({
|
|
478
|
+
id,
|
|
479
|
+
label: entry.label ?? label,
|
|
480
|
+
value,
|
|
481
|
+
type: fieldType
|
|
482
|
+
});
|
|
483
|
+
present.add(key);
|
|
484
|
+
}
|
|
177
485
|
}
|
|
178
486
|
function captureSnapshot() {
|
|
179
|
-
const root =
|
|
487
|
+
const root = chunkUZ2D4BVX_js.getFiberRoot();
|
|
180
488
|
if (!root) {
|
|
181
|
-
|
|
489
|
+
chunkUZ2D4BVX_js.appilotsDebugWarn(
|
|
182
490
|
"captureSnapshot: fiber root not captured yet. Ensure <AppilotsProvider> has rendered before calling this."
|
|
183
491
|
);
|
|
184
|
-
|
|
492
|
+
chunkUZ2D4BVX_js.recordIntrospectionFailure("never-mounted", null);
|
|
185
493
|
return {
|
|
186
|
-
route:
|
|
494
|
+
route: chunkUZ2D4BVX_js.getCurrentScreen(),
|
|
187
495
|
texts: [],
|
|
188
496
|
inputs: [],
|
|
189
497
|
buttons: [],
|
|
@@ -197,9 +505,9 @@ function captureSnapshot() {
|
|
|
197
505
|
};
|
|
198
506
|
}
|
|
199
507
|
const start = Date.now();
|
|
200
|
-
const snapshot =
|
|
508
|
+
const snapshot = chunkUZ2D4BVX_js.walkFiber(root);
|
|
201
509
|
recordBlindWalk();
|
|
202
|
-
const activePath =
|
|
510
|
+
const activePath = chunkUZ2D4BVX_js.getActiveRouteNames();
|
|
203
511
|
const deepestRoute = activePath[activePath.length - 1];
|
|
204
512
|
if (deepestRoute) snapshot.route = deepestRoute;
|
|
205
513
|
mergeRegisteredLists(snapshot);
|
|
@@ -207,15 +515,16 @@ function captureSnapshot() {
|
|
|
207
515
|
mergeNativeDialog(snapshot);
|
|
208
516
|
reconcileSliders(snapshot);
|
|
209
517
|
canonicalizeRegisteredFields(snapshot);
|
|
210
|
-
|
|
211
|
-
|
|
518
|
+
mergeRegisteredFieldValues(snapshot);
|
|
519
|
+
chunkUZ2D4BVX_js.clampSnapshotToWireLimits(snapshot);
|
|
520
|
+
const entries = chunkUZ2D4BVX_js.deriveInteractionElements(snapshot, { rectOf: chunkUZ2D4BVX_js.rectForNode });
|
|
212
521
|
const rectById = new Map(
|
|
213
522
|
entries.flatMap((entry) => entry.rect ? [[entry.id, entry.rect]] : [])
|
|
214
523
|
);
|
|
215
|
-
snapshot.elements = entries.map(
|
|
216
|
-
snapshot.choiceGroups =
|
|
217
|
-
|
|
218
|
-
|
|
524
|
+
snapshot.elements = entries.map(chunkUZ2D4BVX_js.toWireElement);
|
|
525
|
+
snapshot.choiceGroups = chunkUZ2D4BVX_js.attachElementIdsToChoiceGroups(snapshot.choiceGroups, snapshot.elements);
|
|
526
|
+
chunkUZ2D4BVX_js.clampSnapshotToWireLimits(snapshot);
|
|
527
|
+
chunkUZ2D4BVX_js.elementRegistry.replaceAll(
|
|
219
528
|
snapshot.elements.map((element) => {
|
|
220
529
|
const rect = rectById.get(element.id);
|
|
221
530
|
return rect ? { ...element, rect } : element;
|
|
@@ -227,10 +536,10 @@ function captureSnapshot() {
|
|
|
227
536
|
(acc, l) => acc + (typeof l.itemCount === "number" ? l.itemCount : 0),
|
|
228
537
|
0
|
|
229
538
|
);
|
|
230
|
-
|
|
539
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
231
540
|
`captureSnapshot: route="${snapshot.route}" texts=${snapshot.texts.length} inputs=${snapshot.inputs.length} buttons=${snapshot.buttons.length} toggles=${snapshot.toggles.length} sliders=${snapshot.sliders.length} loading=${snapshot.loading} modal=${snapshot.modalOpen} lists=${snapshot.lists.length}(visibleItems=${totalListItems}, dataItems=${totalListDataItems}) choices=${snapshot.choiceGroups.length} elements=${snapshot.elements.length} ` + (snapshot.truncated ? "truncated=true " : "") + `(walked ${snapshot.stats?.visitedFibers ?? 0} fibers, skipped ${snapshot.stats?.skippedHidden ?? 0} hidden, ${elapsed}ms)`
|
|
232
541
|
);
|
|
233
|
-
|
|
542
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
234
543
|
`captureSnapshot detail: lists=[${snapshot.lists.map((l) => `${l.containerType}:${l.id ?? l.label ?? "?"}(rows=${l.items.length})`).join(", ")}] inputs=[${snapshot.inputs.map((i) => i.id ?? i.label ?? "?").slice(0, 12).join(", ")}] buttons=[${snapshot.buttons.map((b) => b.id ?? b.label ?? "?").slice(0, 15).join(", ")}]`
|
|
235
544
|
);
|
|
236
545
|
return snapshot;
|
|
@@ -241,10 +550,10 @@ function registryCounts() {
|
|
|
241
550
|
toggles: 0,
|
|
242
551
|
sliders: 0,
|
|
243
552
|
targets: 0,
|
|
244
|
-
lists:
|
|
245
|
-
elements:
|
|
553
|
+
lists: chunkUZ2D4BVX_js.listRegistry.snapshot().length,
|
|
554
|
+
elements: chunkUZ2D4BVX_js.elementRegistry.size
|
|
246
555
|
};
|
|
247
|
-
for (const { kind } of
|
|
556
|
+
for (const { kind } of chunkUZ2D4BVX_js.componentRegistry.snapshot()) {
|
|
248
557
|
if (kind === "field") counts.fields++;
|
|
249
558
|
else if (kind === "toggle") counts.toggles++;
|
|
250
559
|
else if (kind === "slider") counts.sliders++;
|
|
@@ -253,26 +562,26 @@ function registryCounts() {
|
|
|
253
562
|
return counts;
|
|
254
563
|
}
|
|
255
564
|
function appilotsSelfCheck() {
|
|
256
|
-
const root =
|
|
565
|
+
const root = chunkUZ2D4BVX_js.getFiberRoot();
|
|
257
566
|
const start = Date.now();
|
|
258
|
-
if (root)
|
|
567
|
+
if (root) chunkUZ2D4BVX_js.walkFiber(root);
|
|
259
568
|
const elapsedMs = Date.now() - start;
|
|
260
|
-
const walk =
|
|
569
|
+
const walk = chunkUZ2D4BVX_js.getLastWalkDiagnostics();
|
|
261
570
|
return {
|
|
262
|
-
sdkVersion:
|
|
571
|
+
sdkVersion: chunkUZ2D4BVX_js.SDK_VERSION,
|
|
263
572
|
reactVersion: React__default.default.version ?? null,
|
|
264
|
-
route:
|
|
265
|
-
introspection:
|
|
266
|
-
autoTracking:
|
|
573
|
+
route: chunkUZ2D4BVX_js.getCurrentScreen() || null,
|
|
574
|
+
introspection: chunkUZ2D4BVX_js.getIntrospectionDiagnostics(),
|
|
575
|
+
autoTracking: chunkUZ2D4BVX_js.getAutoTrackingState(),
|
|
267
576
|
walk: {
|
|
268
577
|
visitedFibers: root ? walk?.visitedFibers ?? 0 : 0,
|
|
269
578
|
skippedHidden: root ? walk?.skippedHidden ?? 0 : 0,
|
|
270
579
|
elapsedMs
|
|
271
580
|
},
|
|
272
|
-
detectors: root ? walk?.detectors ??
|
|
581
|
+
detectors: root ? walk?.detectors ?? chunkUZ2D4BVX_js.emptyDetectorCounts() : chunkUZ2D4BVX_js.emptyDetectorCounts(),
|
|
273
582
|
registry: registryCounts(),
|
|
274
|
-
nameMangling:
|
|
275
|
-
geometry: { availability:
|
|
583
|
+
nameMangling: chunkUZ2D4BVX_js.getNameManglingProbe(),
|
|
584
|
+
geometry: { availability: chunkUZ2D4BVX_js.geometryAvailability(), ...chunkUZ2D4BVX_js.geometryStats() }
|
|
276
585
|
};
|
|
277
586
|
}
|
|
278
587
|
|
|
@@ -285,7 +594,7 @@ function declaredState(props) {
|
|
|
285
594
|
return typeof checked === "boolean" ? checked : void 0;
|
|
286
595
|
}
|
|
287
596
|
function isReactNativeSwitch(fiber) {
|
|
288
|
-
return
|
|
597
|
+
return chunkUZ2D4BVX_js.getTypeName(fiber?.type) === "Switch" || chunkUZ2D4BVX_js.getTypeName(fiber?.elementType) === "Switch";
|
|
289
598
|
}
|
|
290
599
|
var SWITCH_FLIP_HANDLERS = ["onValueChange", "onChange", "onPress"];
|
|
291
600
|
function flipSwitchFiber(fiber, next) {
|
|
@@ -309,6 +618,11 @@ function flipSwitchFiber(fiber, next) {
|
|
|
309
618
|
return { ok: true, via: handler.via };
|
|
310
619
|
}
|
|
311
620
|
|
|
621
|
+
// src/introspection/positionalIdentity.ts
|
|
622
|
+
function isPositionalControlId(value) {
|
|
623
|
+
return /^(?:list-\d+-item-\d+-)?(?:btn|input|slider|toggle)-\d+$/i.test(value.trim());
|
|
624
|
+
}
|
|
625
|
+
|
|
312
626
|
// src/introspection/findInteractive.ts
|
|
313
627
|
function getTypeName2(type) {
|
|
314
628
|
if (!type) return null;
|
|
@@ -383,7 +697,7 @@ function shouldSkipSubtree2(fiber) {
|
|
|
383
697
|
const typeName = getTypeName2(fiber.type) ?? getTypeName2(fiber.elementType);
|
|
384
698
|
if (typeName && SELF_REFERENTIAL_COMPONENTS.has(typeName)) return true;
|
|
385
699
|
if (isAppilotsSkipMarked(props)) return true;
|
|
386
|
-
if (
|
|
700
|
+
if (chunkUZ2D4BVX_js.isModalFiber(fiber) && props.visible === false) return true;
|
|
387
701
|
if (matchesName(fiber, "Screen") && props.activityState === 0) return true;
|
|
388
702
|
const style = props.style;
|
|
389
703
|
if (style) {
|
|
@@ -393,9 +707,14 @@ function shouldSkipSubtree2(fiber) {
|
|
|
393
707
|
}
|
|
394
708
|
return false;
|
|
395
709
|
}
|
|
396
|
-
var normalize =
|
|
710
|
+
var normalize = chunkUZ2D4BVX_js.foldForCompare;
|
|
397
711
|
function scoreMatchDetail(fiber, queryNorm, queryRaw) {
|
|
398
712
|
const props = fiber.memoizedProps ?? {};
|
|
713
|
+
if (chunkUZ2D4BVX_js.isSourceControlId(queryRaw)) {
|
|
714
|
+
const matches = chunkUZ2D4BVX_js.sourceControlId(fiber) === queryRaw;
|
|
715
|
+
const disabled = props.disabled === true || props.accessibilityState?.disabled === true;
|
|
716
|
+
return { score: matches ? disabled ? 60 : 120 : 0, named: matches, disabled };
|
|
717
|
+
}
|
|
399
718
|
const candidates = [];
|
|
400
719
|
if (typeof props.testID === "string") candidates.push({ val: props.testID, weight: 100 });
|
|
401
720
|
if (typeof props.accessibilityLabel === "string")
|
|
@@ -414,11 +733,11 @@ function scoreMatchDetail(fiber, queryNorm, queryRaw) {
|
|
|
414
733
|
if (!vNorm) continue;
|
|
415
734
|
if (val === queryRaw) best = Math.max(best, weight + 20);
|
|
416
735
|
else if (vNorm === queryNorm) best = Math.max(best, weight + 10);
|
|
417
|
-
else if (queryNorm && (vNorm.includes(queryNorm) || queryNorm.includes(vNorm)))
|
|
736
|
+
else if (!isPositionalControlId(queryRaw) && queryNorm && (vNorm.includes(queryNorm) || queryNorm.includes(vNorm)))
|
|
418
737
|
best = Math.max(best, weight - 20);
|
|
419
738
|
}
|
|
420
739
|
const named = best >= IDENTITY_MATCH_SCORE;
|
|
421
|
-
const disabledProp = props.disabled === true;
|
|
740
|
+
const disabledProp = props.disabled === true || props.editable === false || props.readOnly === true;
|
|
422
741
|
const disabledA11y = typeof props.accessibilityState === "object" && props.accessibilityState !== null && props.accessibilityState.disabled === true;
|
|
423
742
|
if (best > 0 && disabledProp) {
|
|
424
743
|
best = Math.max(1, best - 60);
|
|
@@ -428,12 +747,18 @@ function scoreMatchDetail(fiber, queryNorm, queryRaw) {
|
|
|
428
747
|
}
|
|
429
748
|
return { score: best, named, disabled: disabledProp || disabledA11y };
|
|
430
749
|
}
|
|
750
|
+
var inputIdentities = /* @__PURE__ */ new WeakMap();
|
|
431
751
|
function wrapTextInput(fiber) {
|
|
752
|
+
const identity = inputIdentities.get(fiber) ?? (fiber.alternate && inputIdentities.get(fiber.alternate)) ?? {};
|
|
753
|
+
inputIdentities.set(fiber, identity);
|
|
754
|
+
if (fiber.alternate) inputIdentities.set(fiber.alternate, identity);
|
|
432
755
|
const getProps = () => fiber.memoizedProps ?? {};
|
|
433
756
|
return {
|
|
434
757
|
kind: "field",
|
|
758
|
+
controlIdentity: identity,
|
|
435
759
|
label: getProps().accessibilityLabel ?? getProps().label ?? getProps().placeholder ?? getProps().testID,
|
|
436
760
|
getValue: () => getProps().value,
|
|
761
|
+
finishEditing: () => chunkUZ2D4BVX_js.endTextInputEditing(getProps()),
|
|
437
762
|
setValue: (value) => {
|
|
438
763
|
const { onChangeText, onChange } = getProps();
|
|
439
764
|
if (typeof onChangeText === "function") {
|
|
@@ -468,7 +793,7 @@ function wrapSwitch(fiber) {
|
|
|
468
793
|
// `accessibilityRole="switch"`) has only the former, and reporting
|
|
469
794
|
// `false` for a control that is on is worse than reporting nothing:
|
|
470
795
|
// the caller inverts this to decide where to move.
|
|
471
|
-
getValue: () =>
|
|
796
|
+
getValue: () => chunkUZ2D4BVX_js.switchValue(getProps()),
|
|
472
797
|
setValue: (value) => {
|
|
473
798
|
const boolVal = typeof value === "boolean" ? value : value === "true" || value === true;
|
|
474
799
|
const flipped = flipSwitchFiber(fiber, boolVal);
|
|
@@ -514,18 +839,18 @@ function describeCandidate(fiber, kind) {
|
|
|
514
839
|
const props = fiber?.memoizedProps ?? {};
|
|
515
840
|
return props.testID ?? props.accessibilityLabel ?? props.placeholder ?? (kind === "target" ? findChildText(fiber) : void 0);
|
|
516
841
|
}
|
|
517
|
-
function isDescendantOf(fiber, ancestor) {
|
|
842
|
+
function isDescendantOf(fiber, ancestor, parents) {
|
|
518
843
|
if (!fiber || !ancestor) return false;
|
|
519
|
-
let node = fiber
|
|
520
|
-
for (let depth = 0; node && depth < 200; depth++, node = node
|
|
844
|
+
let node = parents.get(fiber);
|
|
845
|
+
for (let depth = 0; node && depth < 200; depth++, node = parents.get(node)) {
|
|
521
846
|
if (node === ancestor) return true;
|
|
522
847
|
}
|
|
523
848
|
return false;
|
|
524
849
|
}
|
|
525
850
|
function findInteractiveByIdentifier(query, options = {}) {
|
|
526
|
-
const root =
|
|
851
|
+
const root = chunkUZ2D4BVX_js.getFiberRoot();
|
|
527
852
|
if (!root) {
|
|
528
|
-
|
|
853
|
+
chunkUZ2D4BVX_js.appilotsDebugWarn("findInteractiveByIdentifier: fiber root not captured yet");
|
|
529
854
|
return null;
|
|
530
855
|
}
|
|
531
856
|
const queryNorm = normalize(query);
|
|
@@ -538,18 +863,20 @@ function findInteractiveByIdentifier(query, options = {}) {
|
|
|
538
863
|
let bestDisabled = false;
|
|
539
864
|
let tied = [];
|
|
540
865
|
const visited = /* @__PURE__ */ new WeakSet();
|
|
866
|
+
const parents = /* @__PURE__ */ new WeakMap();
|
|
541
867
|
const stack = [];
|
|
542
|
-
if (root.child) stack.push(root.child);
|
|
868
|
+
if (root.child) stack.push({ fiber: root.child, parent: root });
|
|
543
869
|
while (stack.length > 0) {
|
|
544
|
-
const fiber = stack.pop();
|
|
870
|
+
const { fiber, parent } = stack.pop();
|
|
545
871
|
if (!fiber || visited.has(fiber)) continue;
|
|
546
872
|
visited.add(fiber);
|
|
547
|
-
|
|
873
|
+
parents.set(fiber, parent);
|
|
874
|
+
if (fiber.sibling) stack.push({ fiber: fiber.sibling, parent });
|
|
548
875
|
if (shouldSkipSubtree2(fiber)) continue;
|
|
549
876
|
const props = fiber.memoizedProps ?? {};
|
|
550
877
|
let kind = null;
|
|
551
878
|
if (matchesName(fiber, "TextInput")) kind = "field";
|
|
552
|
-
else if (
|
|
879
|
+
else if (chunkUZ2D4BVX_js.isSwitchLike(fiber, props)) kind = "toggle";
|
|
553
880
|
else if (isPressableTarget(fiber)) kind = "target";
|
|
554
881
|
if (kind && (!options.kind || options.kind === kind)) {
|
|
555
882
|
const detail = scoreMatchDetail(fiber, queryNorm, queryRaw);
|
|
@@ -558,7 +885,7 @@ function findInteractiveByIdentifier(query, options = {}) {
|
|
|
558
885
|
if (score > bestScore) tied = [{ fiber, kind }];
|
|
559
886
|
else if (score === bestScore) tied.push({ fiber, kind });
|
|
560
887
|
}
|
|
561
|
-
const beatsBest = score > bestScore || score > 0 && score === bestScore && isDescendantOf(fiber, bestFiber);
|
|
888
|
+
const beatsBest = score > bestScore || score > 0 && score === bestScore && isDescendantOf(fiber, bestFiber, parents);
|
|
562
889
|
if (beatsBest) {
|
|
563
890
|
bestScore = score;
|
|
564
891
|
bestFiber = fiber;
|
|
@@ -567,14 +894,18 @@ function findInteractiveByIdentifier(query, options = {}) {
|
|
|
567
894
|
bestId = describeCandidate(fiber, kind);
|
|
568
895
|
if (kind === "field") bestHandle = wrapTextInput(fiber);
|
|
569
896
|
else if (kind === "toggle") bestHandle = wrapSwitch(fiber);
|
|
570
|
-
else
|
|
897
|
+
else if (chunkUZ2D4BVX_js.isSourceControlId(queryRaw)) {
|
|
898
|
+
const bound = chunkUZ2D4BVX_js.sourceControlTarget(fiber);
|
|
899
|
+
if (!bound || bound.disabled) bestHandle = null;
|
|
900
|
+
else bestHandle = wrapTouchable(bound.fiber, findChildText(fiber));
|
|
901
|
+
} else bestHandle = wrapTouchable(fiber, findChildText(fiber));
|
|
571
902
|
}
|
|
572
903
|
}
|
|
573
904
|
if (kind === "toggle") continue;
|
|
574
|
-
if (fiber.child) stack.push(fiber.child);
|
|
905
|
+
if (fiber.child) stack.push({ fiber: fiber.child, parent: fiber });
|
|
575
906
|
}
|
|
576
907
|
if (bestHandle && bestScore < (options.minScore ?? 0)) {
|
|
577
|
-
|
|
908
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
578
909
|
`findInteractiveByIdentifier: query="${query}" \u2192 best match scored ${bestScore}, below the requested floor of ${options.minScore} \u2014 refusing it`
|
|
579
910
|
);
|
|
580
911
|
return null;
|
|
@@ -582,23 +913,138 @@ function findInteractiveByIdentifier(query, options = {}) {
|
|
|
582
913
|
if (bestHandle) {
|
|
583
914
|
const independent = tied.filter(
|
|
584
915
|
(candidate) => !tied.some(
|
|
585
|
-
(other) => other.fiber !== candidate.fiber && isDescendantOf(other.fiber, candidate.fiber)
|
|
916
|
+
(other) => other.fiber !== candidate.fiber && isDescendantOf(other.fiber, candidate.fiber, parents)
|
|
586
917
|
)
|
|
587
918
|
);
|
|
588
919
|
bestHandle.matchCount = independent.length;
|
|
589
920
|
bestHandle.named = bestNamed;
|
|
590
921
|
bestHandle.disabled = bestDisabled;
|
|
922
|
+
const measured = bestFiber;
|
|
923
|
+
bestHandle.measure = () => chunkUZ2D4BVX_js.rectOfFiber(measured);
|
|
591
924
|
const candidates = independent.map(({ fiber, kind }) => describeCandidate(fiber, kind)).filter((id) => typeof id === "string" && id.length > 0).slice(0, 8);
|
|
592
925
|
if (candidates.length > 0) bestHandle.matchCandidates = candidates;
|
|
593
|
-
|
|
926
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
594
927
|
`findInteractiveByIdentifier: query="${query}" \u2192 kind=${bestHandle.kind} label="${bestHandle.label ?? bestId}" score=${bestScore} named=${bestNamed} disabled=${bestDisabled} tied=${independent.length}`
|
|
595
928
|
);
|
|
596
929
|
} else {
|
|
597
|
-
|
|
930
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(`findInteractiveByIdentifier: query="${query}" \u2192 no match`);
|
|
598
931
|
}
|
|
599
932
|
return bestHandle;
|
|
600
933
|
}
|
|
601
934
|
|
|
935
|
+
// src/introspection/spotlightTarget.ts
|
|
936
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
937
|
+
var current = null;
|
|
938
|
+
var seq = 0;
|
|
939
|
+
var expiry = null;
|
|
940
|
+
var SPOTLIGHT_TTL_MS = 1200;
|
|
941
|
+
var mode = "off";
|
|
942
|
+
function setSpotlightMode(next) {
|
|
943
|
+
mode = next;
|
|
944
|
+
}
|
|
945
|
+
function getSpotlightMode() {
|
|
946
|
+
return mode;
|
|
947
|
+
}
|
|
948
|
+
function emit() {
|
|
949
|
+
for (const listener of listeners) listener(current);
|
|
950
|
+
}
|
|
951
|
+
function setSpotlightTarget(rect, label) {
|
|
952
|
+
if (expiry) {
|
|
953
|
+
clearTimeout(expiry);
|
|
954
|
+
expiry = null;
|
|
955
|
+
}
|
|
956
|
+
if (!rect) {
|
|
957
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
958
|
+
`setSpotlightTarget: cleared${label ? ` (was about to mark "${label}")` : ""}`
|
|
959
|
+
);
|
|
960
|
+
if (current === null) return;
|
|
961
|
+
current = null;
|
|
962
|
+
emit();
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
current = { rect, label, seq: ++seq };
|
|
966
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
967
|
+
`setSpotlightTarget: seq=${current.seq} label="${label ?? ""}" rect=${Math.round(rect.x)},${Math.round(rect.y)} ${Math.round(rect.width)}x${Math.round(rect.height)}`
|
|
968
|
+
);
|
|
969
|
+
emit();
|
|
970
|
+
expiry = setTimeout(() => {
|
|
971
|
+
expiry = null;
|
|
972
|
+
current = null;
|
|
973
|
+
emit();
|
|
974
|
+
}, SPOTLIGHT_TTL_MS);
|
|
975
|
+
}
|
|
976
|
+
function getSpotlightTarget() {
|
|
977
|
+
return current;
|
|
978
|
+
}
|
|
979
|
+
function subscribeSpotlight(listener) {
|
|
980
|
+
listeners.add(listener);
|
|
981
|
+
return () => {
|
|
982
|
+
listeners.delete(listener);
|
|
983
|
+
};
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
// src/introspection/scrollIntoView.ts
|
|
987
|
+
var REVEAL_MARGIN = 24;
|
|
988
|
+
function offsetToReveal({ rect, viewport, metrics }) {
|
|
989
|
+
const maxOffset = Math.max(0, metrics.contentLength - metrics.visibleLength);
|
|
990
|
+
const viewTop = viewport.top + REVEAL_MARGIN;
|
|
991
|
+
const viewBottom = viewport.top + viewport.height - REVEAL_MARGIN;
|
|
992
|
+
const tallerThanViewport = rect.height > viewport.height - REVEAL_MARGIN * 2;
|
|
993
|
+
let delta;
|
|
994
|
+
if (tallerThanViewport) {
|
|
995
|
+
if (rect.y >= viewTop && rect.y <= viewBottom) return null;
|
|
996
|
+
delta = rect.y - viewTop;
|
|
997
|
+
} else if (rect.y < viewTop) {
|
|
998
|
+
delta = rect.y - viewTop;
|
|
999
|
+
} else if (rect.y + rect.height > viewBottom) {
|
|
1000
|
+
delta = rect.y + rect.height - viewBottom;
|
|
1001
|
+
} else {
|
|
1002
|
+
return null;
|
|
1003
|
+
}
|
|
1004
|
+
const target = clamp(metrics.offset + delta, 0, maxOffset);
|
|
1005
|
+
if (Math.abs(target - metrics.offset) < 1) return null;
|
|
1006
|
+
return target;
|
|
1007
|
+
}
|
|
1008
|
+
function clamp(value, min, max) {
|
|
1009
|
+
return Math.min(max, Math.max(min, value));
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
// src/introspection/revealTarget.ts
|
|
1013
|
+
function revealTarget(rect) {
|
|
1014
|
+
const host = chunkUZ2D4BVX_js.getGeometryHost();
|
|
1015
|
+
if (!host) return { rect, scrolled: false };
|
|
1016
|
+
if (chunkUZ2D4BVX_js.isRectOnScreen(rect, host.window)) return { rect, scrolled: false };
|
|
1017
|
+
const scrollable = resolveScrollable();
|
|
1018
|
+
if (!scrollable) return { rect, scrolled: false };
|
|
1019
|
+
const metrics = scrollable.getScrollMetrics?.();
|
|
1020
|
+
if (!metrics) return { rect, scrolled: false };
|
|
1021
|
+
const box = scrollable.measureViewport?.();
|
|
1022
|
+
const viewport = box ? { top: box.y, height: box.height } : { top: 0, height: host.window.height };
|
|
1023
|
+
const target = offsetToReveal({ rect, viewport, metrics });
|
|
1024
|
+
if (target === null) return { rect, scrolled: false };
|
|
1025
|
+
const moved = scrollable.scrollToOffset?.(target) ?? false;
|
|
1026
|
+
if (!moved) {
|
|
1027
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(`revealTarget: "${scrollable.id}" refused scrollToOffset(${target})`);
|
|
1028
|
+
return { rect, scrolled: false };
|
|
1029
|
+
}
|
|
1030
|
+
const delta = target - metrics.offset;
|
|
1031
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
1032
|
+
`revealTarget: scrolled "${scrollable.id}" by ${Math.round(delta)}px (${Math.round(metrics.offset)} \u2192 ${Math.round(target)})`
|
|
1033
|
+
);
|
|
1034
|
+
return { rect: { ...rect, y: rect.y - delta }, scrolled: true };
|
|
1035
|
+
}
|
|
1036
|
+
function resolveScrollable() {
|
|
1037
|
+
const screen = chunkUZ2D4BVX_js.getCurrentScreen();
|
|
1038
|
+
const candidates = chunkUZ2D4BVX_js.listRegistry.snapshot().filter((entry) => entry.scrollToOffset && entry.getScrollMetrics).filter((entry) => !screen || !entry.screen || entry.screen === screen);
|
|
1039
|
+
if (candidates.length === 1) return candidates[0];
|
|
1040
|
+
if (candidates.length > 1) {
|
|
1041
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
1042
|
+
`revealTarget: ${candidates.length} scrollables on "${screen ?? "?"}" \u2014 cannot tell which holds the target, so not scrolling.`
|
|
1043
|
+
);
|
|
1044
|
+
}
|
|
1045
|
+
return null;
|
|
1046
|
+
}
|
|
1047
|
+
|
|
602
1048
|
// src/executor/handlers/navigateHandler.ts
|
|
603
1049
|
var _reportedMissingNavRef = false;
|
|
604
1050
|
function reportMissingNavigationRef() {
|
|
@@ -641,43 +1087,52 @@ function screenExistsAnywhere(state, screenName) {
|
|
|
641
1087
|
return false;
|
|
642
1088
|
}
|
|
643
1089
|
function safeNavigate(nav, screenName, params, path) {
|
|
1090
|
+
const state = nav.getState?.();
|
|
1091
|
+
const rootState = nav.getRootState?.() ?? state;
|
|
644
1092
|
if (path && path.length > 0) {
|
|
1093
|
+
if (Array.isArray(rootState?.routeNames) && !screenExistsAnywhere(rootState, path[0]) && !state?.routeNames?.includes(path[0])) {
|
|
1094
|
+
if (state?.routeNames?.includes(screenName)) {
|
|
1095
|
+
nav.navigate(screenName, params);
|
|
1096
|
+
return;
|
|
1097
|
+
}
|
|
1098
|
+
throw new Error(
|
|
1099
|
+
`Route "${path[0]}" is not registered in any navigator. Cannot resolve the supplied path to "${screenName}".`
|
|
1100
|
+
);
|
|
1101
|
+
}
|
|
645
1102
|
const { root, nestedParams } = buildNestedParams(path, screenName, params);
|
|
646
|
-
|
|
1103
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
647
1104
|
`safeNavigate: using path-based navigation \u2014 root="${root}", nested=${JSON.stringify(nestedParams)}`
|
|
648
1105
|
);
|
|
649
1106
|
nav.navigate(root, nestedParams);
|
|
650
1107
|
return;
|
|
651
1108
|
}
|
|
652
|
-
const state = nav.getState?.();
|
|
653
1109
|
if (state?.routeNames?.includes(screenName)) {
|
|
654
1110
|
nav.navigate(screenName, params);
|
|
655
1111
|
return;
|
|
656
1112
|
}
|
|
657
|
-
const rootState = nav.getRootState?.() ?? state;
|
|
658
1113
|
if (!screenExistsAnywhere(rootState, screenName)) {
|
|
659
1114
|
throw new Error(
|
|
660
1115
|
`Screen "${screenName}" is not registered in any navigator. The screen may have been removed, may live inside a flow that is not currently mounted (e.g. Auth stack after login), or the MCP doc is stale.`
|
|
661
1116
|
);
|
|
662
1117
|
}
|
|
663
|
-
|
|
1118
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
664
1119
|
`safeNavigate: screen exists in nested navigator, attempting direct navigation to "${screenName}"`
|
|
665
1120
|
);
|
|
666
1121
|
nav.navigate(screenName, params);
|
|
667
1122
|
}
|
|
668
1123
|
function navigateHandler(payload, context) {
|
|
669
|
-
|
|
1124
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
670
1125
|
// Params carry record ids and, on some screens, the user's own
|
|
671
1126
|
// data — the count answers "were params passed?" and nothing else.
|
|
672
|
-
`navigateHandler called: screenName="${payload.screenName}" action="${payload.navigationAction}" params=${
|
|
1127
|
+
`navigateHandler called: screenName="${payload.screenName}" action="${payload.navigationAction}" params=${chunkUZ2D4BVX_js.describeValue(payload.params)}`
|
|
673
1128
|
);
|
|
674
1129
|
const { navigationRef, permissions } = context;
|
|
675
1130
|
const nav = navigationRef.current;
|
|
676
1131
|
if (!permissions.canNavigate) {
|
|
677
1132
|
return {
|
|
678
1133
|
success: false,
|
|
679
|
-
error: "Navigation
|
|
680
|
-
diagnose: { category: "unknown", screen: payload.screenName }
|
|
1134
|
+
error: chunkUZ2D4BVX_js.permissionDeniedMessage("Navigation", "canNavigate"),
|
|
1135
|
+
diagnose: { category: "unknown", screen: payload.screenName, recoverable: false }
|
|
681
1136
|
};
|
|
682
1137
|
}
|
|
683
1138
|
const isGoBack = payload.navigationAction === "goBack";
|
|
@@ -762,12 +1217,12 @@ function navigateHandler(payload, context) {
|
|
|
762
1217
|
diagnose: { category: "unknown", screen: payload.screenName }
|
|
763
1218
|
};
|
|
764
1219
|
}
|
|
765
|
-
|
|
1220
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
766
1221
|
`navigateHandler: navigation succeeded for "${payload.screenName}" (action="${payload.navigationAction}")`
|
|
767
1222
|
);
|
|
768
1223
|
return { success: true };
|
|
769
1224
|
} catch (err) {
|
|
770
|
-
|
|
1225
|
+
chunkUZ2D4BVX_js.appilotsDebugWarn(
|
|
771
1226
|
`navigateHandler: navigation failed for "${payload.screenName}": ${err?.message}`
|
|
772
1227
|
);
|
|
773
1228
|
const msg = String(err?.message ?? "Navigation failed");
|
|
@@ -815,18 +1270,18 @@ function markedItemIndexFromFiber(fiber) {
|
|
|
815
1270
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
816
1271
|
}
|
|
817
1272
|
function normalize2(value) {
|
|
818
|
-
return
|
|
1273
|
+
return chunkUZ2D4BVX_js.foldForCompare(String(value ?? ""));
|
|
819
1274
|
}
|
|
820
1275
|
function hasPressHandler2(fiber) {
|
|
821
1276
|
const props = fiber?.memoizedProps ?? {};
|
|
822
1277
|
return typeof props.onPress === "function" || typeof props.onPressIn === "function";
|
|
823
1278
|
}
|
|
824
1279
|
function isPressableFiber(fiber) {
|
|
825
|
-
const typeName =
|
|
826
|
-
return
|
|
1280
|
+
const typeName = chunkUZ2D4BVX_js.getTypeName(fiber.type) ?? chunkUZ2D4BVX_js.getTypeName(fiber.elementType) ?? "";
|
|
1281
|
+
return chunkUZ2D4BVX_js.TOUCHABLE_NAMES.has(typeName) || hasPressHandler2(fiber);
|
|
827
1282
|
}
|
|
828
1283
|
function findListContainers(options = {}) {
|
|
829
|
-
const root =
|
|
1284
|
+
const root = chunkUZ2D4BVX_js.getFiberRoot();
|
|
830
1285
|
if (!root) return [];
|
|
831
1286
|
const containers = [];
|
|
832
1287
|
const visited = /* @__PURE__ */ new WeakSet();
|
|
@@ -837,17 +1292,17 @@ function findListContainers(options = {}) {
|
|
|
837
1292
|
if (!fiber || visited.has(fiber)) continue;
|
|
838
1293
|
visited.add(fiber);
|
|
839
1294
|
if (fiber.sibling) stack.push(fiber.sibling);
|
|
840
|
-
if (
|
|
841
|
-
if (
|
|
842
|
-
const minItems =
|
|
843
|
-
const items =
|
|
1295
|
+
if (chunkUZ2D4BVX_js.shouldSkipSubtree(fiber)) continue;
|
|
1296
|
+
if (chunkUZ2D4BVX_js.isAlwaysListContainer(fiber) || chunkUZ2D4BVX_js.isHeuristicListContainer(fiber)) {
|
|
1297
|
+
const minItems = chunkUZ2D4BVX_js.isAlwaysListContainer(fiber) || options.allowSingleHeuristic ? 1 : 2;
|
|
1298
|
+
const items = chunkUZ2D4BVX_js.findListItems(fiber, minItems);
|
|
844
1299
|
if (items && items.length >= minItems) {
|
|
845
1300
|
containers.push({
|
|
846
1301
|
container: fiber,
|
|
847
1302
|
items,
|
|
848
1303
|
listId: listIdFromContainer(fiber),
|
|
849
1304
|
listLabel: listLabelFromContainer(fiber),
|
|
850
|
-
containerType:
|
|
1305
|
+
containerType: chunkUZ2D4BVX_js.getTypeName(fiber.type) ?? chunkUZ2D4BVX_js.getTypeName(fiber.elementType) ?? "List"
|
|
851
1306
|
});
|
|
852
1307
|
continue;
|
|
853
1308
|
}
|
|
@@ -866,7 +1321,7 @@ function findFirstTouchable(item) {
|
|
|
866
1321
|
const { fiber, includeSibling } = stack.pop();
|
|
867
1322
|
if (!fiber || visited.has(fiber)) continue;
|
|
868
1323
|
visited.add(fiber);
|
|
869
|
-
if (
|
|
1324
|
+
if (chunkUZ2D4BVX_js.shouldSkipSubtree(fiber)) continue;
|
|
870
1325
|
if (isPressableFiber(fiber)) {
|
|
871
1326
|
const props = fiber.memoizedProps ?? {};
|
|
872
1327
|
if (typeof props.onPress === "function" || typeof props.onPressIn === "function") {
|
|
@@ -893,7 +1348,7 @@ function findTouchableFibers(item) {
|
|
|
893
1348
|
const { fiber, includeSibling } = stack.pop();
|
|
894
1349
|
if (!fiber || visited.has(fiber)) continue;
|
|
895
1350
|
visited.add(fiber);
|
|
896
|
-
if (
|
|
1351
|
+
if (chunkUZ2D4BVX_js.shouldSkipSubtree(fiber)) continue;
|
|
897
1352
|
const props = fiber.memoizedProps ?? {};
|
|
898
1353
|
if (isPressableFiber(fiber) && (typeof props.onPress === "function" || typeof props.onPressIn === "function")) {
|
|
899
1354
|
found.push(fiber);
|
|
@@ -937,7 +1392,7 @@ function findFirstText(fiber) {
|
|
|
937
1392
|
const node = stack.pop();
|
|
938
1393
|
if (!node || visited.has(node)) continue;
|
|
939
1394
|
visited.add(node);
|
|
940
|
-
const typeName =
|
|
1395
|
+
const typeName = chunkUZ2D4BVX_js.getTypeName(node.type) ?? chunkUZ2D4BVX_js.getTypeName(node.elementType) ?? "";
|
|
941
1396
|
if (typeName === "Text") {
|
|
942
1397
|
const text = textFromChildren(node.memoizedProps?.children).trim();
|
|
943
1398
|
if (text) return text;
|
|
@@ -956,7 +1411,7 @@ function collectTexts(fiber) {
|
|
|
956
1411
|
const node = stack.pop();
|
|
957
1412
|
if (!node || visited.has(node)) continue;
|
|
958
1413
|
visited.add(node);
|
|
959
|
-
const typeName =
|
|
1414
|
+
const typeName = chunkUZ2D4BVX_js.getTypeName(node.type) ?? chunkUZ2D4BVX_js.getTypeName(node.elementType) ?? "";
|
|
960
1415
|
if (typeName === "Text") {
|
|
961
1416
|
const text = textFromChildren(node.memoizedProps?.children).trim();
|
|
962
1417
|
if (text) out.push(text);
|
|
@@ -968,10 +1423,10 @@ function collectTexts(fiber) {
|
|
|
968
1423
|
}
|
|
969
1424
|
function hasUsefulTouchableIdentity(fiber) {
|
|
970
1425
|
const props = fiber?.memoizedProps ?? {};
|
|
971
|
-
if (
|
|
972
|
-
if (
|
|
973
|
-
if (
|
|
974
|
-
return
|
|
1426
|
+
if (chunkUZ2D4BVX_js.isReferenceable(props.testID)) return true;
|
|
1427
|
+
if (chunkUZ2D4BVX_js.isReferenceable(props.accessibilityLabel)) return true;
|
|
1428
|
+
if (chunkUZ2D4BVX_js.isReferenceable(props.label)) return true;
|
|
1429
|
+
return chunkUZ2D4BVX_js.isReferenceable(findFirstText(fiber));
|
|
975
1430
|
}
|
|
976
1431
|
function describeTouchable(fiber) {
|
|
977
1432
|
const props = fiber?.memoizedProps ?? {};
|
|
@@ -982,10 +1437,10 @@ function describeTouchable(fiber) {
|
|
|
982
1437
|
}
|
|
983
1438
|
function touchableLooksDestructive(fiber) {
|
|
984
1439
|
const descriptor = describeTouchable(fiber);
|
|
985
|
-
if (descriptor &&
|
|
1440
|
+
if (descriptor && chunkUZ2D4BVX_js.looksDestructiveActionLabel(descriptor)) return true;
|
|
986
1441
|
const props = fiber?.memoizedProps ?? {};
|
|
987
1442
|
const haystack = [props.testID, props.accessibilityLabel, props.accessibilityHint, props.label].filter((value) => typeof value === "string").join(" ");
|
|
988
|
-
return
|
|
1443
|
+
return chunkUZ2D4BVX_js.looksDestructiveActionLabel(haystack);
|
|
989
1444
|
}
|
|
990
1445
|
function describeItemCandidate(listIndex, zeroBasedIndex, item) {
|
|
991
1446
|
const syntheticId = `list-${listIndex}-item-${zeroBasedIndex + 1}`;
|
|
@@ -1034,8 +1489,10 @@ function pressResolvedListItem(list, itemFiber, listIndex, itemIndex) {
|
|
|
1034
1489
|
(candidate) => candidate !== touchable && containsFiber(touchable, candidate)
|
|
1035
1490
|
);
|
|
1036
1491
|
if (primaryWrapsNestedTargets) {
|
|
1037
|
-
|
|
1038
|
-
|
|
1492
|
+
const outer = describeTouchable(touchable) ?? "?";
|
|
1493
|
+
const nested = safeIdentifiableTouchables.filter((candidate) => candidate !== touchable && containsFiber(touchable, candidate)).map((candidate) => describeTouchable(candidate) ?? "?").slice(0, 6);
|
|
1494
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
1495
|
+
`listItemDispatch: item "list-${listIndex}-item-${itemIndex}" has nested pressables; pressing outer row target [outer=${outer}] [nested=${nested.join(", ")}] [outerHasOnPress=${typeof touchable?.memoizedProps?.onPress === "function"}]`
|
|
1039
1496
|
);
|
|
1040
1497
|
} else {
|
|
1041
1498
|
const candidates = safeIdentifiableTouchables.map(describeTouchable).filter((d) => !!d).slice(0, 8);
|
|
@@ -1069,14 +1526,14 @@ function pressResolvedListItem(list, itemFiber, listIndex, itemIndex) {
|
|
|
1069
1526
|
}
|
|
1070
1527
|
return {
|
|
1071
1528
|
ok: true,
|
|
1072
|
-
containerType:
|
|
1529
|
+
containerType: chunkUZ2D4BVX_js.getTypeName(container.type) ?? chunkUZ2D4BVX_js.getTypeName(container.elementType) ?? list.containerType
|
|
1073
1530
|
};
|
|
1074
1531
|
} catch (err) {
|
|
1075
1532
|
return {
|
|
1076
1533
|
ok: false,
|
|
1077
1534
|
reason: "press-threw",
|
|
1078
1535
|
error: err?.message ?? "press handler threw",
|
|
1079
|
-
containerType:
|
|
1536
|
+
containerType: chunkUZ2D4BVX_js.getTypeName(container.type) ?? chunkUZ2D4BVX_js.getTypeName(container.elementType) ?? list.containerType
|
|
1080
1537
|
};
|
|
1081
1538
|
}
|
|
1082
1539
|
}
|
|
@@ -1102,10 +1559,12 @@ function scoreItemCandidate(item, zeroBasedIndex, locator) {
|
|
|
1102
1559
|
if (locator.itemKey) {
|
|
1103
1560
|
if (itemKey === locator.itemKey) score += 1e3;
|
|
1104
1561
|
else if (itemKey && normalize2(itemKey) === normalize2(locator.itemKey)) score += 950;
|
|
1562
|
+
else return 0;
|
|
1105
1563
|
}
|
|
1106
1564
|
if (locator.reactKey) {
|
|
1107
1565
|
if (reactKey === locator.reactKey) score += 900;
|
|
1108
1566
|
else if (reactKey && normalize2(reactKey) === normalize2(locator.reactKey)) score += 850;
|
|
1567
|
+
else if (!locator.itemKey) return 0;
|
|
1109
1568
|
}
|
|
1110
1569
|
if (locator.itemIndex && zeroBasedIndex === locator.itemIndex - 1) score += 750;
|
|
1111
1570
|
if (locator.itemIndex && markedIndex !== void 0 && (markedIndex === locator.itemIndex || markedIndex === locator.itemIndex - 1)) {
|
|
@@ -1132,7 +1591,7 @@ function candidateLists(containers, locator) {
|
|
|
1132
1591
|
return containers.map((list, listIndex) => ({ list, listIndex }));
|
|
1133
1592
|
}
|
|
1134
1593
|
function pressListItemAtOrdinal(listIndex, itemIndex) {
|
|
1135
|
-
if (!
|
|
1594
|
+
if (!chunkUZ2D4BVX_js.getFiberRoot()) return { ok: false, reason: "no-fiber-root" };
|
|
1136
1595
|
const containers = findListContainers({ allowSingleHeuristic: true });
|
|
1137
1596
|
if (listIndex < 0 || listIndex >= containers.length) {
|
|
1138
1597
|
return { ok: false, reason: "list-not-found" };
|
|
@@ -1146,7 +1605,7 @@ function pressListItemAtOrdinal(listIndex, itemIndex) {
|
|
|
1146
1605
|
return pressResolvedListItem(list, items[zeroBased], listIndex, itemIndex);
|
|
1147
1606
|
}
|
|
1148
1607
|
function resolveListItemByIdentity(locator) {
|
|
1149
|
-
if (!
|
|
1608
|
+
if (!chunkUZ2D4BVX_js.getFiberRoot()) return { ok: false, result: { ok: false, reason: "no-fiber-root" } };
|
|
1150
1609
|
const parsed = locator.syntheticId ? parseSyntheticListItemId(locator.syntheticId) : null;
|
|
1151
1610
|
const effective = parsed ? { ...locator, listIndex: parsed.listIndex, itemIndex: parsed.itemIndex } : locator;
|
|
1152
1611
|
const containers = findListContainers({ allowSingleHeuristic: true });
|
|
@@ -1175,7 +1634,7 @@ function resolveListItemByIdentity(locator) {
|
|
|
1175
1634
|
scoredCandidates.sort((a, b) => b.score - a.score);
|
|
1176
1635
|
const best = scoredCandidates[0];
|
|
1177
1636
|
const tiedCandidates = scoredCandidates.filter((c) => c.score === best.score);
|
|
1178
|
-
if (tiedCandidates.length > 1 && best.score < 750) {
|
|
1637
|
+
if (tiedCandidates.length > 1 && (best.score < 750 || Boolean(effective.itemKey || effective.reactKey))) {
|
|
1179
1638
|
const candidates = tiedCandidates.map((c) => describeItemCandidate(c.listIndex, c.itemIndex - 1, c.item)).slice(0, 8);
|
|
1180
1639
|
return {
|
|
1181
1640
|
ok: false,
|
|
@@ -1207,9 +1666,9 @@ function findSwitchFibers(item) {
|
|
|
1207
1666
|
const { fiber, includeSibling } = stack.pop();
|
|
1208
1667
|
if (!fiber || visited.has(fiber)) continue;
|
|
1209
1668
|
visited.add(fiber);
|
|
1210
|
-
if (
|
|
1669
|
+
if (chunkUZ2D4BVX_js.shouldSkipSubtree(fiber)) continue;
|
|
1211
1670
|
const props = fiber.memoizedProps ?? {};
|
|
1212
|
-
if (
|
|
1671
|
+
if (chunkUZ2D4BVX_js.isSwitchLike(fiber, props)) {
|
|
1213
1672
|
if (props.__appilotsInternal !== true) found.push(fiber);
|
|
1214
1673
|
if (includeSibling && fiber.sibling) {
|
|
1215
1674
|
stack.push({ fiber: fiber.sibling, includeSibling: true });
|
|
@@ -1243,11 +1702,11 @@ function toggleListItemByIdentity(locator, options) {
|
|
|
1243
1702
|
}
|
|
1244
1703
|
const target = switches[0];
|
|
1245
1704
|
const props = target?.memoizedProps ?? {};
|
|
1246
|
-
const
|
|
1247
|
-
if (options?.expected !== void 0 &&
|
|
1248
|
-
return { ok: true, containerType: list.containerType, value:
|
|
1705
|
+
const current2 = chunkUZ2D4BVX_js.switchValue(props);
|
|
1706
|
+
if (options?.expected !== void 0 && current2 === options.expected) {
|
|
1707
|
+
return { ok: true, containerType: list.containerType, value: current2, noop: true };
|
|
1249
1708
|
}
|
|
1250
|
-
const flipped = flipSwitchFiber(target, !
|
|
1709
|
+
const flipped = flipSwitchFiber(target, !current2);
|
|
1251
1710
|
if (!flipped.ok) {
|
|
1252
1711
|
if (flipped.reason === "no-handler") {
|
|
1253
1712
|
return {
|
|
@@ -1264,7 +1723,7 @@ function toggleListItemByIdentity(locator, options) {
|
|
|
1264
1723
|
containerType: list.containerType
|
|
1265
1724
|
};
|
|
1266
1725
|
}
|
|
1267
|
-
return { ok: true, containerType: list.containerType, value: !
|
|
1726
|
+
return { ok: true, containerType: list.containerType, value: !current2 };
|
|
1268
1727
|
}
|
|
1269
1728
|
function pressListItemByIdentity(locator) {
|
|
1270
1729
|
const resolved = resolveListItemByIdentity(locator);
|
|
@@ -1282,7 +1741,7 @@ function screenDiagnose(targetId, category = "component-not-found") {
|
|
|
1282
1741
|
return {
|
|
1283
1742
|
category,
|
|
1284
1743
|
targetId,
|
|
1285
|
-
screen:
|
|
1744
|
+
screen: chunkUZ2D4BVX_js.getCurrentScreen() ?? void 0
|
|
1286
1745
|
};
|
|
1287
1746
|
}
|
|
1288
1747
|
function isPressLike(action) {
|
|
@@ -1302,10 +1761,10 @@ function elementLookupKey(value) {
|
|
|
1302
1761
|
return canonicalElementId(value).toLowerCase().replace(/[\s_]+/g, "-");
|
|
1303
1762
|
}
|
|
1304
1763
|
function findRegisteredElement(elementId) {
|
|
1305
|
-
const direct =
|
|
1764
|
+
const direct = chunkUZ2D4BVX_js.elementRegistry.get(elementId) ?? chunkUZ2D4BVX_js.elementRegistry.get(canonicalElementId(elementId));
|
|
1306
1765
|
if (direct) return direct;
|
|
1307
1766
|
const wanted = elementLookupKey(elementId);
|
|
1308
|
-
return
|
|
1767
|
+
return chunkUZ2D4BVX_js.elementRegistry.snapshot().find((element) => elementLookupKey(element.id) === wanted);
|
|
1309
1768
|
}
|
|
1310
1769
|
function resolveInteractionElement(elementId) {
|
|
1311
1770
|
return getLatestElement(elementId);
|
|
@@ -1425,7 +1884,7 @@ function dispatchIdentifiedToggle(targetId, action) {
|
|
|
1425
1884
|
diagnose: { ...screenDiagnose(targetId, "unknown"), recoverable: true }
|
|
1426
1885
|
};
|
|
1427
1886
|
}
|
|
1428
|
-
|
|
1887
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
1429
1888
|
`elementDispatch: "${action}" on "${targetId}" names a switch \u2014 flipping it instead of pressing, so the verb cannot land on an ancestor`
|
|
1430
1889
|
);
|
|
1431
1890
|
try {
|
|
@@ -1459,6 +1918,12 @@ function dispatchFiberTarget(targetId, action) {
|
|
|
1459
1918
|
diagnose: screenDiagnose(targetId)
|
|
1460
1919
|
};
|
|
1461
1920
|
}
|
|
1921
|
+
const measured = handle.measure?.() ?? null;
|
|
1922
|
+
if (measured && getSpotlightMode() === "guided") {
|
|
1923
|
+
setSpotlightTarget(revealTarget(measured).rect, handle.label);
|
|
1924
|
+
} else {
|
|
1925
|
+
setSpotlightTarget(measured, handle.label);
|
|
1926
|
+
}
|
|
1462
1927
|
try {
|
|
1463
1928
|
if (isPressLike(action) && handle.kind === "target" && handle.press) {
|
|
1464
1929
|
handle.press();
|
|
@@ -1509,6 +1974,13 @@ function dispatchLegacyTarget(targetId, registry, action) {
|
|
|
1509
1974
|
};
|
|
1510
1975
|
}
|
|
1511
1976
|
function dispatchElement(element, registry, action) {
|
|
1977
|
+
if (element.dispatchable === false) {
|
|
1978
|
+
return {
|
|
1979
|
+
success: false,
|
|
1980
|
+
error: `Element "${element.id}" is observation-only and has no exact live control binding.`,
|
|
1981
|
+
diagnose: { ...screenDiagnose(element.id, "ambiguous-target"), recoverable: false }
|
|
1982
|
+
};
|
|
1983
|
+
}
|
|
1512
1984
|
if (element.disabled === true) {
|
|
1513
1985
|
return {
|
|
1514
1986
|
success: false,
|
|
@@ -1527,6 +1999,13 @@ function dispatchElement(element, registry, action) {
|
|
|
1527
1999
|
texts: element.texts
|
|
1528
2000
|
});
|
|
1529
2001
|
if (pressed.ok) return { success: true };
|
|
2002
|
+
if (!pressed.refusal && (element.listContext.itemKey || element.listContext.reactKey)) {
|
|
2003
|
+
return {
|
|
2004
|
+
success: false,
|
|
2005
|
+
error: pressed.error ?? `The observed list entity "${element.label ?? element.id}" could not be resolved. Reobserve; do not substitute its old position.`,
|
|
2006
|
+
diagnose: { ...screenDiagnose(element.id, "ambiguous-target"), recoverable: true }
|
|
2007
|
+
};
|
|
2008
|
+
}
|
|
1530
2009
|
if (pressed.refusal) {
|
|
1531
2010
|
return {
|
|
1532
2011
|
success: false,
|
|
@@ -1634,7 +2113,7 @@ function dispatchToggleElement(element, registry) {
|
|
|
1634
2113
|
}
|
|
1635
2114
|
function dispatchStructuredElementId(identifier, action) {
|
|
1636
2115
|
if (!isElementIdentifier(identifier) || !isPressLike(action)) return null;
|
|
1637
|
-
const parsed =
|
|
2116
|
+
const parsed = chunkUZ2D4BVX_js.parseStableElementId(identifier);
|
|
1638
2117
|
if (!parsed || parsed.role !== "option") return null;
|
|
1639
2118
|
if (!parsed.itemKey && !parsed.listId) return null;
|
|
1640
2119
|
const pressed = pressListItemByIdentity({
|
|
@@ -1644,7 +2123,7 @@ function dispatchStructuredElementId(identifier, action) {
|
|
|
1644
2123
|
texts: parsed.itemKey ? [parsed.itemKey] : void 0
|
|
1645
2124
|
});
|
|
1646
2125
|
if (pressed.ok) {
|
|
1647
|
-
|
|
2126
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
1648
2127
|
`elementDispatch: resolved stale el id "${identifier}" via structural identity (listId="${parsed.listId}", itemKey="${parsed.itemKey}")`
|
|
1649
2128
|
);
|
|
1650
2129
|
return { success: true };
|
|
@@ -1675,20 +2154,20 @@ function normalize4(value) {
|
|
|
1675
2154
|
return value.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]/g, "");
|
|
1676
2155
|
}
|
|
1677
2156
|
function resolveScreenForFormFields() {
|
|
1678
|
-
const activePath =
|
|
2157
|
+
const activePath = chunkUZ2D4BVX_js.getActiveRouteNames();
|
|
1679
2158
|
for (let i = activePath.length - 1; i >= 0; i--) {
|
|
1680
2159
|
const name = activePath[i];
|
|
1681
|
-
const meta = name ?
|
|
2160
|
+
const meta = name ? chunkUZ2D4BVX_js.getScreenMetadata(name) : void 0;
|
|
1682
2161
|
if (name && Array.isArray(meta?.fields) && meta.fields.length > 0) return name;
|
|
1683
2162
|
}
|
|
1684
|
-
return
|
|
2163
|
+
return chunkUZ2D4BVX_js.getCurrentScreen();
|
|
1685
2164
|
}
|
|
1686
2165
|
function collectKnownFormFields(registry) {
|
|
1687
2166
|
const registryFields = registry.snapshot().filter((entry) => entry.kind === "field" || entry.kind === "slider").map((entry) => ({ id: entry.id, label: entry.label }));
|
|
1688
2167
|
if (registryFields.length >= 2) return registryFields;
|
|
1689
2168
|
const screen = resolveScreenForFormFields();
|
|
1690
2169
|
if (screen) {
|
|
1691
|
-
const metaFields =
|
|
2170
|
+
const metaFields = chunkUZ2D4BVX_js.getScreenMetadata(screen)?.fields;
|
|
1692
2171
|
if (Array.isArray(metaFields) && metaFields.length > 0) {
|
|
1693
2172
|
return metaFields.filter((field) => !!field && typeof field.id === "string").map((field) => ({
|
|
1694
2173
|
id: field.id,
|
|
@@ -1698,7 +2177,7 @@ function collectKnownFormFields(registry) {
|
|
|
1698
2177
|
}));
|
|
1699
2178
|
}
|
|
1700
2179
|
}
|
|
1701
|
-
for (const meta of
|
|
2180
|
+
for (const meta of chunkUZ2D4BVX_js.getAllScreens()) {
|
|
1702
2181
|
if (Array.isArray(meta.fields) && meta.fields.length > 0) {
|
|
1703
2182
|
return meta.fields.filter((field) => !!field && typeof field.id === "string").map((field) => ({
|
|
1704
2183
|
id: field.id,
|
|
@@ -1811,7 +2290,7 @@ function rewriteMisplacedFormFillFields(fields, registry) {
|
|
|
1811
2290
|
const inferred = inferFieldIdForValue(String(field.value ?? ""), knownFields, used);
|
|
1812
2291
|
if (!inferred) return field;
|
|
1813
2292
|
used.add(inferred);
|
|
1814
|
-
|
|
2293
|
+
chunkUZ2D4BVX_js.appilotsDebugWarn(
|
|
1815
2294
|
`formFieldRewrite: ${field.fieldId} \u2192 ${inferred} (value=${JSON.stringify(field.value)})`
|
|
1816
2295
|
);
|
|
1817
2296
|
return { ...field, fieldId: inferred };
|
|
@@ -1819,8 +2298,8 @@ function rewriteMisplacedFormFillFields(fields, registry) {
|
|
|
1819
2298
|
}
|
|
1820
2299
|
|
|
1821
2300
|
// src/executor/formValidation.ts
|
|
1822
|
-
var FORM_VALIDATION_TEXT_RE2 =
|
|
1823
|
-
var FORM_SUCCESS_TEXT_RE =
|
|
2301
|
+
var FORM_VALIDATION_TEXT_RE2 = chunkUZ2D4BVX_js.FORM_VALIDATION_TEXT_RE;
|
|
2302
|
+
var FORM_SUCCESS_TEXT_RE = chunkUZ2D4BVX_js.FORM_WRITE_SUCCESS_TEXT_RE;
|
|
1824
2303
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
1825
2304
|
function inferValidationFieldId(message, inputs) {
|
|
1826
2305
|
const haystack = normalizeText(message);
|
|
@@ -1844,12 +2323,18 @@ function normalizeText(value) {
|
|
|
1844
2323
|
function containsWord(haystack, needle) {
|
|
1845
2324
|
return ` ${haystack} `.includes(` ${needle} `);
|
|
1846
2325
|
}
|
|
1847
|
-
function readVisibleFormValidation(snap) {
|
|
2326
|
+
function readVisibleFormValidation(snap, beforeTexts) {
|
|
1848
2327
|
if (!snap) return void 0;
|
|
2328
|
+
const invalid = snap.inputs?.find((input) => input.invalid === true);
|
|
2329
|
+
const hasSubmitControl = snap.buttons?.some(
|
|
2330
|
+
(button) => chunkUZ2D4BVX_js.SUBMIT_CONTROL_RE.test(button.label ?? button.id ?? "")
|
|
2331
|
+
);
|
|
1849
2332
|
for (const text of snap.texts ?? []) {
|
|
1850
|
-
if (!text?.trim() || !
|
|
2333
|
+
if (!text?.trim() || !chunkUZ2D4BVX_js.isVisibleValidationText(text, { invalid: !!invalid, hasSubmitControl, beforeTexts }))
|
|
2334
|
+
continue;
|
|
1851
2335
|
return { fieldId: inferValidationFieldId(text, snap.inputs), message: text };
|
|
1852
2336
|
}
|
|
2337
|
+
if (invalid) return { fieldId: invalid.id, message: "The app marks this field as invalid." };
|
|
1853
2338
|
return void 0;
|
|
1854
2339
|
}
|
|
1855
2340
|
function readVisibleFormSuccess(snap) {
|
|
@@ -1857,20 +2342,23 @@ function readVisibleFormSuccess(snap) {
|
|
|
1857
2342
|
return (snap.texts ?? []).find((text) => text?.trim() && FORM_SUCCESS_TEXT_RE.test(text));
|
|
1858
2343
|
}
|
|
1859
2344
|
function submitAsyncStillPending(submitTargetId) {
|
|
1860
|
-
const probe =
|
|
2345
|
+
const probe = chunkUZ2D4BVX_js.probeLoadingState(submitTargetId ?? null, chunkUZ2D4BVX_js.getCurrentScreen());
|
|
1861
2346
|
if (probe.loading) return true;
|
|
1862
2347
|
if (submitTargetId && probe.pressedFound && probe.pressedDisabled) return true;
|
|
1863
2348
|
return false;
|
|
1864
2349
|
}
|
|
1865
|
-
function evaluatePostSubmitSnapshot(snap, activePath) {
|
|
1866
|
-
const validation = readVisibleFormValidation(snap);
|
|
2350
|
+
function evaluatePostSubmitSnapshot(snap, activePath, beforeTexts) {
|
|
2351
|
+
const validation = readVisibleFormValidation(snap, beforeTexts);
|
|
1867
2352
|
if (validation) {
|
|
1868
2353
|
return { status: "failure", fieldId: validation.fieldId, message: validation.message };
|
|
1869
2354
|
}
|
|
1870
2355
|
const successText = readVisibleFormSuccess(snap);
|
|
1871
2356
|
if (successText) return { status: "success", message: successText };
|
|
1872
|
-
if (!
|
|
1873
|
-
return {
|
|
2357
|
+
if (!chunkUZ2D4BVX_js.snapshotShowsOpenCreateForm(snap, activePath)) {
|
|
2358
|
+
return {
|
|
2359
|
+
status: "unverified",
|
|
2360
|
+
message: "The form closed without a visible success receipt. Inspect the resulting record before claiming the goal is complete."
|
|
2361
|
+
};
|
|
1874
2362
|
}
|
|
1875
2363
|
return void 0;
|
|
1876
2364
|
}
|
|
@@ -1885,8 +2373,8 @@ async function waitForPostSubmitOutcome(options) {
|
|
|
1885
2373
|
continue;
|
|
1886
2374
|
}
|
|
1887
2375
|
const snap2 = captureSnapshot();
|
|
1888
|
-
const activePath2 =
|
|
1889
|
-
const outcome2 = evaluatePostSubmitSnapshot(snap2, activePath2);
|
|
2376
|
+
const activePath2 = chunkUZ2D4BVX_js.getActiveRouteNames();
|
|
2377
|
+
const outcome2 = evaluatePostSubmitSnapshot(snap2, activePath2, options?.beforeTexts);
|
|
1890
2378
|
if (outcome2) return outcome2;
|
|
1891
2379
|
await sleep(pollMs);
|
|
1892
2380
|
}
|
|
@@ -1897,8 +2385,8 @@ async function waitForPostSubmitOutcome(options) {
|
|
|
1897
2385
|
};
|
|
1898
2386
|
}
|
|
1899
2387
|
const snap = captureSnapshot();
|
|
1900
|
-
const activePath =
|
|
1901
|
-
const outcome = evaluatePostSubmitSnapshot(snap, activePath);
|
|
2388
|
+
const activePath = chunkUZ2D4BVX_js.getActiveRouteNames();
|
|
2389
|
+
const outcome = evaluatePostSubmitSnapshot(snap, activePath, options?.beforeTexts);
|
|
1902
2390
|
if (outcome) return outcome;
|
|
1903
2391
|
return {
|
|
1904
2392
|
status: "failure",
|
|
@@ -1906,91 +2394,6 @@ async function waitForPostSubmitOutcome(options) {
|
|
|
1906
2394
|
};
|
|
1907
2395
|
}
|
|
1908
2396
|
|
|
1909
|
-
// ../shared/dist/chunk-ERITSWKE.mjs
|
|
1910
|
-
var DEFAULT_FUZZY_FLOOR = 4;
|
|
1911
|
-
function normalizeId(value) {
|
|
1912
|
-
return String(value ?? "").normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1913
|
-
}
|
|
1914
|
-
var KIND_PREFIX_WORDS = "button|switch|toggle|input|field|link|btn|slider";
|
|
1915
|
-
var KEBAB_SNAKE_PREFIX_RE = new RegExp(`^(?:${KIND_PREFIX_WORDS})[-_]`, "i");
|
|
1916
|
-
var CAMEL_PREFIX_RE = new RegExp(`^(?:${KIND_PREFIX_WORDS})(?=[A-Z])`, "");
|
|
1917
|
-
function stripKindPrefix(id) {
|
|
1918
|
-
const raw = String(id ?? "");
|
|
1919
|
-
if (KEBAB_SNAKE_PREFIX_RE.test(raw)) return raw.replace(KEBAB_SNAKE_PREFIX_RE, "");
|
|
1920
|
-
if (CAMEL_PREFIX_RE.test(raw)) return raw.replace(CAMEL_PREFIX_RE, "");
|
|
1921
|
-
return raw;
|
|
1922
|
-
}
|
|
1923
|
-
function actionAllowsKind(action, kind) {
|
|
1924
|
-
if (!action || !kind) return true;
|
|
1925
|
-
switch (action) {
|
|
1926
|
-
case "press":
|
|
1927
|
-
case "longPress":
|
|
1928
|
-
return kind !== "field" && kind !== "input" && kind !== "slider";
|
|
1929
|
-
case "set_value":
|
|
1930
|
-
return kind === "slider" || kind === "field" || kind === "input";
|
|
1931
|
-
case "focus":
|
|
1932
|
-
return kind === "field" || kind === "input";
|
|
1933
|
-
case "toggle":
|
|
1934
|
-
return kind === "toggle";
|
|
1935
|
-
default:
|
|
1936
|
-
return true;
|
|
1937
|
-
}
|
|
1938
|
-
}
|
|
1939
|
-
function distinctIds(candidates) {
|
|
1940
|
-
return [...new Set(candidates.map((c) => c.id))];
|
|
1941
|
-
}
|
|
1942
|
-
function resolveTarget(requested, candidates, opts = {}) {
|
|
1943
|
-
const floor = opts.fuzzyFloor ?? DEFAULT_FUZZY_FLOOR;
|
|
1944
|
-
const nReq = normalizeId(requested);
|
|
1945
|
-
if (!nReq || candidates.length === 0) {
|
|
1946
|
-
return { status: "unverified", reason: "not-found" };
|
|
1947
|
-
}
|
|
1948
|
-
for (const c of candidates) {
|
|
1949
|
-
if (normalizeId(c.id) === nReq) {
|
|
1950
|
-
return { status: "matched", id: c.id, tier: "exact" };
|
|
1951
|
-
}
|
|
1952
|
-
}
|
|
1953
|
-
const labelExact = distinctIds(
|
|
1954
|
-
candidates.filter((c) => c.label && normalizeId(c.label) === nReq)
|
|
1955
|
-
);
|
|
1956
|
-
if (labelExact.length === 1) return { status: "matched", id: labelExact[0], tier: "exact" };
|
|
1957
|
-
if (labelExact.length > 1) return { status: "unverified", reason: "ambiguous" };
|
|
1958
|
-
const nReqStripped = normalizeId(stripKindPrefix(requested));
|
|
1959
|
-
for (const c of candidates) {
|
|
1960
|
-
const nId = normalizeId(c.id);
|
|
1961
|
-
const nIdStripped = normalizeId(stripKindPrefix(c.id));
|
|
1962
|
-
if (nReqStripped && (nReqStripped === nId || nReqStripped === nIdStripped) || nIdStripped && nIdStripped === nReq) {
|
|
1963
|
-
return { status: "matched", id: c.id, tier: "prefix" };
|
|
1964
|
-
}
|
|
1965
|
-
}
|
|
1966
|
-
if (opts.destructive) {
|
|
1967
|
-
return { status: "unverified", reason: "destructive-inexact" };
|
|
1968
|
-
}
|
|
1969
|
-
if (nReq.length < floor) {
|
|
1970
|
-
return { status: "unverified", reason: "not-found" };
|
|
1971
|
-
}
|
|
1972
|
-
const fuzzy = candidates.filter((c) => {
|
|
1973
|
-
for (const s of [c.id, c.label]) {
|
|
1974
|
-
if (!s) continue;
|
|
1975
|
-
const ns = normalizeId(s);
|
|
1976
|
-
if (ns.length >= floor && (ns.includes(nReq) || nReq.includes(ns))) return true;
|
|
1977
|
-
}
|
|
1978
|
-
return false;
|
|
1979
|
-
});
|
|
1980
|
-
if (fuzzy.length === 0) {
|
|
1981
|
-
return { status: "unverified", reason: "not-found" };
|
|
1982
|
-
}
|
|
1983
|
-
const typed = fuzzy.filter((c) => actionAllowsKind(opts.action, c.kind));
|
|
1984
|
-
if (typed.length === 0) {
|
|
1985
|
-
return { status: "unverified", reason: "type-mismatch" };
|
|
1986
|
-
}
|
|
1987
|
-
const ids = distinctIds(typed);
|
|
1988
|
-
if (ids.length > 1) {
|
|
1989
|
-
return { status: "unverified", reason: "ambiguous" };
|
|
1990
|
-
}
|
|
1991
|
-
return { status: "matched", id: ids[0], tier: "fuzzy" };
|
|
1992
|
-
}
|
|
1993
|
-
|
|
1994
2397
|
// src/executor/handlers/uiInteractionHandler.ts
|
|
1995
2398
|
function findSnapshotButton(targetId) {
|
|
1996
2399
|
try {
|
|
@@ -2003,16 +2406,16 @@ function findSnapshotButton(targetId) {
|
|
|
2003
2406
|
}
|
|
2004
2407
|
}
|
|
2005
2408
|
function buildUiDiagnose(targetId, cause) {
|
|
2006
|
-
const activePath =
|
|
2007
|
-
const screen = activePath[activePath.length - 1] ??
|
|
2409
|
+
const activePath = chunkUZ2D4BVX_js.getActiveRouteNames();
|
|
2410
|
+
const screen = activePath[activePath.length - 1] ?? chunkUZ2D4BVX_js.getCurrentScreen() ?? void 0;
|
|
2008
2411
|
const screenPath = activePath.length > 1 ? activePath.join("/") : screen;
|
|
2009
2412
|
const diagnose = {
|
|
2010
2413
|
category: cause === "not-found" ? "component-not-found" : cause === "disabled" ? "disabled" : "unknown",
|
|
2011
2414
|
targetId,
|
|
2012
2415
|
screen: screenPath
|
|
2013
2416
|
};
|
|
2014
|
-
if (
|
|
2015
|
-
diagnose.visibleMessage =
|
|
2417
|
+
if (chunkUZ2D4BVX_js.isOptionalStepAutomationFailure(targetId, screenPath, activePath)) {
|
|
2418
|
+
diagnose.visibleMessage = chunkUZ2D4BVX_js.OPTIONAL_STEP_AUTOMATION_HINT;
|
|
2016
2419
|
diagnose.recoverable = true;
|
|
2017
2420
|
}
|
|
2018
2421
|
return diagnose;
|
|
@@ -2063,6 +2466,7 @@ function stripComponentPrefix(componentId) {
|
|
|
2063
2466
|
return null;
|
|
2064
2467
|
}
|
|
2065
2468
|
function resolveComponentId(componentId, registry, action) {
|
|
2469
|
+
if (chunkUZ2D4BVX_js.isSourceControlId(componentId)) return componentId;
|
|
2066
2470
|
if (registry.getTarget(componentId) || registry.getToggle(componentId) || registry.getField(componentId) || registry.getSlider(componentId)) {
|
|
2067
2471
|
return componentId;
|
|
2068
2472
|
}
|
|
@@ -2070,15 +2474,16 @@ function resolveComponentId(componentId, registry, action) {
|
|
|
2070
2474
|
const snapshot = registry.snapshot();
|
|
2071
2475
|
for (const comp of snapshot) {
|
|
2072
2476
|
if (comp.id.toLowerCase() === lower) {
|
|
2073
|
-
|
|
2477
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
2074
2478
|
`resolveComponentId: case-insensitive match "${componentId}" \u2192 "${comp.id}"`
|
|
2075
2479
|
);
|
|
2076
2480
|
return comp.id;
|
|
2077
2481
|
}
|
|
2078
2482
|
}
|
|
2079
|
-
|
|
2483
|
+
if (isPositionalControlId(componentId)) return componentId;
|
|
2484
|
+
const currentScreen = chunkUZ2D4BVX_js.getCurrentScreen();
|
|
2080
2485
|
if (currentScreen) {
|
|
2081
|
-
const screenMeta =
|
|
2486
|
+
const screenMeta = chunkUZ2D4BVX_js.getScreenMetadata(currentScreen);
|
|
2082
2487
|
const actions = screenMeta?.actions;
|
|
2083
2488
|
if (actions && Array.isArray(actions)) {
|
|
2084
2489
|
const metaAction = actions.find(
|
|
@@ -2087,14 +2492,14 @@ function resolveComponentId(componentId, registry, action) {
|
|
|
2087
2492
|
if (metaAction && typeof metaAction === "object" && metaAction.label) {
|
|
2088
2493
|
const metaLabel = metaAction.label;
|
|
2089
2494
|
const normalizedMetaLabel = metaLabel.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]/g, "");
|
|
2090
|
-
|
|
2495
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
2091
2496
|
`resolveComponentId: found screen metadata for "${componentId}" \u2192 label="${metaLabel}"`
|
|
2092
2497
|
);
|
|
2093
2498
|
for (const comp of snapshot) {
|
|
2094
2499
|
if (!comp.label) continue;
|
|
2095
2500
|
const compLabel = comp.label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]/g, "");
|
|
2096
2501
|
if (compLabel === normalizedMetaLabel || compLabel.includes(normalizedMetaLabel) || normalizedMetaLabel.includes(compLabel)) {
|
|
2097
|
-
|
|
2502
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
2098
2503
|
`resolveComponentId: FOUND via metadata: "${componentId}" \u2192 "${comp.id}" (label="${comp.label}")`
|
|
2099
2504
|
);
|
|
2100
2505
|
return comp.id;
|
|
@@ -2109,9 +2514,9 @@ function resolveComponentId(componentId, registry, action) {
|
|
|
2109
2514
|
label: c.label,
|
|
2110
2515
|
kind: c.kind
|
|
2111
2516
|
}));
|
|
2112
|
-
const match = resolveTarget(componentId, candidates, { action });
|
|
2517
|
+
const match = chunkUZ2D4BVX_js.resolveTarget(componentId, candidates, { action });
|
|
2113
2518
|
if (match.status === "matched") {
|
|
2114
|
-
|
|
2519
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
2115
2520
|
`resolveComponentId: matched "${componentId}" -> "${match.id}" (tier=${match.tier})`
|
|
2116
2521
|
);
|
|
2117
2522
|
return match.id;
|
|
@@ -2201,7 +2606,7 @@ function setValueHandler(rawComponentId, requested, registry) {
|
|
|
2201
2606
|
try {
|
|
2202
2607
|
slider.setValue(applied);
|
|
2203
2608
|
if (applied !== requestedValue) {
|
|
2204
|
-
|
|
2609
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
2205
2610
|
`uiInteractionHandler: set_value snapped ${requestedValue} \u2192 ${applied} for "${componentId}" (step=${step})`
|
|
2206
2611
|
);
|
|
2207
2612
|
}
|
|
@@ -2236,7 +2641,7 @@ function checkModalOcclusion(rawComponentId, action) {
|
|
|
2236
2641
|
return null;
|
|
2237
2642
|
}
|
|
2238
2643
|
if (typeof rawComponentId !== "string" || rawComponentId.trim().length === 0) return null;
|
|
2239
|
-
const dialog =
|
|
2644
|
+
const dialog = chunkUZ2D4BVX_js.getOpenNativeDialog();
|
|
2240
2645
|
if (dialog) {
|
|
2241
2646
|
const needle = normalizeIdent(rawComponentId);
|
|
2242
2647
|
if (dialog.buttons.some((b) => normalizeIdent(b.label) === needle)) return null;
|
|
@@ -2246,16 +2651,16 @@ function checkModalOcclusion(rawComponentId, action) {
|
|
|
2246
2651
|
diagnose: {
|
|
2247
2652
|
category: "ambiguous-target",
|
|
2248
2653
|
targetId: rawComponentId,
|
|
2249
|
-
screen:
|
|
2654
|
+
screen: chunkUZ2D4BVX_js.getCurrentScreen() ?? void 0,
|
|
2250
2655
|
candidates: dialog.buttons.map((b) => b.label).slice(0, 8)
|
|
2251
2656
|
}
|
|
2252
2657
|
};
|
|
2253
2658
|
}
|
|
2254
|
-
const fiberRoot =
|
|
2659
|
+
const fiberRoot = chunkUZ2D4BVX_js.getFiberRoot();
|
|
2255
2660
|
if (!fiberRoot) return null;
|
|
2256
2661
|
let snap;
|
|
2257
2662
|
try {
|
|
2258
|
-
snap =
|
|
2663
|
+
snap = chunkUZ2D4BVX_js.walkFiber(fiberRoot);
|
|
2259
2664
|
} catch {
|
|
2260
2665
|
return null;
|
|
2261
2666
|
}
|
|
@@ -2317,15 +2722,18 @@ function checkModalOcclusion(rawComponentId, action) {
|
|
|
2317
2722
|
}
|
|
2318
2723
|
function uiInteractionHandler(payload, context) {
|
|
2319
2724
|
const { permissions } = context;
|
|
2320
|
-
const registry = context.registry ??
|
|
2725
|
+
const registry = context.registry ?? chunkUZ2D4BVX_js.componentRegistry;
|
|
2321
2726
|
if (!permissions.canInteractUI) {
|
|
2322
2727
|
return {
|
|
2323
2728
|
success: false,
|
|
2324
|
-
error: "UI interaction
|
|
2325
|
-
diagnose:
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2729
|
+
error: chunkUZ2D4BVX_js.permissionDeniedMessage("UI interaction", "canInteractUI"),
|
|
2730
|
+
diagnose: {
|
|
2731
|
+
...buildUiDiagnose(
|
|
2732
|
+
payload.componentId ?? payload.targetId ?? "",
|
|
2733
|
+
"unknown"
|
|
2734
|
+
),
|
|
2735
|
+
recoverable: false
|
|
2736
|
+
}
|
|
2329
2737
|
};
|
|
2330
2738
|
}
|
|
2331
2739
|
const { action } = payload;
|
|
@@ -2339,7 +2747,7 @@ function uiInteractionHandler(payload, context) {
|
|
|
2339
2747
|
if (sliderId) {
|
|
2340
2748
|
const smuggled = payload.value ?? payload.params?.value;
|
|
2341
2749
|
if (smuggled !== void 0) {
|
|
2342
|
-
|
|
2750
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
2343
2751
|
`uiInteractionHandler: "${actionStr}" on slider "${sliderId}" carried value=${JSON.stringify(smuggled)} \u2014 routing to set_value`
|
|
2344
2752
|
);
|
|
2345
2753
|
return setValueHandler(rawComponentId, smuggled, registry);
|
|
@@ -2350,23 +2758,23 @@ function uiInteractionHandler(payload, context) {
|
|
|
2350
2758
|
diagnose: { ...buildUiDiagnose(sliderId, "unknown"), recoverable: true }
|
|
2351
2759
|
};
|
|
2352
2760
|
}
|
|
2353
|
-
const openDialog =
|
|
2761
|
+
const openDialog = chunkUZ2D4BVX_js.getOpenNativeDialog();
|
|
2354
2762
|
const isPressVerb = actionStr === "press" || actionStr === "tap" || actionStr === "click";
|
|
2355
2763
|
if (openDialog && isPressVerb) {
|
|
2356
2764
|
const needle = normalizeIdent(rawComponentId);
|
|
2357
2765
|
const button = openDialog.buttons.find((b) => normalizeIdent(b.label) === needle);
|
|
2358
2766
|
if (button) {
|
|
2359
2767
|
button.press();
|
|
2360
|
-
|
|
2768
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(`uiInteractionHandler: pressed native dialog button "${button.label}"`);
|
|
2361
2769
|
return { success: true, effect: "changed" };
|
|
2362
2770
|
}
|
|
2363
2771
|
}
|
|
2364
2772
|
if (!openDialog && isPressVerb) {
|
|
2365
|
-
const answered =
|
|
2773
|
+
const answered = chunkUZ2D4BVX_js.getLastAnsweredNativeDialog();
|
|
2366
2774
|
const needle = normalizeIdent(rawComponentId);
|
|
2367
2775
|
if (answered && needle) {
|
|
2368
2776
|
if (answered.answeredWith && normalizeIdent(answered.answeredWith) === needle) {
|
|
2369
|
-
|
|
2777
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
2370
2778
|
`uiInteractionHandler: native dialog button "${answered.answeredWith}" was already pressed and the dialog is closed \u2014 treating the repeat as done`
|
|
2371
2779
|
);
|
|
2372
2780
|
return { success: true, effect: "completed" };
|
|
@@ -2378,7 +2786,7 @@ function uiInteractionHandler(payload, context) {
|
|
|
2378
2786
|
diagnose: {
|
|
2379
2787
|
category: "component-not-found",
|
|
2380
2788
|
targetId: rawComponentId,
|
|
2381
|
-
screen:
|
|
2789
|
+
screen: chunkUZ2D4BVX_js.getCurrentScreen() ?? void 0,
|
|
2382
2790
|
recoverable: false
|
|
2383
2791
|
}
|
|
2384
2792
|
};
|
|
@@ -2387,7 +2795,7 @@ function uiInteractionHandler(payload, context) {
|
|
|
2387
2795
|
}
|
|
2388
2796
|
const occluded = checkModalOcclusion(rawComponentId, actionStr);
|
|
2389
2797
|
if (occluded) {
|
|
2390
|
-
|
|
2798
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
2391
2799
|
`uiInteractionHandler: blocked "${actionStr}" on "${rawComponentId}" \u2014 target is behind an open modal`
|
|
2392
2800
|
);
|
|
2393
2801
|
return occluded;
|
|
@@ -2395,7 +2803,7 @@ function uiInteractionHandler(payload, context) {
|
|
|
2395
2803
|
if (typeof rawComponentId === "string" && rawComponentId.trim().toLowerCase().startsWith("el:")) {
|
|
2396
2804
|
const result = dispatchElementOrTarget(rawComponentId, registry, actionStr);
|
|
2397
2805
|
if (result.success) {
|
|
2398
|
-
|
|
2806
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
2399
2807
|
`uiInteractionHandler: interaction element dispatch succeeded for "${rawComponentId}"`
|
|
2400
2808
|
);
|
|
2401
2809
|
}
|
|
@@ -2403,17 +2811,17 @@ function uiInteractionHandler(payload, context) {
|
|
|
2403
2811
|
}
|
|
2404
2812
|
const ordinal = parseSyntheticListItemId(rawComponentId);
|
|
2405
2813
|
if (ordinal && (action === "press" || actionStr === "tap" || actionStr === "click" || actionStr === "longPress")) {
|
|
2406
|
-
|
|
2814
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
2407
2815
|
`uiInteractionHandler: dispatching synthetic list ordinal \u2014 componentId="${rawComponentId}" list=${ordinal.listIndex} item=${ordinal.itemIndex}`
|
|
2408
2816
|
);
|
|
2409
2817
|
const result = pressListItemAtOrdinal(ordinal.listIndex, ordinal.itemIndex);
|
|
2410
2818
|
if (result.ok) {
|
|
2411
|
-
|
|
2819
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
2412
2820
|
`uiInteractionHandler: synthetic ordinal press succeeded (container=${result.containerType ?? "List"})`
|
|
2413
2821
|
);
|
|
2414
2822
|
return { success: true };
|
|
2415
2823
|
}
|
|
2416
|
-
const screen =
|
|
2824
|
+
const screen = chunkUZ2D4BVX_js.getCurrentScreen() ?? void 0;
|
|
2417
2825
|
if (result.reason === "list-not-found" || result.reason === "item-not-found") {
|
|
2418
2826
|
return {
|
|
2419
2827
|
success: false,
|
|
@@ -2454,7 +2862,7 @@ function uiInteractionHandler(payload, context) {
|
|
|
2454
2862
|
};
|
|
2455
2863
|
}
|
|
2456
2864
|
const componentId = resolveComponentId(rawComponentId, registry, actionStr);
|
|
2457
|
-
|
|
2865
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
2458
2866
|
`uiInteractionHandler: resolved componentId="${payload.componentId}" \u2192 "${componentId}"`
|
|
2459
2867
|
);
|
|
2460
2868
|
const target = registry.getTarget(componentId);
|
|
@@ -2507,7 +2915,7 @@ function uiInteractionHandler(payload, context) {
|
|
|
2507
2915
|
return { success: false, error: err?.message ?? "Focus failed" };
|
|
2508
2916
|
}
|
|
2509
2917
|
}
|
|
2510
|
-
|
|
2918
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
2511
2919
|
`uiInteractionHandler: registry miss for "${componentId}", falling back to fiber tree`
|
|
2512
2920
|
);
|
|
2513
2921
|
const namedToggle = dispatchIdentifiedToggle(componentId, actionStr);
|
|
@@ -2519,7 +2927,7 @@ function uiInteractionHandler(payload, context) {
|
|
|
2519
2927
|
try {
|
|
2520
2928
|
if (actionStr === "press" && handle.kind === "target" && handle.press) {
|
|
2521
2929
|
handle.press();
|
|
2522
|
-
|
|
2930
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
2523
2931
|
`uiInteractionHandler: fiber fallback press succeeded for "${componentId}"`
|
|
2524
2932
|
);
|
|
2525
2933
|
return { success: true };
|
|
@@ -2555,6 +2963,28 @@ function uiInteractionHandler(payload, context) {
|
|
|
2555
2963
|
};
|
|
2556
2964
|
}
|
|
2557
2965
|
|
|
2966
|
+
// src/executor/completeTextEdit.ts
|
|
2967
|
+
var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
2968
|
+
async function completeTextEdit(fieldId, expected, registered, origin, resolveRegistered) {
|
|
2969
|
+
await sleep2(80);
|
|
2970
|
+
const current2 = findInteractiveByIdentifier(fieldId, { kind: "field" });
|
|
2971
|
+
if (origin?.controlIdentity && current2?.controlIdentity !== origin.controlIdentity) return false;
|
|
2972
|
+
if (registered && resolveRegistered && resolveRegistered() !== registered) return false;
|
|
2973
|
+
if (registered?.finishEditing) registered.finishEditing();
|
|
2974
|
+
else if (current2 && (current2.matchCount ?? 1) === 1 && !current2.disabled)
|
|
2975
|
+
current2.finishEditing?.();
|
|
2976
|
+
const started = Date.now();
|
|
2977
|
+
do {
|
|
2978
|
+
await sleep2(80);
|
|
2979
|
+
const live = findInteractiveByIdentifier(fieldId, { kind: "field" });
|
|
2980
|
+
if (origin?.controlIdentity && live?.controlIdentity !== origin.controlIdentity) return false;
|
|
2981
|
+
if (registered && resolveRegistered && resolveRegistered() !== registered) return false;
|
|
2982
|
+
const value = registered ? registered.getValue() : live?.getValue?.();
|
|
2983
|
+
if (value !== void 0 && value !== null && String(value) === String(expected)) return true;
|
|
2984
|
+
} while (Date.now() - started < 480);
|
|
2985
|
+
return false;
|
|
2986
|
+
}
|
|
2987
|
+
|
|
2558
2988
|
// src/executor/formSubmitResolve.ts
|
|
2559
2989
|
var SUBMIT_LABEL_HINT_RE = /\b(submit|save|send|continue|next|sign\s*in|log\s*in|register|salvar|enviar|entrar|cadastrar|continuar|proximo|próximo|avancar|avançar|confirmar|guardar|registrarse|iniciar\s+sesi[óo]n|enregistrer|envoyer|valider|soumettre|confirmer|se\s+connecter|s['e]\s*inscrire)\b/i;
|
|
2560
2990
|
var AGENT_CHROME_TARGET_RE = /\b(fechar|close|dismiss|cancelar|cancel|limpar|clear|chat\s+do\s+assistente|assistant\s+chat)\b/i;
|
|
@@ -2582,7 +3012,7 @@ function submitLabelHintsSubmit(label) {
|
|
|
2582
3012
|
return SUBMIT_LABEL_HINT_RE.test(trimmed);
|
|
2583
3013
|
}
|
|
2584
3014
|
function screenDeclaresSubmitAction(screenName) {
|
|
2585
|
-
const meta =
|
|
3015
|
+
const meta = chunkUZ2D4BVX_js.getScreenMetadata(screenName);
|
|
2586
3016
|
return Array.isArray(meta?.actions) && meta.actions.some(
|
|
2587
3017
|
(action) => typeof action === "object" && action !== null && action.type === "submit"
|
|
2588
3018
|
);
|
|
@@ -2615,7 +3045,7 @@ function resolveFormScreensForSubmit(screen, activePath, registry) {
|
|
|
2615
3045
|
} else {
|
|
2616
3046
|
push(screen);
|
|
2617
3047
|
}
|
|
2618
|
-
push(
|
|
3048
|
+
push(chunkUZ2D4BVX_js.getCurrentScreen() ?? void 0);
|
|
2619
3049
|
const withSubmit = [];
|
|
2620
3050
|
const rest = [];
|
|
2621
3051
|
for (const name of ordered) {
|
|
@@ -2633,7 +3063,7 @@ function collectSubmitTargetCandidates(screens, registry) {
|
|
|
2633
3063
|
candidates.push(id);
|
|
2634
3064
|
};
|
|
2635
3065
|
for (const screenName of screens) {
|
|
2636
|
-
const meta =
|
|
3066
|
+
const meta = chunkUZ2D4BVX_js.getScreenMetadata(screenName);
|
|
2637
3067
|
const submitMeta = Array.isArray(meta?.actions) ? meta.actions.find(
|
|
2638
3068
|
(action) => typeof action === "object" && action !== null && action.type === "submit"
|
|
2639
3069
|
) : void 0;
|
|
@@ -2677,8 +3107,8 @@ function readVisibleValidation(fieldId, label) {
|
|
|
2677
3107
|
return void 0;
|
|
2678
3108
|
}
|
|
2679
3109
|
function resolveScreenContext() {
|
|
2680
|
-
const activePath =
|
|
2681
|
-
const screen = activePath[activePath.length - 1] ??
|
|
3110
|
+
const activePath = chunkUZ2D4BVX_js.getActiveRouteNames();
|
|
3111
|
+
const screen = activePath[activePath.length - 1] ?? chunkUZ2D4BVX_js.getCurrentScreen() ?? void 0;
|
|
2682
3112
|
return { screen, activePath };
|
|
2683
3113
|
}
|
|
2684
3114
|
function selectValueApplied(fieldId, requestedValue, currentValue, registry) {
|
|
@@ -2686,36 +3116,36 @@ function selectValueApplied(fieldId, requestedValue, currentValue, registry) {
|
|
|
2686
3116
|
if (!requested) return false;
|
|
2687
3117
|
const meta = getMetadataField(fieldId, registry);
|
|
2688
3118
|
const options = Array.isArray(meta?.options) ? meta.options : [];
|
|
2689
|
-
const requestedNorm =
|
|
2690
|
-
const currentNorm =
|
|
3119
|
+
const requestedNorm = chunkUZ2D4BVX_js.normalize3(requested);
|
|
3120
|
+
const currentNorm = chunkUZ2D4BVX_js.normalize3(currentValue);
|
|
2691
3121
|
if (currentNorm === requestedNorm) return true;
|
|
2692
3122
|
for (const option of options) {
|
|
2693
3123
|
const value = typeof option?.value === "string" ? option.value : "";
|
|
2694
3124
|
const label = typeof option?.label === "string" ? option.label : "";
|
|
2695
|
-
if (
|
|
2696
|
-
if (
|
|
2697
|
-
if (
|
|
3125
|
+
if (chunkUZ2D4BVX_js.normalize3(value) === requestedNorm && chunkUZ2D4BVX_js.normalize3(label) === currentNorm) return true;
|
|
3126
|
+
if (chunkUZ2D4BVX_js.normalize3(label) === requestedNorm && chunkUZ2D4BVX_js.normalize3(label) === currentNorm) return true;
|
|
3127
|
+
if (chunkUZ2D4BVX_js.normalize3(value) === requestedNorm && chunkUZ2D4BVX_js.normalize3(value) === currentNorm) return true;
|
|
2698
3128
|
}
|
|
2699
3129
|
return false;
|
|
2700
3130
|
}
|
|
2701
3131
|
function getMetadataField(fieldId, registry) {
|
|
2702
3132
|
const screens = /* @__PURE__ */ new Set();
|
|
2703
|
-
for (const name of
|
|
2704
|
-
const
|
|
2705
|
-
if (
|
|
3133
|
+
for (const name of chunkUZ2D4BVX_js.getActiveRouteNames()) screens.add(name);
|
|
3134
|
+
const current2 = chunkUZ2D4BVX_js.getCurrentScreen();
|
|
3135
|
+
if (current2) screens.add(current2);
|
|
2706
3136
|
if (registry) {
|
|
2707
3137
|
for (const comp of registry.snapshot()) {
|
|
2708
3138
|
if (comp.kind === "field" && comp.screen) screens.add(comp.screen);
|
|
2709
3139
|
}
|
|
2710
3140
|
}
|
|
2711
|
-
const needle =
|
|
3141
|
+
const needle = chunkUZ2D4BVX_js.normalize3(fieldId);
|
|
2712
3142
|
for (const screenName of screens) {
|
|
2713
|
-
const screenMeta =
|
|
3143
|
+
const screenMeta = chunkUZ2D4BVX_js.getScreenMetadata(screenName);
|
|
2714
3144
|
const fields = Array.isArray(screenMeta?.fields) ? screenMeta.fields : [];
|
|
2715
3145
|
const match = fields.find((field) => {
|
|
2716
3146
|
if (!field || typeof field !== "object") return false;
|
|
2717
|
-
const id = typeof field.id === "string" ?
|
|
2718
|
-
const label = typeof field.label === "string" ?
|
|
3147
|
+
const id = typeof field.id === "string" ? chunkUZ2D4BVX_js.normalize3(field.id) : "";
|
|
3148
|
+
const label = typeof field.label === "string" ? chunkUZ2D4BVX_js.normalize3(field.label) : "";
|
|
2719
3149
|
return id === needle || label === needle;
|
|
2720
3150
|
});
|
|
2721
3151
|
if (match) return match;
|
|
@@ -2727,11 +3157,11 @@ function resolveSelectOption(fieldId, value, registry) {
|
|
|
2727
3157
|
if (!requested) return void 0;
|
|
2728
3158
|
const meta = getMetadataField(fieldId, registry);
|
|
2729
3159
|
const options = Array.isArray(meta?.options) ? meta.options : [];
|
|
2730
|
-
const requestedNorm =
|
|
3160
|
+
const requestedNorm = chunkUZ2D4BVX_js.normalize3(requested);
|
|
2731
3161
|
for (const option of options) {
|
|
2732
3162
|
const optionValue = typeof option?.value === "string" ? option.value : "";
|
|
2733
3163
|
const optionLabel = typeof option?.label === "string" ? option.label : "";
|
|
2734
|
-
if (
|
|
3164
|
+
if (chunkUZ2D4BVX_js.normalize3(optionValue) === requestedNorm || chunkUZ2D4BVX_js.normalize3(optionLabel) === requestedNorm) {
|
|
2735
3165
|
return { value: optionValue, label: optionLabel };
|
|
2736
3166
|
}
|
|
2737
3167
|
}
|
|
@@ -2743,7 +3173,7 @@ async function tryOpenSelectModal(fieldId, registry) {
|
|
|
2743
3173
|
if (!target) continue;
|
|
2744
3174
|
try {
|
|
2745
3175
|
target.press();
|
|
2746
|
-
await
|
|
3176
|
+
await sleep3(180);
|
|
2747
3177
|
return true;
|
|
2748
3178
|
} catch {
|
|
2749
3179
|
}
|
|
@@ -2781,12 +3211,12 @@ async function tryPressSelectOption(fieldId, value, registry, options = {}) {
|
|
|
2781
3211
|
return {
|
|
2782
3212
|
success: false,
|
|
2783
3213
|
error: `No pressable option found for select field "${fieldId}"`,
|
|
2784
|
-
diagnose: { category: "component-not-found", fieldId, screen:
|
|
3214
|
+
diagnose: { category: "component-not-found", fieldId, screen: chunkUZ2D4BVX_js.getCurrentScreen() ?? void 0 }
|
|
2785
3215
|
};
|
|
2786
3216
|
}
|
|
2787
3217
|
function normalizeFieldType(type) {
|
|
2788
3218
|
if (typeof type !== "string") return void 0;
|
|
2789
|
-
const normalized =
|
|
3219
|
+
const normalized = chunkUZ2D4BVX_js.normalize3(type);
|
|
2790
3220
|
if (normalized === "select" || normalized === "picker" || normalized === "dropdown")
|
|
2791
3221
|
return "select";
|
|
2792
3222
|
if (normalized === "toggle" || normalized === "switch" || normalized === "checkbox")
|
|
@@ -2816,7 +3246,7 @@ function fieldCueTerms(fieldId, label) {
|
|
|
2816
3246
|
);
|
|
2817
3247
|
const terms = /* @__PURE__ */ new Set();
|
|
2818
3248
|
for (const value of raw) {
|
|
2819
|
-
const normalized =
|
|
3249
|
+
const normalized = chunkUZ2D4BVX_js.normalize3(value);
|
|
2820
3250
|
if (normalized.length >= 3 && normalized !== "id") terms.add(normalized);
|
|
2821
3251
|
}
|
|
2822
3252
|
return [...terms];
|
|
@@ -2824,17 +3254,17 @@ function fieldCueTerms(fieldId, label) {
|
|
|
2824
3254
|
function snapshotHasFieldCue(snap, fieldId, label) {
|
|
2825
3255
|
const terms = fieldCueTerms(fieldId, label);
|
|
2826
3256
|
if (terms.length === 0) return false;
|
|
2827
|
-
const visible = [...snap.texts ?? [], ...(snap.buttons ?? []).map((b) => b.label ?? b.id ?? "")].map((text) =>
|
|
3257
|
+
const visible = [...snap.texts ?? [], ...(snap.buttons ?? []).map((b) => b.label ?? b.id ?? "")].map((text) => chunkUZ2D4BVX_js.normalize3(text)).filter(Boolean);
|
|
2828
3258
|
return visible.some((text) => terms.some((term) => text.includes(term) || term.includes(text)));
|
|
2829
3259
|
}
|
|
2830
3260
|
function scoreCandidateText(value, texts) {
|
|
2831
|
-
const valueNorm =
|
|
3261
|
+
const valueNorm = chunkUZ2D4BVX_js.normalize3(String(value ?? ""));
|
|
2832
3262
|
if (!valueNorm) return 0;
|
|
2833
3263
|
let best = 0;
|
|
2834
3264
|
for (const text of texts) {
|
|
2835
|
-
const textNorm =
|
|
3265
|
+
const textNorm = chunkUZ2D4BVX_js.normalize3(text);
|
|
2836
3266
|
if (!textNorm) continue;
|
|
2837
|
-
best = Math.max(best,
|
|
3267
|
+
best = Math.max(best, chunkUZ2D4BVX_js.matchScore(valueNorm, textNorm));
|
|
2838
3268
|
}
|
|
2839
3269
|
return best;
|
|
2840
3270
|
}
|
|
@@ -2848,7 +3278,7 @@ function optionTexts(option) {
|
|
|
2848
3278
|
function buildChoiceCandidates(snap, fieldId, value, allowFirstVisibleWhenNoCue, registry) {
|
|
2849
3279
|
const fieldLabel = getFieldLabel(fieldId, registry);
|
|
2850
3280
|
const fieldCueVisible = snapshotHasFieldCue(snap, fieldId, fieldLabel);
|
|
2851
|
-
const genericValue =
|
|
3281
|
+
const genericValue = chunkUZ2D4BVX_js.isGenericSelectValue(value);
|
|
2852
3282
|
const candidates = [];
|
|
2853
3283
|
let order = 0;
|
|
2854
3284
|
const choiceGroups = snap.choiceGroups ?? [];
|
|
@@ -2860,7 +3290,7 @@ function buildChoiceCandidates(snap, fieldId, value, allowFirstVisibleWhenNoCue,
|
|
|
2860
3290
|
const groupCueScore = Math.max(
|
|
2861
3291
|
globalCueScore,
|
|
2862
3292
|
...groupTexts.map((text) => {
|
|
2863
|
-
const normalized =
|
|
3293
|
+
const normalized = chunkUZ2D4BVX_js.normalize3(text);
|
|
2864
3294
|
return fieldCueTerms(fieldId, fieldLabel).some(
|
|
2865
3295
|
(term) => normalized.includes(term) || term.includes(normalized)
|
|
2866
3296
|
) ? 80 : 0;
|
|
@@ -2897,7 +3327,7 @@ function buildChoiceCandidates(snap, fieldId, value, allowFirstVisibleWhenNoCue,
|
|
|
2897
3327
|
const elementCueScore = Math.max(
|
|
2898
3328
|
fieldCueVisible && elements.length <= 12 ? 50 : 0,
|
|
2899
3329
|
...cueTexts.map((text) => {
|
|
2900
|
-
const normalized =
|
|
3330
|
+
const normalized = chunkUZ2D4BVX_js.normalize3(text);
|
|
2901
3331
|
return fieldTerms.some((term) => normalized.includes(term) || term.includes(normalized)) ? 80 : 0;
|
|
2902
3332
|
})
|
|
2903
3333
|
);
|
|
@@ -2955,7 +3385,7 @@ async function selectVisibleChoiceAsync(fieldId, value, registry, options) {
|
|
|
2955
3385
|
return {
|
|
2956
3386
|
success: false,
|
|
2957
3387
|
error: err?.message ?? "Could not capture visible choices",
|
|
2958
|
-
diagnose: { category: "unknown", fieldId, screen:
|
|
3388
|
+
diagnose: { category: "unknown", fieldId, screen: chunkUZ2D4BVX_js.getCurrentScreen() ?? void 0 }
|
|
2959
3389
|
};
|
|
2960
3390
|
}
|
|
2961
3391
|
const candidates = buildChoiceCandidates(
|
|
@@ -2973,7 +3403,7 @@ async function selectVisibleChoiceAsync(fieldId, value, registry, options) {
|
|
|
2973
3403
|
diagnose: {
|
|
2974
3404
|
category: "component-not-found",
|
|
2975
3405
|
fieldId,
|
|
2976
|
-
screen:
|
|
3406
|
+
screen: chunkUZ2D4BVX_js.getCurrentScreen() ?? void 0
|
|
2977
3407
|
}
|
|
2978
3408
|
};
|
|
2979
3409
|
}
|
|
@@ -2987,7 +3417,7 @@ async function selectVisibleChoiceAsync(fieldId, value, registry, options) {
|
|
|
2987
3417
|
}
|
|
2988
3418
|
function isContinuationButton(label) {
|
|
2989
3419
|
if (!label) return false;
|
|
2990
|
-
return /^(next|continue|proximo|prox|continuar|avancar|avançar)$/i.test(
|
|
3420
|
+
return /^(next|continue|proximo|prox|continuar|avancar|avançar)$/i.test(chunkUZ2D4BVX_js.normalize3(label));
|
|
2991
3421
|
}
|
|
2992
3422
|
function pressContinuationButton(registry) {
|
|
2993
3423
|
const snap = captureSnapshot();
|
|
@@ -3000,40 +3430,40 @@ function pressContinuationButton(registry) {
|
|
|
3000
3430
|
return {
|
|
3001
3431
|
success: false,
|
|
3002
3432
|
error: "No enabled continuation button is visible",
|
|
3003
|
-
diagnose: { category: "component-not-found", screen:
|
|
3433
|
+
diagnose: { category: "component-not-found", screen: chunkUZ2D4BVX_js.getCurrentScreen() ?? void 0 }
|
|
3004
3434
|
};
|
|
3005
3435
|
}
|
|
3006
3436
|
return pressTargetByIdOrLabel(id, registry);
|
|
3007
3437
|
}
|
|
3008
3438
|
function findField(fieldId, registry) {
|
|
3009
|
-
|
|
3439
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(`findField: searching for fieldId="${fieldId}"`);
|
|
3010
3440
|
const exact = registry.getField(fieldId);
|
|
3011
3441
|
if (exact) {
|
|
3012
|
-
|
|
3442
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(`findField: FOUND exact match for fieldId="${fieldId}"`);
|
|
3013
3443
|
return exact;
|
|
3014
3444
|
}
|
|
3015
3445
|
const lower = fieldId.toLowerCase();
|
|
3016
3446
|
const snapshot = registry.snapshot();
|
|
3017
3447
|
for (const comp of snapshot) {
|
|
3018
3448
|
if (comp.kind === "field" && comp.id.toLowerCase() === lower) {
|
|
3019
|
-
|
|
3449
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
3020
3450
|
`findField: FOUND case-insensitive match: registered="${comp.id}" for searched="${fieldId}"`
|
|
3021
3451
|
);
|
|
3022
3452
|
return registry.getField(comp.id);
|
|
3023
3453
|
}
|
|
3024
3454
|
}
|
|
3025
|
-
const currentScreenForTieBreak =
|
|
3026
|
-
const needle =
|
|
3455
|
+
const currentScreenForTieBreak = chunkUZ2D4BVX_js.getCurrentScreen();
|
|
3456
|
+
const needle = chunkUZ2D4BVX_js.normalize3(fieldId);
|
|
3027
3457
|
let bestComp;
|
|
3028
3458
|
let bestScore = 0;
|
|
3029
3459
|
let bestOnCurrentScreen = false;
|
|
3030
3460
|
for (const comp of snapshot) {
|
|
3031
3461
|
if (comp.kind !== "field") continue;
|
|
3032
|
-
const candidates = [
|
|
3033
|
-
if (comp.label) candidates.push(
|
|
3462
|
+
const candidates = [chunkUZ2D4BVX_js.normalize3(comp.id)];
|
|
3463
|
+
if (comp.label) candidates.push(chunkUZ2D4BVX_js.normalize3(comp.label));
|
|
3034
3464
|
let candidateScore = 0;
|
|
3035
3465
|
for (const cand of candidates) {
|
|
3036
|
-
const s =
|
|
3466
|
+
const s = chunkUZ2D4BVX_js.matchScore(needle, cand);
|
|
3037
3467
|
if (s > candidateScore) candidateScore = s;
|
|
3038
3468
|
}
|
|
3039
3469
|
if (candidateScore === 0) continue;
|
|
@@ -3046,14 +3476,14 @@ function findField(fieldId, registry) {
|
|
|
3046
3476
|
}
|
|
3047
3477
|
}
|
|
3048
3478
|
if (bestComp && bestScore >= 75) {
|
|
3049
|
-
|
|
3479
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
3050
3480
|
`findField: scored match "${fieldId}" -> "${bestComp.id}" (label="${bestComp.label}", score=${bestScore})`
|
|
3051
3481
|
);
|
|
3052
3482
|
return registry.getField(bestComp.id);
|
|
3053
3483
|
}
|
|
3054
|
-
const currentScreen =
|
|
3484
|
+
const currentScreen = chunkUZ2D4BVX_js.getCurrentScreen();
|
|
3055
3485
|
if (currentScreen) {
|
|
3056
|
-
const screenMeta =
|
|
3486
|
+
const screenMeta = chunkUZ2D4BVX_js.getScreenMetadata(currentScreen);
|
|
3057
3487
|
const fields = screenMeta?.fields;
|
|
3058
3488
|
if (fields && Array.isArray(fields)) {
|
|
3059
3489
|
const metaField = fields.find(
|
|
@@ -3061,19 +3491,19 @@ function findField(fieldId, registry) {
|
|
|
3061
3491
|
);
|
|
3062
3492
|
if (metaField && typeof metaField === "object" && metaField.label) {
|
|
3063
3493
|
const metaLabel = metaField.label;
|
|
3064
|
-
const metaNeedle =
|
|
3494
|
+
const metaNeedle = chunkUZ2D4BVX_js.normalize3(metaLabel);
|
|
3065
3495
|
let mBest;
|
|
3066
3496
|
let mBestScore = 0;
|
|
3067
3497
|
for (const comp of snapshot) {
|
|
3068
3498
|
if (comp.kind !== "field" || !comp.label) continue;
|
|
3069
|
-
const score =
|
|
3499
|
+
const score = chunkUZ2D4BVX_js.matchScore(metaNeedle, chunkUZ2D4BVX_js.normalize3(comp.label));
|
|
3070
3500
|
if (score > mBestScore) {
|
|
3071
3501
|
mBestScore = score;
|
|
3072
3502
|
mBest = comp;
|
|
3073
3503
|
}
|
|
3074
3504
|
}
|
|
3075
3505
|
if (mBest && mBestScore >= 60) {
|
|
3076
|
-
|
|
3506
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
3077
3507
|
`findField: FOUND via screen metadata translation: fieldId="${fieldId}" -> metaLabel="${metaLabel}" -> registered="${mBest.id}" (score=${mBestScore})`
|
|
3078
3508
|
);
|
|
3079
3509
|
return registry.getField(mBest.id);
|
|
@@ -3082,34 +3512,34 @@ function findField(fieldId, registry) {
|
|
|
3082
3512
|
}
|
|
3083
3513
|
}
|
|
3084
3514
|
if (bestComp && bestScore >= 40) {
|
|
3085
|
-
|
|
3515
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
3086
3516
|
`findField: weak substring match "${fieldId}" -> "${bestComp.id}" (label="${bestComp.label}", score=${bestScore})`
|
|
3087
3517
|
);
|
|
3088
3518
|
return registry.getField(bestComp.id);
|
|
3089
3519
|
}
|
|
3090
|
-
|
|
3520
|
+
chunkUZ2D4BVX_js.appilotsDebugWarn(
|
|
3091
3521
|
`findField: NOT FOUND \u2014 fieldId="${fieldId}" not in registry. Available fields: ${snapshot.filter((c) => c.kind === "field").map((c) => `"${c.id}" (label: ${c.label})`).join(", ") || "none"}`
|
|
3092
3522
|
);
|
|
3093
3523
|
return void 0;
|
|
3094
3524
|
}
|
|
3095
3525
|
function findToggle(fieldId, registry) {
|
|
3096
|
-
|
|
3526
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(`findToggle: searching for fieldId="${fieldId}"`);
|
|
3097
3527
|
const exact = registry.getToggle(fieldId);
|
|
3098
3528
|
if (exact) {
|
|
3099
|
-
|
|
3529
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(`findToggle: FOUND exact match for "${fieldId}"`);
|
|
3100
3530
|
return exact;
|
|
3101
3531
|
}
|
|
3102
3532
|
const lower = fieldId.toLowerCase();
|
|
3103
3533
|
const snapshot = registry.snapshot();
|
|
3104
3534
|
for (const comp of snapshot) {
|
|
3105
3535
|
if (comp.kind === "toggle" && comp.id.toLowerCase() === lower) {
|
|
3106
|
-
|
|
3536
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
3107
3537
|
`findToggle: FOUND case-insensitive match: registered="${comp.id}" for searched="${fieldId}"`
|
|
3108
3538
|
);
|
|
3109
3539
|
return registry.getToggle(comp.id);
|
|
3110
3540
|
}
|
|
3111
3541
|
}
|
|
3112
|
-
|
|
3542
|
+
chunkUZ2D4BVX_js.appilotsDebugWarn(
|
|
3113
3543
|
`findToggle: NOT FOUND \u2014 fieldId="${fieldId}" not in registry. Available toggles: ${snapshot.filter((c) => c.kind === "toggle").map((c) => `"${c.id}"`).join(", ") || "none"}`
|
|
3114
3544
|
);
|
|
3115
3545
|
return void 0;
|
|
@@ -3120,7 +3550,7 @@ function findSlider(fieldId, registry) {
|
|
|
3120
3550
|
const lower = fieldId.toLowerCase();
|
|
3121
3551
|
for (const comp of registry.snapshot()) {
|
|
3122
3552
|
if (comp.kind === "slider" && comp.id.toLowerCase() === lower) {
|
|
3123
|
-
|
|
3553
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
3124
3554
|
`findSlider: FOUND case-insensitive match: registered="${comp.id}" for searched="${fieldId}"`
|
|
3125
3555
|
);
|
|
3126
3556
|
return registry.getSlider(comp.id);
|
|
@@ -3128,17 +3558,17 @@ function findSlider(fieldId, registry) {
|
|
|
3128
3558
|
}
|
|
3129
3559
|
return void 0;
|
|
3130
3560
|
}
|
|
3131
|
-
var
|
|
3561
|
+
var sleep3 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
3132
3562
|
async function formFillHandler(payload, context) {
|
|
3133
3563
|
const { permissions } = context;
|
|
3134
|
-
const registry = context.registry ??
|
|
3564
|
+
const registry = context.registry ?? chunkUZ2D4BVX_js.componentRegistry;
|
|
3135
3565
|
const { screen, activePath } = resolveScreenContext();
|
|
3136
3566
|
const screenPath = activePath.length > 1 ? activePath.join("/") : screen;
|
|
3137
3567
|
if (!permissions.canFillForms) {
|
|
3138
3568
|
return {
|
|
3139
3569
|
success: false,
|
|
3140
|
-
error: "Form filling
|
|
3141
|
-
diagnose: { category: "unknown", screen: screenPath }
|
|
3570
|
+
error: chunkUZ2D4BVX_js.permissionDeniedMessage("Form filling", "canFillForms"),
|
|
3571
|
+
diagnose: { category: "unknown", screen: screenPath, recoverable: false }
|
|
3142
3572
|
};
|
|
3143
3573
|
}
|
|
3144
3574
|
if (!payload.fields || payload.fields.length === 0) {
|
|
@@ -3150,11 +3580,11 @@ async function formFillHandler(payload, context) {
|
|
|
3150
3580
|
}
|
|
3151
3581
|
const registrySnapshot = registry.snapshot();
|
|
3152
3582
|
if (registrySnapshot.length === 0) {
|
|
3153
|
-
|
|
3583
|
+
chunkUZ2D4BVX_js.appilotsDebugWarn(
|
|
3154
3584
|
"formFillHandler: registry is EMPTY \u2014 auto-tracking may not be active. Ensure enableAppilotsAutoTracking() runs before components mount."
|
|
3155
3585
|
);
|
|
3156
3586
|
} else {
|
|
3157
|
-
|
|
3587
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
3158
3588
|
`[Appilots formFillHandler] Registry has ${registrySnapshot.length} components:`,
|
|
3159
3589
|
registrySnapshot.map((c) => `${c.kind}:${c.id}`).join(", ")
|
|
3160
3590
|
);
|
|
@@ -3162,7 +3592,7 @@ async function formFillHandler(payload, context) {
|
|
|
3162
3592
|
const fieldResults = [];
|
|
3163
3593
|
let allSuccess = true;
|
|
3164
3594
|
let selectedChoiceThisBatch = false;
|
|
3165
|
-
|
|
3595
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(`formFillHandler: processing ${payload.fields.length} fields`);
|
|
3166
3596
|
const availableFieldIds = () => registry.snapshot().filter((comp) => comp.kind === "field").map((comp) => `${comp.id}${comp.label ? ` (${comp.label})` : ""}`).slice(0, 8);
|
|
3167
3597
|
const isElementIdField = (field) => typeof field.fieldId === "string" && field.fieldId.trim().toLowerCase().startsWith("el:");
|
|
3168
3598
|
for (const field of payload.fields.filter(isElementIdField)) {
|
|
@@ -3189,20 +3619,57 @@ async function formFillHandler(payload, context) {
|
|
|
3189
3619
|
const { fieldId, fieldType, value } = field;
|
|
3190
3620
|
const effectiveFieldType = getEffectiveFieldType(fieldId, fieldType, registry);
|
|
3191
3621
|
let selectFailure;
|
|
3192
|
-
|
|
3193
|
-
`formFillHandler: looking up fieldId="${fieldId}" fieldType="${fieldType}" effectiveFieldType="${effectiveFieldType}" value=${
|
|
3622
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
3623
|
+
`formFillHandler: looking up fieldId="${fieldId}" fieldType="${fieldType}" effectiveFieldType="${effectiveFieldType}" value=${chunkUZ2D4BVX_js.describeValue(value)}`
|
|
3194
3624
|
);
|
|
3195
3625
|
const fieldEntry = findField(fieldId, registry);
|
|
3196
3626
|
if (fieldEntry) {
|
|
3197
3627
|
try {
|
|
3198
|
-
|
|
3628
|
+
const nativeField = findInteractiveByIdentifier(fieldId, { kind: "field" });
|
|
3629
|
+
if (nativeField?.disabled || (nativeField?.matchCount ?? 1) > 1) {
|
|
3630
|
+
fieldResults.push({
|
|
3631
|
+
fieldId,
|
|
3632
|
+
success: false,
|
|
3633
|
+
error: nativeField?.disabled ? "The field is disabled" : "The field identifier matches multiple controls",
|
|
3634
|
+
diagnose: {
|
|
3635
|
+
category: nativeField?.disabled ? "disabled" : "ambiguous-target",
|
|
3636
|
+
fieldId,
|
|
3637
|
+
screen: screenPath
|
|
3638
|
+
}
|
|
3639
|
+
});
|
|
3640
|
+
allSuccess = false;
|
|
3641
|
+
continue;
|
|
3642
|
+
}
|
|
3643
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
3199
3644
|
`formFillHandler: found field "${fieldId}" via registry, calling setValue(<${String(value).length} chars>)`
|
|
3200
3645
|
);
|
|
3201
3646
|
const beforeValue = effectiveFieldType === "date" ? fieldEntry.getValue?.() ?? "" : void 0;
|
|
3202
3647
|
fieldEntry.focus?.();
|
|
3203
3648
|
fieldEntry.setValue(String(value));
|
|
3649
|
+
if (effectiveFieldType === "text" || effectiveFieldType === "number") {
|
|
3650
|
+
if (!await completeTextEdit(
|
|
3651
|
+
fieldId,
|
|
3652
|
+
value,
|
|
3653
|
+
fieldEntry,
|
|
3654
|
+
nativeField,
|
|
3655
|
+
() => findField(fieldId, registry)
|
|
3656
|
+
)) {
|
|
3657
|
+
fieldResults.push({
|
|
3658
|
+
fieldId,
|
|
3659
|
+
success: false,
|
|
3660
|
+
error: "The field did not retain the requested value after editing ended. Inspect its current value before retrying.",
|
|
3661
|
+
diagnose: { category: "validation", fieldId, screen: screenPath }
|
|
3662
|
+
});
|
|
3663
|
+
allSuccess = false;
|
|
3664
|
+
continue;
|
|
3665
|
+
}
|
|
3666
|
+
}
|
|
3204
3667
|
if (effectiveFieldType === "date") {
|
|
3205
|
-
|
|
3668
|
+
let afterValue = fieldEntry.getValue?.() ?? "";
|
|
3669
|
+
if (afterValue === beforeValue) {
|
|
3670
|
+
await sleep3(80);
|
|
3671
|
+
afterValue = fieldEntry.getValue?.() ?? "";
|
|
3672
|
+
}
|
|
3206
3673
|
if (afterValue === beforeValue) {
|
|
3207
3674
|
fieldResults.push({
|
|
3208
3675
|
fieldId,
|
|
@@ -3222,11 +3689,11 @@ async function formFillHandler(payload, context) {
|
|
|
3222
3689
|
if (effectiveFieldType === "select") {
|
|
3223
3690
|
let after = fieldEntry.getValue?.() ?? "";
|
|
3224
3691
|
if (!selectValueApplied(fieldId, value, after, registry)) {
|
|
3225
|
-
await
|
|
3692
|
+
await sleep3(80);
|
|
3226
3693
|
after = fieldEntry.getValue?.() ?? "";
|
|
3227
3694
|
}
|
|
3228
3695
|
if (!selectValueApplied(fieldId, value, after, registry)) {
|
|
3229
|
-
|
|
3696
|
+
chunkUZ2D4BVX_js.appilotsDebugWarn(
|
|
3230
3697
|
`formFillHandler: select field "${fieldId}" setValue did not stick (wrote <${String(value).length} chars>, current is <${String(after ?? "").length} chars>), trying visible choice fallback`
|
|
3231
3698
|
);
|
|
3232
3699
|
const selectResult = await selectVisibleChoice(fieldId, value, registry, {
|
|
@@ -3343,7 +3810,7 @@ async function formFillHandler(payload, context) {
|
|
|
3343
3810
|
if (!selectResult.success && selectedChoiceThisBatch) {
|
|
3344
3811
|
const nextResult = pressContinuationButton(registry);
|
|
3345
3812
|
if (nextResult.success) {
|
|
3346
|
-
await
|
|
3813
|
+
await sleep3(180);
|
|
3347
3814
|
selectResult = await selectVisibleChoice(fieldId, value, registry, {
|
|
3348
3815
|
allowFirstVisibleWhenNoCue: true
|
|
3349
3816
|
});
|
|
@@ -3351,24 +3818,50 @@ async function formFillHandler(payload, context) {
|
|
|
3351
3818
|
}
|
|
3352
3819
|
if (selectResult.success) {
|
|
3353
3820
|
selectedChoiceThisBatch = true;
|
|
3354
|
-
|
|
3821
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
3355
3822
|
`formFillHandler: selected visible option for "${fieldId}"` + (selectResult.selectedLabel ? ` \u2192 "${selectResult.selectedLabel}"` : "")
|
|
3356
3823
|
);
|
|
3357
|
-
await
|
|
3824
|
+
await sleep3(120);
|
|
3358
3825
|
fieldResults.push({ fieldId, success: true });
|
|
3359
3826
|
continue;
|
|
3360
3827
|
}
|
|
3361
3828
|
selectFailure = selectResult;
|
|
3362
3829
|
}
|
|
3363
|
-
|
|
3830
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(`formFillHandler: registry miss for "${fieldId}", falling back to fiber tree`);
|
|
3364
3831
|
const handle = findInteractiveByIdentifier(fieldId, {
|
|
3365
3832
|
kind: effectiveFieldType === "toggle" ? "toggle" : "field"
|
|
3366
3833
|
});
|
|
3367
3834
|
if (handle?.setValue) {
|
|
3368
3835
|
try {
|
|
3836
|
+
if (handle.disabled || (handle.matchCount ?? 1) > 1) {
|
|
3837
|
+
fieldResults.push({
|
|
3838
|
+
fieldId,
|
|
3839
|
+
success: false,
|
|
3840
|
+
error: handle.disabled ? "The field is disabled" : "The field identifier matches multiple controls",
|
|
3841
|
+
diagnose: {
|
|
3842
|
+
category: handle.disabled ? "disabled" : "ambiguous-target",
|
|
3843
|
+
fieldId,
|
|
3844
|
+
screen: screenPath,
|
|
3845
|
+
candidates: handle.matchCandidates
|
|
3846
|
+
}
|
|
3847
|
+
});
|
|
3848
|
+
allSuccess = false;
|
|
3849
|
+
continue;
|
|
3850
|
+
}
|
|
3851
|
+
setSpotlightTarget(handle.measure?.() ?? null, handle.label);
|
|
3369
3852
|
handle.focus?.();
|
|
3370
3853
|
handle.setValue(value);
|
|
3371
|
-
|
|
3854
|
+
if (handle.kind === "field" && !await completeTextEdit(fieldId, value, void 0, handle)) {
|
|
3855
|
+
fieldResults.push({
|
|
3856
|
+
fieldId,
|
|
3857
|
+
success: false,
|
|
3858
|
+
error: "The field did not retain the requested value after editing ended. Inspect its current value before retrying.",
|
|
3859
|
+
diagnose: { category: "validation", fieldId, screen: screenPath }
|
|
3860
|
+
});
|
|
3861
|
+
allSuccess = false;
|
|
3862
|
+
continue;
|
|
3863
|
+
}
|
|
3864
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
3372
3865
|
`formFillHandler: fiber fallback succeeded for "${fieldId}" \u2192 label="${handle.label}"`
|
|
3373
3866
|
);
|
|
3374
3867
|
fieldResults.push({ fieldId, success: true });
|
|
@@ -3405,13 +3898,25 @@ async function formFillHandler(payload, context) {
|
|
|
3405
3898
|
allSuccess = false;
|
|
3406
3899
|
}
|
|
3407
3900
|
if (payload.submitAfterFill === true) {
|
|
3901
|
+
if (!permissions.canSubmitForms) {
|
|
3902
|
+
return {
|
|
3903
|
+
success: false,
|
|
3904
|
+
error: "Form submission is not permitted",
|
|
3905
|
+
fieldResults,
|
|
3906
|
+
diagnose: { category: "unknown", screen: screenPath }
|
|
3907
|
+
};
|
|
3908
|
+
}
|
|
3408
3909
|
if (!allSuccess) {
|
|
3409
3910
|
const failedIds = fieldResults.filter((result) => !result.success).map((result) => result.fieldId);
|
|
3410
|
-
|
|
3911
|
+
chunkUZ2D4BVX_js.appilotsDebugWarn(
|
|
3411
3912
|
"formFillHandler: submitAfterFill=true requested but some fields failed; NOT submitting" + (failedIds.length > 0 ? ` (failed: ${failedIds.join(", ")})` : "")
|
|
3412
3913
|
);
|
|
3413
3914
|
} else {
|
|
3414
|
-
await
|
|
3915
|
+
await sleep3(120);
|
|
3916
|
+
if (!permissions.canSubmitForms) {
|
|
3917
|
+
return { success: false, error: "Form submission is not permitted", fieldResults };
|
|
3918
|
+
}
|
|
3919
|
+
const beforeSubmitTexts = captureSnapshot().texts;
|
|
3415
3920
|
const submitResult = pressSubmitButton(
|
|
3416
3921
|
{
|
|
3417
3922
|
screen,
|
|
@@ -3422,7 +3927,7 @@ async function formFillHandler(payload, context) {
|
|
|
3422
3927
|
registry
|
|
3423
3928
|
);
|
|
3424
3929
|
if (!submitResult.success) {
|
|
3425
|
-
|
|
3930
|
+
chunkUZ2D4BVX_js.appilotsDebugWarn(`formFillHandler: submitAfterFill failed \u2014 ${submitResult.error}`);
|
|
3426
3931
|
return {
|
|
3427
3932
|
success: false,
|
|
3428
3933
|
error: submitResult.error,
|
|
@@ -3431,10 +3936,11 @@ async function formFillHandler(payload, context) {
|
|
|
3431
3936
|
};
|
|
3432
3937
|
}
|
|
3433
3938
|
const postSubmit = await waitForPostSubmitOutcome({
|
|
3434
|
-
submitTargetId: submitResult.pressedTargetId
|
|
3939
|
+
submitTargetId: submitResult.pressedTargetId,
|
|
3940
|
+
beforeTexts: beforeSubmitTexts
|
|
3435
3941
|
});
|
|
3436
3942
|
if (postSubmit.status === "pending") {
|
|
3437
|
-
|
|
3943
|
+
chunkUZ2D4BVX_js.appilotsDebugWarn(`formFillHandler: submit still pending \u2014 ${postSubmit.message}`);
|
|
3438
3944
|
return {
|
|
3439
3945
|
success: false,
|
|
3440
3946
|
error: postSubmit.message,
|
|
@@ -3443,7 +3949,7 @@ async function formFillHandler(payload, context) {
|
|
|
3443
3949
|
};
|
|
3444
3950
|
}
|
|
3445
3951
|
if (postSubmit.status === "failure") {
|
|
3446
|
-
|
|
3952
|
+
chunkUZ2D4BVX_js.appilotsDebugWarn(
|
|
3447
3953
|
`formFillHandler: submit rejected by visible validation \u2014 ${postSubmit.message}`
|
|
3448
3954
|
);
|
|
3449
3955
|
return {
|
|
@@ -3458,7 +3964,10 @@ async function formFillHandler(payload, context) {
|
|
|
3458
3964
|
}
|
|
3459
3965
|
};
|
|
3460
3966
|
}
|
|
3461
|
-
|
|
3967
|
+
if (postSubmit.status === "unverified") {
|
|
3968
|
+
return { success: true, fieldResults, effect: "unknown" };
|
|
3969
|
+
}
|
|
3970
|
+
chunkUZ2D4BVX_js.appilotsDebugLog("formFillHandler: submitAfterFill \u2014 submit completed");
|
|
3462
3971
|
}
|
|
3463
3972
|
}
|
|
3464
3973
|
const aggregatedDiagnose = aggregateFieldDiagnoses(fieldResults, screenPath);
|
|
@@ -3470,17 +3979,17 @@ async function formFillHandler(payload, context) {
|
|
|
3470
3979
|
};
|
|
3471
3980
|
}
|
|
3472
3981
|
function pressSubmitButton(context, registry) {
|
|
3473
|
-
const activePath = context.activePath ??
|
|
3982
|
+
const activePath = context.activePath ?? chunkUZ2D4BVX_js.getActiveRouteNames();
|
|
3474
3983
|
const hintScreen = context.screen ?? context.screenPath;
|
|
3475
3984
|
const formScreens = resolveFormScreensForSubmit(hintScreen, activePath, registry);
|
|
3476
|
-
const resolvedScreen = formScreens.find((name) => screenDeclaresSubmit(name)) ?? formScreens[0] ?? hintScreen ??
|
|
3985
|
+
const resolvedScreen = formScreens.find((name) => screenDeclaresSubmit(name)) ?? formScreens[0] ?? hintScreen ?? chunkUZ2D4BVX_js.getCurrentScreen() ?? void 0;
|
|
3477
3986
|
const candidates = collectSubmitTargetCandidates(formScreens, registry);
|
|
3478
3987
|
for (const candidate of candidates) {
|
|
3479
3988
|
const target = registry.getTarget(candidate);
|
|
3480
3989
|
if (target) {
|
|
3481
3990
|
try {
|
|
3482
3991
|
target.press();
|
|
3483
|
-
|
|
3992
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
3484
3993
|
`formFillHandler: submitAfterFill \u2014 pressed registry target "${candidate}"` + (resolvedScreen ? ` on screen "${resolvedScreen}"` : "")
|
|
3485
3994
|
);
|
|
3486
3995
|
return { success: true, pressedTargetId: candidate };
|
|
@@ -3494,7 +4003,7 @@ function pressSubmitButton(context, registry) {
|
|
|
3494
4003
|
}
|
|
3495
4004
|
}
|
|
3496
4005
|
for (const screenName of formScreens) {
|
|
3497
|
-
const screenMeta =
|
|
4006
|
+
const screenMeta = chunkUZ2D4BVX_js.getScreenMetadata(screenName);
|
|
3498
4007
|
const submitMeta = Array.isArray(screenMeta?.actions) ? screenMeta.actions.find(
|
|
3499
4008
|
(action) => typeof action === "object" && action !== null && action.type === "submit"
|
|
3500
4009
|
) : void 0;
|
|
@@ -3505,7 +4014,7 @@ function pressSubmitButton(context, registry) {
|
|
|
3505
4014
|
if (handle?.press) {
|
|
3506
4015
|
try {
|
|
3507
4016
|
handle.press();
|
|
3508
|
-
|
|
4017
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(`formFillHandler: submitAfterFill \u2014 fiber fallback "${submitLabel}"`);
|
|
3509
4018
|
return { success: true, pressedTargetId: submitId ?? submitLabel };
|
|
3510
4019
|
} catch (err) {
|
|
3511
4020
|
return {
|
|
@@ -3527,7 +4036,7 @@ function pressSubmitButton(context, registry) {
|
|
|
3527
4036
|
if (id) {
|
|
3528
4037
|
const pressed = pressTargetByIdOrLabel(id, registry);
|
|
3529
4038
|
if (pressed.success) {
|
|
3530
|
-
|
|
4039
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(`formFillHandler: submitAfterFill \u2014 pressed visible heuristic "${id}"`);
|
|
3531
4040
|
return { success: true, pressedTargetId: id };
|
|
3532
4041
|
}
|
|
3533
4042
|
}
|
|
@@ -3541,7 +4050,7 @@ function pressSubmitButton(context, registry) {
|
|
|
3541
4050
|
if (target) {
|
|
3542
4051
|
try {
|
|
3543
4052
|
target.press();
|
|
3544
|
-
|
|
4053
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
3545
4054
|
`formFillHandler: submitAfterFill \u2014 pressed by label heuristic "${comp.label}"`
|
|
3546
4055
|
);
|
|
3547
4056
|
return { success: true, pressedTargetId: comp.id };
|
|
@@ -3557,7 +4066,7 @@ function pressSubmitButton(context, registry) {
|
|
|
3557
4066
|
for (const fieldId of [...context.filledFieldIds ?? []].reverse()) {
|
|
3558
4067
|
const handle = findInteractiveByIdentifier(fieldId, { kind: "field" });
|
|
3559
4068
|
if (handle?.submitFromKeyboard?.()) {
|
|
3560
|
-
|
|
4069
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(`formFillHandler: submitAfterFill \u2014 return key on "${fieldId}"`);
|
|
3561
4070
|
return { success: true, pressedTargetId: fieldId };
|
|
3562
4071
|
}
|
|
3563
4072
|
}
|
|
@@ -3595,7 +4104,21 @@ function aggregateFieldDiagnoses(results, screen) {
|
|
|
3595
4104
|
var FALLBACK_PAGE_PX = 600;
|
|
3596
4105
|
var PAGE_FRACTION = 0.85;
|
|
3597
4106
|
var POST_SCROLL_MOUNT_MS = 400;
|
|
3598
|
-
var
|
|
4107
|
+
var PAGINATION_MAX_WAIT_MS = 4e3;
|
|
4108
|
+
var PAGINATION_POLL_MS = 150;
|
|
4109
|
+
var sleep4 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
4110
|
+
async function settleAfterScroll() {
|
|
4111
|
+
await sleep4(POST_SCROLL_MOUNT_MS);
|
|
4112
|
+
if (!chunkUZ2D4BVX_js.probeLoadingState(void 0, chunkUZ2D4BVX_js.getCurrentScreen()).loading) return;
|
|
4113
|
+
const deadline = Date.now() + PAGINATION_MAX_WAIT_MS;
|
|
4114
|
+
while (Date.now() < deadline) {
|
|
4115
|
+
await sleep4(PAGINATION_POLL_MS);
|
|
4116
|
+
if (!chunkUZ2D4BVX_js.probeLoadingState(void 0, chunkUZ2D4BVX_js.getCurrentScreen()).loading) {
|
|
4117
|
+
await sleep4(POST_SCROLL_MOUNT_MS);
|
|
4118
|
+
return;
|
|
4119
|
+
}
|
|
4120
|
+
}
|
|
4121
|
+
}
|
|
3599
4122
|
function normalizeId2(value) {
|
|
3600
4123
|
return String(value ?? "").toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "");
|
|
3601
4124
|
}
|
|
@@ -3603,12 +4126,12 @@ function buildDiagnose(category, targetId, candidates) {
|
|
|
3603
4126
|
return {
|
|
3604
4127
|
category,
|
|
3605
4128
|
targetId,
|
|
3606
|
-
screen:
|
|
4129
|
+
screen: chunkUZ2D4BVX_js.getCurrentScreen() ?? void 0,
|
|
3607
4130
|
...candidates && candidates.length > 0 ? { candidates: candidates.slice(0, 8) } : {}
|
|
3608
4131
|
};
|
|
3609
4132
|
}
|
|
3610
4133
|
function resolveListEntry(listId) {
|
|
3611
|
-
const entries =
|
|
4134
|
+
const entries = chunkUZ2D4BVX_js.listRegistry.snapshot();
|
|
3612
4135
|
if (entries.length === 0) return {};
|
|
3613
4136
|
if (listId) {
|
|
3614
4137
|
const wanted = normalizeId2(listId);
|
|
@@ -3631,13 +4154,26 @@ function pageOffset(metrics, direction) {
|
|
|
3631
4154
|
}
|
|
3632
4155
|
return next;
|
|
3633
4156
|
}
|
|
4157
|
+
async function finishScroll(entry, before) {
|
|
4158
|
+
await settleAfterScroll();
|
|
4159
|
+
const current2 = chunkUZ2D4BVX_js.listRegistry.get(entry.id) ?? entry;
|
|
4160
|
+
const after = current2.getScrollMetrics?.();
|
|
4161
|
+
const grew = typeof entry.itemCount === "number" && typeof current2.itemCount === "number" && current2.itemCount > entry.itemCount;
|
|
4162
|
+
const moved = grew || !!(before && after && (Math.abs(after.offset - before.offset) > 2 || after.contentLength > before.contentLength + 2));
|
|
4163
|
+
const outcome = moved ? "moved" : before && after ? "no-progress" : "unverified";
|
|
4164
|
+
current2.exploration?.recordScroll(outcome);
|
|
4165
|
+
return {
|
|
4166
|
+
success: true,
|
|
4167
|
+
effect: moved ? "changed" : outcome === "no-progress" ? "none" : "unknown"
|
|
4168
|
+
};
|
|
4169
|
+
}
|
|
3634
4170
|
async function scrollListHandler(payload, context) {
|
|
3635
4171
|
const { permissions } = context;
|
|
3636
4172
|
if (!permissions.canInteractUI) {
|
|
3637
4173
|
return {
|
|
3638
4174
|
success: false,
|
|
3639
|
-
error: "UI interaction
|
|
3640
|
-
diagnose: buildDiagnose("unknown", payload.listId)
|
|
4175
|
+
error: chunkUZ2D4BVX_js.permissionDeniedMessage("UI interaction", "canInteractUI"),
|
|
4176
|
+
diagnose: { ...buildDiagnose("unknown", payload.listId), recoverable: false }
|
|
3641
4177
|
};
|
|
3642
4178
|
}
|
|
3643
4179
|
const toIndex = typeof payload.toIndex === "number" ? payload.toIndex : void 0;
|
|
@@ -3665,6 +4201,15 @@ async function scrollListHandler(payload, context) {
|
|
|
3665
4201
|
diagnose: buildDiagnose("component-not-found", payload.listId, candidates)
|
|
3666
4202
|
};
|
|
3667
4203
|
}
|
|
4204
|
+
const exploration = entry.exploration?.snapshot();
|
|
4205
|
+
if (exploration && (exploration.remainingScrollSteps === 0 || exploration.consecutiveNoProgress >= 2)) {
|
|
4206
|
+
return {
|
|
4207
|
+
success: false,
|
|
4208
|
+
effect: "none",
|
|
4209
|
+
error: "List exploration stopped: scroll budget exhausted or repeated no progress. Use the current loaded count/coverage and report any remaining uncertainty; do not repeat this scroll.",
|
|
4210
|
+
diagnose: { ...buildDiagnose("validation", entry.id), recoverable: false }
|
|
4211
|
+
};
|
|
4212
|
+
}
|
|
3668
4213
|
if (toIndex !== void 0) {
|
|
3669
4214
|
if (entry.kind === "scroll") {
|
|
3670
4215
|
return {
|
|
@@ -3680,17 +4225,16 @@ async function scrollListHandler(payload, context) {
|
|
|
3680
4225
|
diagnose: buildDiagnose("validation", entry.id)
|
|
3681
4226
|
};
|
|
3682
4227
|
}
|
|
4228
|
+
const before = entry.getScrollMetrics?.();
|
|
3683
4229
|
const zeroBased = toIndex - 1;
|
|
3684
4230
|
if (entry.scrollToIndex?.(zeroBased)) {
|
|
3685
|
-
|
|
3686
|
-
return { success: true };
|
|
4231
|
+
return finishScroll(entry, before);
|
|
3687
4232
|
}
|
|
3688
4233
|
const metrics2 = entry.getScrollMetrics?.();
|
|
3689
4234
|
if (metrics2 && metrics2.contentLength > 0 && typeof entry.itemCount === "number" && entry.itemCount > 0) {
|
|
3690
4235
|
const estimated = zeroBased / entry.itemCount * metrics2.contentLength;
|
|
3691
4236
|
if (entry.scrollToOffset?.(Math.max(0, estimated))) {
|
|
3692
|
-
|
|
3693
|
-
return { success: true };
|
|
4237
|
+
return finishScroll(entry, before);
|
|
3694
4238
|
}
|
|
3695
4239
|
}
|
|
3696
4240
|
return {
|
|
@@ -3700,10 +4244,21 @@ async function scrollListHandler(payload, context) {
|
|
|
3700
4244
|
};
|
|
3701
4245
|
}
|
|
3702
4246
|
const metrics = entry.getScrollMetrics?.();
|
|
4247
|
+
if (!metrics && exploration?.lastScroll === "unverified") {
|
|
4248
|
+
return {
|
|
4249
|
+
success: false,
|
|
4250
|
+
effect: "unknown",
|
|
4251
|
+
error: "Scroll offset is still unavailable after one probe. Cannot safely page again; do not infer the end or repeat the same absolute offset.",
|
|
4252
|
+
diagnose: { ...buildDiagnose("validation", entry.id), recoverable: false }
|
|
4253
|
+
};
|
|
4254
|
+
}
|
|
3703
4255
|
const target = pageOffset(metrics, direction);
|
|
4256
|
+
if (metrics && Math.abs(target - metrics.offset) <= 2) {
|
|
4257
|
+
entry.exploration?.recordScroll("boundary");
|
|
4258
|
+
return { success: true, effect: "none" };
|
|
4259
|
+
}
|
|
3704
4260
|
if (entry.scrollToOffset?.(target)) {
|
|
3705
|
-
|
|
3706
|
-
return { success: true };
|
|
4261
|
+
return finishScroll(entry, metrics);
|
|
3707
4262
|
}
|
|
3708
4263
|
return {
|
|
3709
4264
|
success: false,
|
|
@@ -3717,6 +4272,59 @@ async function confirmHandler(_actionId, _payload) {
|
|
|
3717
4272
|
return { success: true, effect: "unknown" };
|
|
3718
4273
|
}
|
|
3719
4274
|
|
|
4275
|
+
// src/platform/asyncBudget.ts
|
|
4276
|
+
var POST_ACTION_LOADING_MAX_MS = 6e3;
|
|
4277
|
+
var INFERRED_ASYNC_LOADING_MAX_MS = 1e4;
|
|
4278
|
+
var POST_NAVIGATE_LOADING_MAX_MS = 3e3;
|
|
4279
|
+
var MAX_DECLARED_ASYNC_BUDGET_MS = 12e4;
|
|
4280
|
+
var ASYNC_BUSY_CEILING_MS = MAX_DECLARED_ASYNC_BUDGET_MS;
|
|
4281
|
+
function declaredBudgetMs(hints) {
|
|
4282
|
+
const declared = hints?.asyncBudgetMs;
|
|
4283
|
+
if (typeof declared !== "number" || !Number.isFinite(declared) || declared <= 0) return void 0;
|
|
4284
|
+
return Math.min(declared, MAX_DECLARED_ASYNC_BUDGET_MS);
|
|
4285
|
+
}
|
|
4286
|
+
function resolveSettleCapMs(hints) {
|
|
4287
|
+
const declared = declaredBudgetMs(hints);
|
|
4288
|
+
if (declared !== void 0) return declared;
|
|
4289
|
+
return hints?.isAsyncTrigger === true ? INFERRED_ASYNC_LOADING_MAX_MS : POST_ACTION_LOADING_MAX_MS;
|
|
4290
|
+
}
|
|
4291
|
+
function resolveBusyCeilingMs(hints) {
|
|
4292
|
+
return declaredBudgetMs(hints) === void 0 ? ASYNC_BUSY_CEILING_MS : void 0;
|
|
4293
|
+
}
|
|
4294
|
+
function resolvePostNavigateCapMs(hints) {
|
|
4295
|
+
return Math.max(POST_NAVIGATE_LOADING_MAX_MS, declaredBudgetMs(hints) ?? 0);
|
|
4296
|
+
}
|
|
4297
|
+
function resolveActionHints(screen, pressedComponentId, actionPayload) {
|
|
4298
|
+
if (actionPayload && typeof actionPayload === "object") {
|
|
4299
|
+
const payload = actionPayload;
|
|
4300
|
+
const inline = payload._appilotsInferred;
|
|
4301
|
+
const declared = payload._appilotsAsyncBudgetMs;
|
|
4302
|
+
if (inline && typeof inline === "object") {
|
|
4303
|
+
const hints = { ...inline };
|
|
4304
|
+
if (typeof declared === "number") hints.asyncBudgetMs = declared;
|
|
4305
|
+
return hints;
|
|
4306
|
+
}
|
|
4307
|
+
if (typeof declared === "number") return { asyncBudgetMs: declared };
|
|
4308
|
+
}
|
|
4309
|
+
if (!screen || !pressedComponentId) return void 0;
|
|
4310
|
+
const meta = chunkUZ2D4BVX_js.getScreenMetadata(screen);
|
|
4311
|
+
const actions = meta?.actions;
|
|
4312
|
+
if (!actions || actions.length === 0) return void 0;
|
|
4313
|
+
for (const a of actions) {
|
|
4314
|
+
if (typeof a === "string") continue;
|
|
4315
|
+
if (chunkUZ2D4BVX_js.idLooselyMatches(a.id, pressedComponentId)) {
|
|
4316
|
+
const inferred = a.appilotsInferred;
|
|
4317
|
+
const declared = a.asyncBudgetMs;
|
|
4318
|
+
const hints = {
|
|
4319
|
+
...inferred && typeof inferred === "object" ? inferred : {},
|
|
4320
|
+
...typeof declared === "number" ? { asyncBudgetMs: declared } : {}
|
|
4321
|
+
};
|
|
4322
|
+
return Object.keys(hints).length > 0 ? hints : void 0;
|
|
4323
|
+
}
|
|
4324
|
+
}
|
|
4325
|
+
return void 0;
|
|
4326
|
+
}
|
|
4327
|
+
|
|
3720
4328
|
// src/executor/postInteractionSettle.ts
|
|
3721
4329
|
var sleepMs = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
3722
4330
|
function targetIdFromPayload(payload) {
|
|
@@ -3734,12 +4342,12 @@ function hashFieldValue(value) {
|
|
|
3734
4342
|
}
|
|
3735
4343
|
return (hash >>> 0).toString(36);
|
|
3736
4344
|
}
|
|
3737
|
-
var DISCRETE_FIELD_TYPES = /* @__PURE__ */ new Set(["select", "date"]);
|
|
4345
|
+
var DISCRETE_FIELD_TYPES = /* @__PURE__ */ new Set(["select", "date", "number"]);
|
|
3738
4346
|
function discreteFieldSignature() {
|
|
3739
4347
|
const sigs = [];
|
|
3740
|
-
for (const { id, kind } of
|
|
4348
|
+
for (const { id, kind } of chunkUZ2D4BVX_js.componentRegistry.snapshot()) {
|
|
3741
4349
|
if (kind !== "field") continue;
|
|
3742
|
-
const entry =
|
|
4350
|
+
const entry = chunkUZ2D4BVX_js.componentRegistry.getField(id);
|
|
3743
4351
|
if (!entry || !DISCRETE_FIELD_TYPES.has(entry.fieldType ?? "")) continue;
|
|
3744
4352
|
try {
|
|
3745
4353
|
sigs.push(`${id}:${hashFieldValue(String(entry.getValue() ?? ""))}`);
|
|
@@ -3748,34 +4356,46 @@ function discreteFieldSignature() {
|
|
|
3748
4356
|
}
|
|
3749
4357
|
return sigs.sort().join(",");
|
|
3750
4358
|
}
|
|
3751
|
-
|
|
4359
|
+
function capturePreInteractionBaseline(payload) {
|
|
4360
|
+
const targetId = targetIdFromPayload(payload);
|
|
4361
|
+
const screen = chunkUZ2D4BVX_js.getCurrentScreen();
|
|
4362
|
+
const probe = chunkUZ2D4BVX_js.probeLoadingState(targetId || null, screen);
|
|
4363
|
+
return {
|
|
4364
|
+
fingerprint: probe.fingerprint,
|
|
4365
|
+
fields: discreteFieldSignature(),
|
|
4366
|
+
screen,
|
|
4367
|
+
readable: probe.fingerprint !== ""
|
|
4368
|
+
};
|
|
4369
|
+
}
|
|
4370
|
+
async function waitForPostInteractionSettle(payload, preBaseline) {
|
|
3752
4371
|
const targetId = targetIdFromPayload(payload);
|
|
3753
|
-
const
|
|
3754
|
-
const
|
|
3755
|
-
const baselineFields =
|
|
3756
|
-
const readable = baseline.
|
|
4372
|
+
const baseline = preBaseline ?? capturePreInteractionBaseline(payload);
|
|
4373
|
+
const fromScreen = baseline.screen;
|
|
4374
|
+
const baselineFields = baseline.fields;
|
|
4375
|
+
const readable = baseline.readable;
|
|
3757
4376
|
await sleepMs(100);
|
|
3758
|
-
const afterPress =
|
|
4377
|
+
const afterPress = chunkUZ2D4BVX_js.probeLoadingState(targetId || null, chunkUZ2D4BVX_js.getCurrentScreen());
|
|
3759
4378
|
const modalOrLoading = afterPress.modalOpen || afterPress.loading || afterPress.pressedDisabled;
|
|
3760
4379
|
const fingerprintChanged = afterPress.fingerprint !== baseline.fingerprint;
|
|
3761
4380
|
const verdict = () => {
|
|
3762
4381
|
if (!readable) return { effect: "unknown" };
|
|
3763
|
-
const settled =
|
|
4382
|
+
const settled = chunkUZ2D4BVX_js.probeLoadingState(targetId || null, chunkUZ2D4BVX_js.getCurrentScreen());
|
|
3764
4383
|
if (settled.fingerprint === "") return { effect: "unknown" };
|
|
3765
4384
|
if (discreteFieldSignature() !== baselineFields) return { effect: "changed" };
|
|
3766
4385
|
return { effect: settled.fingerprint !== baseline.fingerprint ? "changed" : "none" };
|
|
3767
4386
|
};
|
|
3768
|
-
const
|
|
4387
|
+
const declared = declaredBudgetMs(resolveActionHints(fromScreen, targetId || null, payload));
|
|
4388
|
+
const capMs = declared ?? (chunkUZ2D4BVX_js.isListItemPressTarget(targetId) ? 5e3 : 1e4);
|
|
3769
4389
|
if (modalOrLoading || fingerprintChanged) {
|
|
3770
|
-
await
|
|
4390
|
+
await chunkUZ2D4BVX_js.waitForLoadingSettle({
|
|
3771
4391
|
pressedComponentId: targetId || null,
|
|
3772
4392
|
fromScreen,
|
|
3773
4393
|
maxMs: capMs
|
|
3774
4394
|
});
|
|
3775
4395
|
return verdict();
|
|
3776
4396
|
}
|
|
3777
|
-
if (
|
|
3778
|
-
await
|
|
4397
|
+
if (chunkUZ2D4BVX_js.isListItemPressTarget(targetId)) {
|
|
4398
|
+
await chunkUZ2D4BVX_js.waitForLoadingSettle({
|
|
3779
4399
|
fromScreen,
|
|
3780
4400
|
maxMs: 3e3
|
|
3781
4401
|
});
|
|
@@ -3784,19 +4404,13 @@ async function waitForPostInteractionSettle(payload) {
|
|
|
3784
4404
|
}
|
|
3785
4405
|
|
|
3786
4406
|
// src/executor/ActionExecutor.ts
|
|
3787
|
-
var DEFAULT_PERMISSIONS = {
|
|
3788
|
-
canNavigate: true,
|
|
3789
|
-
canFillForms: true,
|
|
3790
|
-
canInteractUI: true,
|
|
3791
|
-
canSubmitForms: true
|
|
3792
|
-
};
|
|
3793
4407
|
function validateActionPayload(action) {
|
|
3794
4408
|
const invalid = (message, ids) => ({
|
|
3795
4409
|
success: false,
|
|
3796
4410
|
error: message,
|
|
3797
4411
|
diagnose: {
|
|
3798
4412
|
category: "validation",
|
|
3799
|
-
screen:
|
|
4413
|
+
screen: chunkUZ2D4BVX_js.getCurrentScreen() ?? void 0,
|
|
3800
4414
|
...ids ?? {}
|
|
3801
4415
|
}
|
|
3802
4416
|
});
|
|
@@ -3857,10 +4471,10 @@ function isDestructivePayload(payload) {
|
|
|
3857
4471
|
return !!params && typeof params === "object" && params.destructive === true;
|
|
3858
4472
|
}
|
|
3859
4473
|
async function executeAction(action, context) {
|
|
3860
|
-
|
|
4474
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
3861
4475
|
`executeAction called: type="${action.type}", id="${action.id}", payload=${JSON.stringify(action.payload)}`
|
|
3862
4476
|
);
|
|
3863
|
-
const permissions = context.permissions
|
|
4477
|
+
const permissions = chunkUZ2D4BVX_js.resolveAgentPermissions(context.permissions);
|
|
3864
4478
|
context.emit({
|
|
3865
4479
|
type: "agent:action:start",
|
|
3866
4480
|
timestamp: Date.now(),
|
|
@@ -3886,7 +4500,7 @@ async function executeAction(action, context) {
|
|
|
3886
4500
|
let result;
|
|
3887
4501
|
const validationFailure = validateActionPayload(action);
|
|
3888
4502
|
if (validationFailure) {
|
|
3889
|
-
|
|
4503
|
+
chunkUZ2D4BVX_js.appilotsDebugWarn(
|
|
3890
4504
|
`executeAction: payload validation failed for type="${action.type}" id="${action.id}": ${validationFailure.error}`
|
|
3891
4505
|
);
|
|
3892
4506
|
context.emit({
|
|
@@ -3913,17 +4527,18 @@ async function executeAction(action, context) {
|
|
|
3913
4527
|
case "form_fill":
|
|
3914
4528
|
result = await formFillHandler(action.payload, {
|
|
3915
4529
|
permissions,
|
|
3916
|
-
registry: context.registry ??
|
|
4530
|
+
registry: context.registry ?? chunkUZ2D4BVX_js.getDefaultRegistry()
|
|
3917
4531
|
});
|
|
3918
4532
|
break;
|
|
3919
4533
|
case "ui_interaction": {
|
|
3920
4534
|
const payload = action.payload;
|
|
4535
|
+
const baseline = capturePreInteractionBaseline(payload);
|
|
3921
4536
|
result = uiInteractionHandler(payload, {
|
|
3922
4537
|
permissions,
|
|
3923
|
-
registry: context.registry ??
|
|
4538
|
+
registry: context.registry ?? chunkUZ2D4BVX_js.getDefaultRegistry()
|
|
3924
4539
|
});
|
|
3925
4540
|
if (result.success) {
|
|
3926
|
-
const settle = await waitForPostInteractionSettle(payload);
|
|
4541
|
+
const settle = await waitForPostInteractionSettle(payload, baseline);
|
|
3927
4542
|
result.effect = result.effect ?? effectFor(payload, settle.effect);
|
|
3928
4543
|
}
|
|
3929
4544
|
break;
|
|
@@ -3949,7 +4564,7 @@ async function executeAction(action, context) {
|
|
|
3949
4564
|
};
|
|
3950
4565
|
}
|
|
3951
4566
|
} catch (err) {
|
|
3952
|
-
|
|
4567
|
+
chunkUZ2D4BVX_js.appilotsDebugWarn(
|
|
3953
4568
|
`executeAction: exception during action type="${action.type}" id="${action.id}": ${err?.message}`
|
|
3954
4569
|
);
|
|
3955
4570
|
result = {
|
|
@@ -3957,7 +4572,7 @@ async function executeAction(action, context) {
|
|
|
3957
4572
|
error: err?.message ?? "Action execution failed unexpectedly"
|
|
3958
4573
|
};
|
|
3959
4574
|
}
|
|
3960
|
-
|
|
4575
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
3961
4576
|
`executeAction result: type="${action.type}", id="${action.id}", success=${result.success}, error=${result.error ?? "none"}`
|
|
3962
4577
|
);
|
|
3963
4578
|
context.emit({
|
|
@@ -4011,18 +4626,28 @@ var _patchedAlert = (title, message, buttons, options) => {
|
|
|
4011
4626
|
return suppression.originalAlert(title, message, buttons, options);
|
|
4012
4627
|
}
|
|
4013
4628
|
suppression.consumed = true;
|
|
4014
|
-
|
|
4629
|
+
const report = (handlerCompleted) => suppression.onHandled?.({
|
|
4630
|
+
title: title.slice(0, 300),
|
|
4631
|
+
message: message?.slice(0, 1e3),
|
|
4632
|
+
buttonLabel: button.text?.slice(0, 160),
|
|
4633
|
+
handlerCompleted
|
|
4634
|
+
});
|
|
4635
|
+
chunkUZ2D4BVX_js.appilotsDebugLog("Suppressing native Alert during already-confirmed destructive agent action");
|
|
4015
4636
|
try {
|
|
4016
|
-
suppression.pending = Promise.resolve(button.onPress()).then(() =>
|
|
4637
|
+
suppression.pending = Promise.resolve(button.onPress()).then(() => report(true)).catch((err) => {
|
|
4638
|
+
reportHandlerFailure(err);
|
|
4639
|
+
report(false);
|
|
4640
|
+
});
|
|
4017
4641
|
} catch (err) {
|
|
4018
4642
|
reportHandlerFailure(err);
|
|
4019
4643
|
suppression.pending = null;
|
|
4644
|
+
report(false);
|
|
4020
4645
|
}
|
|
4021
4646
|
};
|
|
4022
4647
|
function reportHandlerFailure(err) {
|
|
4023
4648
|
console.error("[Appilots] The app\u2019s Alert handler threw while being auto-confirmed", err);
|
|
4024
4649
|
}
|
|
4025
|
-
async function runWithConfirmedDestructiveContext(enabled, host, fn) {
|
|
4650
|
+
async function runWithConfirmedDestructiveContext(enabled, host, fn, onHandled) {
|
|
4026
4651
|
if (!enabled) return fn();
|
|
4027
4652
|
if (_active) {
|
|
4028
4653
|
_active.depth += 1;
|
|
@@ -4043,6 +4668,7 @@ async function runWithConfirmedDestructiveContext(enabled, host, fn) {
|
|
|
4043
4668
|
depth: 1,
|
|
4044
4669
|
consumed: false,
|
|
4045
4670
|
pending: null,
|
|
4671
|
+
onHandled,
|
|
4046
4672
|
timer: null
|
|
4047
4673
|
};
|
|
4048
4674
|
_active = suppression;
|
|
@@ -4062,138 +4688,153 @@ async function runWithConfirmedDestructiveContext(enabled, host, fn) {
|
|
|
4062
4688
|
}
|
|
4063
4689
|
|
|
4064
4690
|
// src/platform/reactNativeAdapter.ts
|
|
4065
|
-
var
|
|
4691
|
+
var deltaTracker = chunkUZ2D4BVX_js.createSnapshotDeltaTracker();
|
|
4066
4692
|
function resolveScreenMetadata() {
|
|
4067
|
-
const activePath =
|
|
4693
|
+
const activePath = chunkUZ2D4BVX_js.getActiveRouteNames();
|
|
4068
4694
|
for (let i = activePath.length - 1; i >= 0; i--) {
|
|
4069
4695
|
const name = activePath[i];
|
|
4070
|
-
const meta = name ?
|
|
4696
|
+
const meta = name ? chunkUZ2D4BVX_js.getScreenMetadata(name) : void 0;
|
|
4071
4697
|
if (meta && (Array.isArray(meta.fields) && meta.fields.length > 0 || Array.isArray(meta.actions) && meta.actions.length > 0)) {
|
|
4072
4698
|
return meta;
|
|
4073
4699
|
}
|
|
4074
4700
|
}
|
|
4075
|
-
const screen =
|
|
4076
|
-
return screen ?
|
|
4701
|
+
const screen = chunkUZ2D4BVX_js.getCurrentScreen();
|
|
4702
|
+
return screen ? chunkUZ2D4BVX_js.getScreenMetadata(screen) : void 0;
|
|
4077
4703
|
}
|
|
4078
4704
|
function buildAgentContext(extras = {}) {
|
|
4705
|
+
if (extras.newMission === true) {
|
|
4706
|
+
deltaTracker.reset();
|
|
4707
|
+
for (const entry of chunkUZ2D4BVX_js.listRegistry.snapshot()) entry.exploration?.reset();
|
|
4708
|
+
}
|
|
4079
4709
|
const context = {};
|
|
4080
4710
|
context.platform = "react-native";
|
|
4081
|
-
|
|
4711
|
+
context.missionProtocol = 1;
|
|
4712
|
+
context.deviceLocale = detectDeviceLocale() ?? "en";
|
|
4713
|
+
const screen = chunkUZ2D4BVX_js.getCurrentScreen();
|
|
4082
4714
|
if (screen) context.currentScreen = screen;
|
|
4083
|
-
const navigationState =
|
|
4715
|
+
const navigationState = chunkUZ2D4BVX_js.getNavigationStateSnapshot();
|
|
4084
4716
|
if (navigationState) context.navigationState = navigationState;
|
|
4085
4717
|
const screenMeta = resolveScreenMetadata();
|
|
4086
4718
|
if (screenMeta) context.screenMetadata = screenMeta;
|
|
4087
4719
|
try {
|
|
4088
|
-
|
|
4720
|
+
const snapshot = captureSnapshot();
|
|
4721
|
+
for (const list of snapshot.lists) {
|
|
4722
|
+
const memory = list.id ? chunkUZ2D4BVX_js.listRegistry.get(list.id)?.exploration : void 0;
|
|
4723
|
+
if (!memory) continue;
|
|
4724
|
+
memory.observe(list.items);
|
|
4725
|
+
list.exploration = memory.snapshot();
|
|
4726
|
+
}
|
|
4727
|
+
const delta = deltaTracker.observe(snapshot);
|
|
4728
|
+
if (delta) snapshot.delta = delta;
|
|
4729
|
+
context.snapshot = snapshot;
|
|
4089
4730
|
} catch (err) {
|
|
4090
|
-
|
|
4731
|
+
chunkUZ2D4BVX_js.appilotsDebugWarn("buildAgentContext: captureSnapshot failed", err);
|
|
4091
4732
|
}
|
|
4092
|
-
const registry =
|
|
4733
|
+
const registry = chunkUZ2D4BVX_js.componentRegistry.snapshot();
|
|
4093
4734
|
const filtered = screen ? registry.filter((c) => !c.screen || c.screen === screen) : registry;
|
|
4094
4735
|
if (filtered.length > 0) context.registeredComponents = filtered;
|
|
4095
|
-
const registeredLists =
|
|
4736
|
+
const registeredLists = chunkUZ2D4BVX_js.listRegistry.snapshot();
|
|
4096
4737
|
if (registeredLists.length > 0) {
|
|
4097
|
-
|
|
4098
|
-
|
|
4738
|
+
const snapshot = context.snapshot;
|
|
4739
|
+
const activeIds = new Set(
|
|
4740
|
+
[...snapshot?.lists ?? [], ...snapshot?.scrollables ?? []].map((l) => l.id)
|
|
4099
4741
|
);
|
|
4742
|
+
context.registeredLists = registeredLists.filter((entry) => activeIds.has(entry.id)).map(({ id, kind, component, itemCount, totalItemCount, label, refreshing, empty }) => ({
|
|
4743
|
+
id,
|
|
4744
|
+
kind,
|
|
4745
|
+
component,
|
|
4746
|
+
itemCount,
|
|
4747
|
+
totalItemCount,
|
|
4748
|
+
label,
|
|
4749
|
+
refreshing,
|
|
4750
|
+
empty
|
|
4751
|
+
}));
|
|
4100
4752
|
}
|
|
4101
4753
|
if (extras.loadingPending === true) context.loadingPending = true;
|
|
4102
4754
|
return context;
|
|
4103
4755
|
}
|
|
4104
|
-
function resolveActionHints(screen, pressedComponentId, actionPayload) {
|
|
4105
|
-
if (actionPayload && typeof actionPayload === "object") {
|
|
4106
|
-
const inline = actionPayload._appilotsInferred;
|
|
4107
|
-
if (inline && typeof inline === "object") {
|
|
4108
|
-
return inline;
|
|
4109
|
-
}
|
|
4110
|
-
}
|
|
4111
|
-
if (!screen || !pressedComponentId) return void 0;
|
|
4112
|
-
const meta = chunkKZ2BLMS4_js.getScreenMetadata(screen);
|
|
4113
|
-
const actions = meta?.actions;
|
|
4114
|
-
if (!actions || actions.length === 0) return void 0;
|
|
4115
|
-
for (const a of actions) {
|
|
4116
|
-
if (typeof a === "string") continue;
|
|
4117
|
-
if (chunkKZ2BLMS4_js.idLooselyMatches(a.id, pressedComponentId)) {
|
|
4118
|
-
const inferred = a.appilotsInferred;
|
|
4119
|
-
if (inferred && typeof inferred === "object") return inferred;
|
|
4120
|
-
return void 0;
|
|
4121
|
-
}
|
|
4122
|
-
}
|
|
4123
|
-
return void 0;
|
|
4124
|
-
}
|
|
4125
4756
|
async function settleTurn(input) {
|
|
4126
4757
|
const toolWithoutEffectIds = /* @__PURE__ */ new Set();
|
|
4127
4758
|
let loadingPending = false;
|
|
4128
4759
|
const { turnActions, pressedComponentId: pressedId, navigateTargetScreen } = input;
|
|
4129
4760
|
const successById = new Map(input.results.map((r) => [r.actionId, r.success]));
|
|
4761
|
+
const effectById = new Map(input.results.map((r) => [r.actionId, r.effect]));
|
|
4130
4762
|
const typeById = new Map(input.results.map((r) => [r.actionId, r.type]));
|
|
4763
|
+
const pressedAction = turnActions.find(
|
|
4764
|
+
(a) => a.type === "ui_interaction" && a.payload?.componentId === pressedId
|
|
4765
|
+
);
|
|
4766
|
+
const hints = resolveActionHints(
|
|
4767
|
+
chunkUZ2D4BVX_js.getCurrentScreen(),
|
|
4768
|
+
pressedId,
|
|
4769
|
+
pressedAction?.payload
|
|
4770
|
+
);
|
|
4771
|
+
const capSource = typeof hints?.asyncBudgetMs === "number" && hints.asyncBudgetMs > 0 ? " (app-declared)" : hints?.isAsyncTrigger ? " (mcp-inferred)" : "";
|
|
4131
4772
|
if (input.hadNavigate) {
|
|
4132
|
-
const settle = await
|
|
4773
|
+
const settle = await chunkUZ2D4BVX_js.waitForScreenSettle({
|
|
4133
4774
|
expectingChange: true,
|
|
4134
4775
|
fromScreen: input.preNavigateScreen ?? null,
|
|
4135
4776
|
fromSignature: input.preNavigateSignature ?? null,
|
|
4136
4777
|
targetScreen: navigateTargetScreen,
|
|
4137
4778
|
maxMs: 3500
|
|
4138
4779
|
});
|
|
4139
|
-
|
|
4780
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
4140
4781
|
`settleTurn: post-navigate settle done \u2014 screen="${settle.screen}" transitioned=${settle.transitioned} timedOut=${settle.timedOut} waitedMs=${settle.waitedMs}`
|
|
4141
4782
|
);
|
|
4142
|
-
const navigationMoved = settle.transitioned ||
|
|
4783
|
+
const navigationMoved = settle.transitioned || chunkUZ2D4BVX_js.screenDepartedBaseline(input.preNavigateScreen ?? null, input.preNavigateSignature ?? null) || !!navigateTargetScreen && !!settle.screen && chunkUZ2D4BVX_js.routesBelongToSameFeature(settle.screen, navigateTargetScreen);
|
|
4143
4784
|
if (!navigationMoved) {
|
|
4144
|
-
|
|
4785
|
+
chunkUZ2D4BVX_js.appilotsDebugWarn(
|
|
4145
4786
|
`tool-without-effect: navigate emitted but screen did not change (stayed at "${input.preNavigateScreen ?? "unknown"}", waitedMs=${settle.waitedMs}). Likely causes: target screenName missing from MCP doc, nested-nav path absent, or React Navigation rejected the route.`
|
|
4146
4787
|
);
|
|
4147
4788
|
for (const [actionId, type] of typeById) {
|
|
4148
4789
|
if (type === "navigate") toolWithoutEffectIds.add(actionId);
|
|
4149
4790
|
}
|
|
4150
4791
|
}
|
|
4151
|
-
const
|
|
4792
|
+
const postNavigateCapMs = resolvePostNavigateCapMs(hints);
|
|
4793
|
+
const loadSettle = await chunkUZ2D4BVX_js.waitForLoadingSettle({
|
|
4152
4794
|
fromScreen: settle.screen ?? null,
|
|
4153
|
-
maxMs:
|
|
4795
|
+
maxMs: postNavigateCapMs
|
|
4154
4796
|
});
|
|
4155
|
-
|
|
4156
|
-
`settleTurn: post-navigate loading settle \u2014 settled=${loadSettle.settled} loadingPending=${loadSettle.loadingPending} probes=${loadSettle.probeCount} waitedMs=${loadSettle.waitedMs}`
|
|
4797
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
4798
|
+
`settleTurn: post-navigate loading settle \u2014 settled=${loadSettle.settled} loadingPending=${loadSettle.loadingPending} probes=${loadSettle.probeCount} waitedMs=${loadSettle.waitedMs} cap=${postNavigateCapMs}${capSource}`
|
|
4157
4799
|
);
|
|
4158
4800
|
if (loadSettle.loadingPending) loadingPending = true;
|
|
4159
4801
|
} else {
|
|
4160
|
-
const
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
const hints = resolveActionHints(chunkKZ2BLMS4_js.getCurrentScreen(), pressedId, pressedAction?.payload);
|
|
4164
|
-
const settleCapMs = hints?.isAsyncTrigger === true ? 1e4 : POST_ACTION_LOADING_MAX_MS;
|
|
4165
|
-
const loadSettle = await chunkKZ2BLMS4_js.waitForLoadingSettle({
|
|
4802
|
+
const settleCapMs = resolveSettleCapMs(hints);
|
|
4803
|
+
const busyMaxMs = resolveBusyCeilingMs(hints);
|
|
4804
|
+
const loadSettle = await chunkUZ2D4BVX_js.waitForLoadingSettle({
|
|
4166
4805
|
pressedComponentId: pressedId,
|
|
4167
|
-
fromScreen:
|
|
4168
|
-
maxMs: settleCapMs
|
|
4806
|
+
fromScreen: chunkUZ2D4BVX_js.getCurrentScreen(),
|
|
4807
|
+
maxMs: settleCapMs,
|
|
4808
|
+
...busyMaxMs !== void 0 ? { busyMaxMs } : {}
|
|
4169
4809
|
});
|
|
4170
|
-
|
|
4171
|
-
`settleTurn: post-action loading settle \u2014 pressedId="${pressedId ?? ""}" settled=${loadSettle.settled} transitioned=${loadSettle.transitioned} loadingPending=${loadSettle.loadingPending} probes=${loadSettle.probeCount} waitedMs=${loadSettle.waitedMs} cap=${settleCapMs}${
|
|
4810
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
4811
|
+
`settleTurn: post-action loading settle \u2014 pressedId="${pressedId ?? ""}" settled=${loadSettle.settled} transitioned=${loadSettle.transitioned} loadingPending=${loadSettle.loadingPending} probes=${loadSettle.probeCount} waitedMs=${loadSettle.waitedMs} cap=${settleCapMs}${capSource}${busyMaxMs !== void 0 ? ` busyCap=${busyMaxMs}` : ""}`
|
|
4172
4812
|
);
|
|
4173
4813
|
if (loadSettle.loadingPending) loadingPending = true;
|
|
4174
4814
|
const listPressActions = turnActions.filter((action) => {
|
|
4175
|
-
const target =
|
|
4176
|
-
return target ?
|
|
4815
|
+
const target = chunkUZ2D4BVX_js.actionPressTargetId(action);
|
|
4816
|
+
return target ? chunkUZ2D4BVX_js.isListItemPressTarget(target) : false;
|
|
4177
4817
|
});
|
|
4178
4818
|
if (listPressActions.length > 0) {
|
|
4179
|
-
const baselineFingerprint =
|
|
4180
|
-
const postPressSettle = await
|
|
4819
|
+
const baselineFingerprint = chunkUZ2D4BVX_js.probeLoadingState(pressedId, chunkUZ2D4BVX_js.getCurrentScreen()).fingerprint;
|
|
4820
|
+
const postPressSettle = await chunkUZ2D4BVX_js.waitForScreenSettle({
|
|
4181
4821
|
expectingChange: true,
|
|
4182
4822
|
fromScreen: input.preNavigateScreen ?? null,
|
|
4183
4823
|
fromSignature: input.preNavigateSignature ?? null,
|
|
4184
4824
|
maxMs: 2500
|
|
4185
4825
|
});
|
|
4186
|
-
await
|
|
4826
|
+
await chunkUZ2D4BVX_js.waitForLoadingSettle({
|
|
4187
4827
|
pressedComponentId: pressedId,
|
|
4188
|
-
fromScreen:
|
|
4828
|
+
fromScreen: chunkUZ2D4BVX_js.getCurrentScreen(),
|
|
4189
4829
|
maxMs: 4e3
|
|
4190
4830
|
});
|
|
4191
|
-
const afterFingerprint =
|
|
4192
|
-
|
|
4831
|
+
const afterFingerprint = chunkUZ2D4BVX_js.probeLoadingState(pressedId, chunkUZ2D4BVX_js.getCurrentScreen()).fingerprint;
|
|
4832
|
+
chunkUZ2D4BVX_js.appilotsDebugLog(
|
|
4193
4833
|
`settleTurn: post-list-press settle \u2014 screen="${postPressSettle.screen}" transitioned=${postPressSettle.transitioned} timedOut=${postPressSettle.timedOut} waitedMs=${postPressSettle.waitedMs}`
|
|
4194
4834
|
);
|
|
4195
4835
|
if (!postPressSettle.transitioned && baselineFingerprint === afterFingerprint) {
|
|
4196
4836
|
for (const action of listPressActions) {
|
|
4837
|
+
if (effectById.get(action.id) === "changed") continue;
|
|
4197
4838
|
if (successById.get(action.id)) {
|
|
4198
4839
|
toolWithoutEffectIds.add(action.id);
|
|
4199
4840
|
}
|
|
@@ -4205,46 +4846,68 @@ async function settleTurn(input) {
|
|
|
4205
4846
|
}
|
|
4206
4847
|
var reactNativeChatAdapter = {
|
|
4207
4848
|
buildContext: buildAgentContext,
|
|
4208
|
-
getCurrentScreen:
|
|
4209
|
-
getCurrentScreenSignature:
|
|
4849
|
+
getCurrentScreen: chunkUZ2D4BVX_js.getCurrentScreen,
|
|
4850
|
+
getCurrentScreenSignature: chunkUZ2D4BVX_js.getCurrentScreenSignature,
|
|
4210
4851
|
settleTurn
|
|
4211
4852
|
};
|
|
4212
4853
|
function createReactNativeActionRunner(getOptions) {
|
|
4213
4854
|
return {
|
|
4855
|
+
buildMissionContext: () => reactNativeChatAdapter.buildContext(),
|
|
4214
4856
|
async execute(action, { confirmedDestructive }) {
|
|
4215
|
-
const { permissions, emit, navigationRef, suppressNativeConfirm } = getOptions();
|
|
4216
|
-
const navRef = navigationRef?.current ? navigationRef : { current:
|
|
4217
|
-
|
|
4857
|
+
const { permissions, emit: emit2, navigationRef, suppressNativeConfirm } = getOptions();
|
|
4858
|
+
const navRef = navigationRef?.current ? navigationRef : { current: chunkUZ2D4BVX_js.getNavigationRef() };
|
|
4859
|
+
let receipt;
|
|
4860
|
+
let terminal;
|
|
4861
|
+
const result = await runWithConfirmedDestructiveContext(
|
|
4218
4862
|
confirmedDestructive && suppressNativeConfirm !== false,
|
|
4219
4863
|
reactNative.Alert,
|
|
4220
4864
|
() => executeAction(action, {
|
|
4221
4865
|
navigationRef: navRef,
|
|
4222
4866
|
permissions,
|
|
4223
|
-
emit
|
|
4224
|
-
|
|
4867
|
+
emit: (event) => {
|
|
4868
|
+
if (confirmedDestructive && (event.type === "agent:action:complete" || event.type === "agent:action:error"))
|
|
4869
|
+
terminal = event;
|
|
4870
|
+
else emit2(event);
|
|
4871
|
+
}
|
|
4872
|
+
}),
|
|
4873
|
+
(handled) => {
|
|
4874
|
+
receipt = handled;
|
|
4875
|
+
}
|
|
4225
4876
|
);
|
|
4877
|
+
const failed = receipt?.handlerCompleted === false;
|
|
4878
|
+
if (terminal)
|
|
4879
|
+
emit2({
|
|
4880
|
+
...terminal,
|
|
4881
|
+
type: failed ? "agent:action:error" : terminal.type,
|
|
4882
|
+
data: {
|
|
4883
|
+
...terminal.data,
|
|
4884
|
+
...receipt ? { nativeConfirmation: receipt } : {},
|
|
4885
|
+
...failed ? { success: false, error: "Native confirmation callback failed" } : {}
|
|
4886
|
+
}
|
|
4887
|
+
});
|
|
4888
|
+
return failed ? { ...result, success: false, error: "Native confirmation callback failed" } : result;
|
|
4226
4889
|
},
|
|
4227
|
-
getCurrentScreen:
|
|
4228
|
-
getCurrentScreenSignature:
|
|
4890
|
+
getCurrentScreen: chunkUZ2D4BVX_js.getCurrentScreen,
|
|
4891
|
+
getCurrentScreenSignature: chunkUZ2D4BVX_js.getCurrentScreenSignature,
|
|
4229
4892
|
getScreenActionsMetadata(screen) {
|
|
4230
|
-
return
|
|
4893
|
+
return chunkUZ2D4BVX_js.getScreenMetadata(screen)?.actions;
|
|
4231
4894
|
},
|
|
4232
|
-
waitForScreenSettle:
|
|
4895
|
+
waitForScreenSettle: chunkUZ2D4BVX_js.waitForScreenSettle
|
|
4233
4896
|
};
|
|
4234
4897
|
}
|
|
4235
4898
|
|
|
4236
4899
|
// src/hooks/useAppilotsChat.ts
|
|
4237
4900
|
function useAppilotsChat(options = {}) {
|
|
4238
|
-
const { client, emit, subscribe } =
|
|
4901
|
+
const { client, emit: emit2, subscribe } = chunkUZ2D4BVX_js.useAppilotsContext();
|
|
4239
4902
|
const machine = React.useMemo(
|
|
4240
|
-
() => new
|
|
4241
|
-
{ client, adapter: reactNativeChatAdapter, emit, warn:
|
|
4903
|
+
() => new chunkUZ2D4BVX_js.ChatSessionMachine(
|
|
4904
|
+
{ client, adapter: reactNativeChatAdapter, emit: emit2, warn: chunkUZ2D4BVX_js.appilotsDebugWarn },
|
|
4242
4905
|
options
|
|
4243
4906
|
),
|
|
4244
4907
|
// A new machine per client/provider instance — options are pushed in
|
|
4245
4908
|
// below so changing copy never resets the transcript.
|
|
4246
4909
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
4247
|
-
[client,
|
|
4910
|
+
[client, emit2]
|
|
4248
4911
|
);
|
|
4249
4912
|
const optionsRef = React.useRef(options);
|
|
4250
4913
|
optionsRef.current = options;
|
|
@@ -4252,6 +4915,14 @@ function useAppilotsChat(options = {}) {
|
|
|
4252
4915
|
const state = React.useSyncExternalStore(machine.subscribeState, machine.getState, machine.getState);
|
|
4253
4916
|
React.useEffect(() => subscribe(machine.handleEvent), [subscribe, machine]);
|
|
4254
4917
|
React.useEffect(() => () => machine.dispose(), [machine]);
|
|
4918
|
+
React.useEffect(() => {
|
|
4919
|
+
void machine.restoreMission();
|
|
4920
|
+
const subscription = reactNative.AppState?.addEventListener?.("change", (next) => {
|
|
4921
|
+
if (next !== "active" && machine.getState().mission?.status === "running")
|
|
4922
|
+
void machine.pauseMission();
|
|
4923
|
+
});
|
|
4924
|
+
return () => subscription?.remove();
|
|
4925
|
+
}, [machine]);
|
|
4255
4926
|
const requestHuman = React.useCallback(
|
|
4256
4927
|
(reason) => machine.requestHuman(reason),
|
|
4257
4928
|
[machine]
|
|
@@ -4261,7 +4932,13 @@ function useAppilotsChat(options = {}) {
|
|
|
4261
4932
|
const clearMessages = React.useCallback(() => machine.clearMessages(), [machine]);
|
|
4262
4933
|
const clearError = React.useCallback(() => machine.clearError(), [machine]);
|
|
4263
4934
|
return {
|
|
4935
|
+
mission: state.mission,
|
|
4936
|
+
pauseMission: () => machine.pauseMission(),
|
|
4937
|
+
resumeMission: () => machine.resumeMission(),
|
|
4938
|
+
cancelMission: () => machine.cancelMission(),
|
|
4939
|
+
hasStartedActing: state.hasStartedActing,
|
|
4264
4940
|
messages: state.messages,
|
|
4941
|
+
replyLocale: state.replyLocale,
|
|
4265
4942
|
isLoading: state.isLoading,
|
|
4266
4943
|
loadingStatusKey: state.loadingStatusKey,
|
|
4267
4944
|
error: state.error,
|
|
@@ -4274,39 +4951,33 @@ function useAppilotsChat(options = {}) {
|
|
|
4274
4951
|
clearError
|
|
4275
4952
|
};
|
|
4276
4953
|
}
|
|
4277
|
-
var DEFAULT_PERMISSIONS2 = {
|
|
4278
|
-
canNavigate: true,
|
|
4279
|
-
canFillForms: true,
|
|
4280
|
-
canInteractUI: true,
|
|
4281
|
-
canSubmitForms: true
|
|
4282
|
-
};
|
|
4283
4954
|
function useAppilotsActions(options = {}) {
|
|
4284
|
-
const { client, subscribe, config, emit } =
|
|
4955
|
+
const { client, subscribe, config, emit: emit2 } = chunkUZ2D4BVX_js.useAppilotsContext();
|
|
4285
4956
|
const { navigationRef, autoExecute = false } = options;
|
|
4286
4957
|
const runnerOptionsRef = React.useRef({
|
|
4287
|
-
permissions: config.permissions
|
|
4288
|
-
emit,
|
|
4958
|
+
permissions: chunkUZ2D4BVX_js.resolveAgentPermissions(config.permissions),
|
|
4959
|
+
emit: emit2,
|
|
4289
4960
|
navigationRef,
|
|
4290
4961
|
suppressNativeConfirm: config.suppressNativeConfirm
|
|
4291
4962
|
});
|
|
4292
4963
|
runnerOptionsRef.current = {
|
|
4293
|
-
permissions: config.permissions
|
|
4294
|
-
emit,
|
|
4964
|
+
permissions: chunkUZ2D4BVX_js.resolveAgentPermissions(config.permissions),
|
|
4965
|
+
emit: emit2,
|
|
4295
4966
|
navigationRef,
|
|
4296
4967
|
suppressNativeConfirm: config.suppressNativeConfirm
|
|
4297
4968
|
};
|
|
4298
4969
|
const machine = React.useMemo(
|
|
4299
|
-
() => new
|
|
4970
|
+
() => new chunkUZ2D4BVX_js.ActionQueueMachine(
|
|
4300
4971
|
{
|
|
4301
4972
|
client,
|
|
4302
4973
|
adapter: createReactNativeActionRunner(() => runnerOptionsRef.current),
|
|
4303
|
-
emit,
|
|
4304
|
-
warn:
|
|
4974
|
+
emit: emit2,
|
|
4975
|
+
warn: chunkUZ2D4BVX_js.appilotsDebugWarn
|
|
4305
4976
|
},
|
|
4306
4977
|
{ autoExecute }
|
|
4307
4978
|
),
|
|
4308
4979
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
4309
|
-
[client,
|
|
4980
|
+
[client, emit2]
|
|
4310
4981
|
);
|
|
4311
4982
|
machine.setOptions({ autoExecute });
|
|
4312
4983
|
const state = React.useSyncExternalStore(machine.subscribeState, machine.getState, machine.getState);
|
|
@@ -4358,7 +5029,7 @@ function shouldShowSuggestedPrompts(args) {
|
|
|
4358
5029
|
|
|
4359
5030
|
// src/hooks/useSuggestedPrompts.ts
|
|
4360
5031
|
function useSuggestedPrompts(options) {
|
|
4361
|
-
const { client } =
|
|
5032
|
+
const { client } = chunkUZ2D4BVX_js.useAppilotsContext();
|
|
4362
5033
|
const { enabled, limit = 4 } = options;
|
|
4363
5034
|
const [prompts, setPrompts] = React.useState([]);
|
|
4364
5035
|
const [isLoading, setIsLoading] = React.useState(false);
|
|
@@ -4368,8 +5039,8 @@ function useSuggestedPrompts(options) {
|
|
|
4368
5039
|
if (!enabled) return;
|
|
4369
5040
|
const requestId = ++requestIdRef.current;
|
|
4370
5041
|
let cancelled = false;
|
|
4371
|
-
const screen =
|
|
4372
|
-
const localDev = screen ? (
|
|
5042
|
+
const screen = chunkUZ2D4BVX_js.getCurrentScreen() ?? void 0;
|
|
5043
|
+
const localDev = screen ? (chunkUZ2D4BVX_js.getScreenMetadata(screen)?.suggestedPrompts ?? []).map((text) => ({
|
|
4373
5044
|
text,
|
|
4374
5045
|
source: "dev-defined"
|
|
4375
5046
|
})) : [];
|
|
@@ -4383,7 +5054,7 @@ function useSuggestedPrompts(options) {
|
|
|
4383
5054
|
if (cancelled || requestIdRef.current !== requestId) return;
|
|
4384
5055
|
setPrompts(mergePromptSources(localDev, data, limit));
|
|
4385
5056
|
}).catch((err) => {
|
|
4386
|
-
|
|
5057
|
+
chunkUZ2D4BVX_js.appilotsDebugWarn("useSuggestedPrompts: fetch failed", err);
|
|
4387
5058
|
}).finally(() => {
|
|
4388
5059
|
if (cancelled || requestIdRef.current !== requestId) return;
|
|
4389
5060
|
setIsLoading(false);
|
|
@@ -4394,11 +5065,11 @@ function useSuggestedPrompts(options) {
|
|
|
4394
5065
|
}, [client, enabled, limit, refreshTick]);
|
|
4395
5066
|
React.useEffect(() => {
|
|
4396
5067
|
if (!enabled) return;
|
|
4397
|
-
let lastScreen =
|
|
5068
|
+
let lastScreen = chunkUZ2D4BVX_js.getCurrentScreen();
|
|
4398
5069
|
const interval = setInterval(() => {
|
|
4399
|
-
const
|
|
4400
|
-
if (
|
|
4401
|
-
lastScreen =
|
|
5070
|
+
const current2 = chunkUZ2D4BVX_js.getCurrentScreen();
|
|
5071
|
+
if (current2 !== lastScreen) {
|
|
5072
|
+
lastScreen = current2;
|
|
4402
5073
|
setRefreshTick((t) => t + 1);
|
|
4403
5074
|
}
|
|
4404
5075
|
}, 800);
|
|
@@ -4411,22 +5082,22 @@ function useSuggestedPrompts(options) {
|
|
|
4411
5082
|
};
|
|
4412
5083
|
}
|
|
4413
5084
|
function useAppilotsNavigation() {
|
|
4414
|
-
const { emit } =
|
|
5085
|
+
const { emit: emit2 } = chunkUZ2D4BVX_js.useAppilotsContext();
|
|
4415
5086
|
const [currentScreen, setCurrentScreenState] = React.useState(null);
|
|
4416
5087
|
const [navigationHistory, setNavigationHistory] = React.useState([]);
|
|
4417
5088
|
const navigationRef = React.useRef(null);
|
|
4418
5089
|
const setCurrentScreen2 = React.useCallback(
|
|
4419
5090
|
(screenName) => {
|
|
4420
5091
|
setCurrentScreenState(screenName);
|
|
4421
|
-
|
|
5092
|
+
chunkUZ2D4BVX_js.setCurrentScreen(screenName);
|
|
4422
5093
|
setNavigationHistory((prev) => [...prev, screenName]);
|
|
4423
|
-
|
|
5094
|
+
emit2({
|
|
4424
5095
|
type: "navigation:change",
|
|
4425
5096
|
timestamp: Date.now(),
|
|
4426
5097
|
data: { screenName }
|
|
4427
5098
|
});
|
|
4428
5099
|
},
|
|
4429
|
-
[
|
|
5100
|
+
[emit2]
|
|
4430
5101
|
);
|
|
4431
5102
|
React.useEffect(() => {
|
|
4432
5103
|
const nav = navigationRef.current;
|
|
@@ -4449,7 +5120,7 @@ function useAppilotsNavigation() {
|
|
|
4449
5120
|
|
|
4450
5121
|
// src/hooks/useAppilots.ts
|
|
4451
5122
|
function useAppilots() {
|
|
4452
|
-
const { config, client } =
|
|
5123
|
+
const { config, client } = chunkUZ2D4BVX_js.useAppilotsContext();
|
|
4453
5124
|
const chat = useAppilotsChat();
|
|
4454
5125
|
const navigation = useAppilotsNavigation();
|
|
4455
5126
|
const actions = useAppilotsActions();
|
|
@@ -4476,9 +5147,14 @@ function useAppilots() {
|
|
|
4476
5147
|
rejectAction: actions.rejectAction
|
|
4477
5148
|
};
|
|
4478
5149
|
}
|
|
5150
|
+
function useAppilotsElementProps(id) {
|
|
5151
|
+
return React.useMemo(() => ({ testID: id }), [id]);
|
|
5152
|
+
}
|
|
5153
|
+
|
|
5154
|
+
// src/hooks/useAppilotsField.ts
|
|
4479
5155
|
function useAppilotsField(id, options) {
|
|
4480
5156
|
const { value, onChangeText, ref, fieldType, label, screen } = options;
|
|
4481
|
-
const registry =
|
|
5157
|
+
const registry = chunkUZ2D4BVX_js.useResolvedRegistry();
|
|
4482
5158
|
const valueRef = React.useRef(value);
|
|
4483
5159
|
const onChangeRef = React.useRef(onChangeText);
|
|
4484
5160
|
valueRef.current = value;
|
|
@@ -4503,10 +5179,11 @@ function useAppilotsField(id, options) {
|
|
|
4503
5179
|
registry.unregister(id);
|
|
4504
5180
|
};
|
|
4505
5181
|
}, [id, registry, getValue, setValue, focus, ref, fieldType, label, screen]);
|
|
5182
|
+
return useAppilotsElementProps(id);
|
|
4506
5183
|
}
|
|
4507
5184
|
function useAppilotsTarget(id, options) {
|
|
4508
5185
|
const { onPress, onLongPress, onScrollTo, label, screen } = options;
|
|
4509
|
-
const registry =
|
|
5186
|
+
const registry = chunkUZ2D4BVX_js.useResolvedRegistry();
|
|
4510
5187
|
const onPressRef = React.useRef(onPress);
|
|
4511
5188
|
const onLongPressRef = React.useRef(onLongPress);
|
|
4512
5189
|
const onScrollToRef = React.useRef(onScrollTo);
|
|
@@ -4530,10 +5207,11 @@ function useAppilotsTarget(id, options) {
|
|
|
4530
5207
|
registry.unregister(id);
|
|
4531
5208
|
};
|
|
4532
5209
|
}, [id, registry, press, longPress, scrollTo, onLongPress, onScrollTo, label, screen]);
|
|
5210
|
+
return useAppilotsElementProps(id);
|
|
4533
5211
|
}
|
|
4534
5212
|
function useAppilotsToggle(id, options) {
|
|
4535
5213
|
const { value, onValueChange, label, screen } = options;
|
|
4536
|
-
const registry =
|
|
5214
|
+
const registry = chunkUZ2D4BVX_js.useResolvedRegistry();
|
|
4537
5215
|
const valueRef = React.useRef(value);
|
|
4538
5216
|
const onChangeRef = React.useRef(onValueChange);
|
|
4539
5217
|
valueRef.current = value;
|
|
@@ -4553,10 +5231,11 @@ function useAppilotsToggle(id, options) {
|
|
|
4553
5231
|
registry.unregister(id);
|
|
4554
5232
|
};
|
|
4555
5233
|
}, [id, registry, getValue, setValue, label, screen]);
|
|
5234
|
+
return useAppilotsElementProps(id);
|
|
4556
5235
|
}
|
|
4557
5236
|
function useAppilotsSlider(id, options) {
|
|
4558
5237
|
const { value, onValueChange, min, max, step, label, screen } = options;
|
|
4559
|
-
const registry =
|
|
5238
|
+
const registry = chunkUZ2D4BVX_js.useResolvedRegistry();
|
|
4560
5239
|
const valueRef = React.useRef(value);
|
|
4561
5240
|
const onChangeRef = React.useRef(onValueChange);
|
|
4562
5241
|
valueRef.current = value;
|
|
@@ -4579,16 +5258,30 @@ function useAppilotsSlider(id, options) {
|
|
|
4579
5258
|
registry.unregister(id);
|
|
4580
5259
|
};
|
|
4581
5260
|
}, [id, registry, getValue, setValue, min, max, step, label, screen]);
|
|
5261
|
+
return useAppilotsElementProps(id);
|
|
4582
5262
|
}
|
|
4583
5263
|
|
|
5264
|
+
exports.AppilotsI18nProvider = AppilotsI18nProvider;
|
|
5265
|
+
exports.REVEAL_MARGIN = REVEAL_MARGIN;
|
|
5266
|
+
exports.SPOTLIGHT_TTL_MS = SPOTLIGHT_TTL_MS;
|
|
4584
5267
|
exports.appilotsSelfCheck = appilotsSelfCheck;
|
|
4585
5268
|
exports.captureSnapshot = captureSnapshot;
|
|
5269
|
+
exports.detectDeviceLocale = detectDeviceLocale;
|
|
4586
5270
|
exports.executeAction = executeAction;
|
|
5271
|
+
exports.getSpotlightMode = getSpotlightMode;
|
|
5272
|
+
exports.getSpotlightTarget = getSpotlightTarget;
|
|
5273
|
+
exports.offsetToReveal = offsetToReveal;
|
|
5274
|
+
exports.resolveLocale = resolveLocale;
|
|
5275
|
+
exports.revealTarget = revealTarget;
|
|
5276
|
+
exports.setSpotlightMode = setSpotlightMode;
|
|
5277
|
+
exports.setSpotlightTarget = setSpotlightTarget;
|
|
4587
5278
|
exports.shouldShowSuggestedPrompts = shouldShowSuggestedPrompts;
|
|
5279
|
+
exports.subscribeSpotlight = subscribeSpotlight;
|
|
4588
5280
|
exports.useAppilots = useAppilots;
|
|
4589
5281
|
exports.useAppilotsActions = useAppilotsActions;
|
|
4590
5282
|
exports.useAppilotsChat = useAppilotsChat;
|
|
4591
5283
|
exports.useAppilotsField = useAppilotsField;
|
|
5284
|
+
exports.useAppilotsI18n = useAppilotsI18n;
|
|
4592
5285
|
exports.useAppilotsNavigation = useAppilotsNavigation;
|
|
4593
5286
|
exports.useAppilotsSlider = useAppilotsSlider;
|
|
4594
5287
|
exports.useAppilotsTarget = useAppilotsTarget;
|