yaver-feedback-react-native 0.9.2 → 0.9.3
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/README.md +102 -1
- package/dist/AuthOverlay.d.ts +1 -14
- package/dist/AuthOverlay.js +9 -62
- package/dist/Discovery.js +0 -6
- package/dist/DogfoodRuntime.d.ts +124 -0
- package/dist/DogfoodRuntime.js +273 -0
- package/dist/FeedbackModal.js +347 -61
- package/dist/LoginScreen.d.ts +1 -5
- package/dist/LoginScreen.js +2 -6
- package/dist/MachinePickerScreen.d.ts +1 -3
- package/dist/MachinePickerScreen.js +6 -18
- package/dist/P2PClient.d.ts +116 -3
- package/dist/P2PClient.js +273 -3
- package/dist/P2PDogfoodDriver.d.ts +12 -0
- package/dist/P2PDogfoodDriver.js +118 -0
- package/dist/PairDeviceModal.d.ts +2 -3
- package/dist/VibeChatScreen.d.ts +11 -1
- package/dist/VibeChatScreen.js +200 -41
- package/dist/YaverFeedback.d.ts +34 -0
- package/dist/YaverFeedback.js +124 -19
- package/dist/YaverModeBadge.d.ts +22 -0
- package/dist/YaverModeBadge.js +219 -0
- package/dist/__tests__/AuthDevices.test.js +1 -48
- package/dist/__tests__/DogfoodRuntime.test.d.ts +1 -0
- package/dist/__tests__/DogfoodRuntime.test.js +116 -0
- package/dist/__tests__/P2PDogfoodDriver.test.d.ts +1 -0
- package/dist/__tests__/P2PDogfoodDriver.test.js +64 -0
- package/dist/__tests__/ReportIdentity.test.d.ts +25 -1
- package/dist/__tests__/ReportIdentity.test.js +34 -22
- package/dist/__tests__/YaverFeedback.test.js +13 -3
- package/dist/__tests__/deviceDogfood.test.d.ts +1 -0
- package/dist/__tests__/deviceDogfood.test.js +86 -0
- package/dist/__tests__/dogfoodPolicy.test.d.ts +1 -0
- package/dist/__tests__/dogfoodPolicy.test.js +33 -0
- package/dist/_core/ansi.d.ts +117 -0
- package/dist/_core/ansi.js +468 -0
- package/dist/_core/ansi.test.d.ts +1 -0
- package/dist/_core/ansi.test.js +225 -0
- package/dist/_core/buildFeedbackPrompt.d.ts +4 -9
- package/dist/_core/buildFeedbackPrompt.js +18 -72
- package/dist/_core/constants.d.ts +19 -6
- package/dist/_core/constants.js +20 -7
- package/dist/_core/device.d.ts +9 -23
- package/dist/_core/device.js +13 -28
- package/dist/_core/endpoints.d.ts +0 -7
- package/dist/_core/endpoints.js +0 -7
- package/dist/_core/index.d.ts +4 -0
- package/dist/_core/index.js +4 -0
- package/dist/_core/remoteless.d.ts +44 -0
- package/dist/_core/remoteless.js +75 -0
- package/dist/_core/trace.d.ts +47 -0
- package/dist/_core/trace.js +38 -0
- package/dist/_core/trace.test.d.ts +1 -0
- package/dist/_core/trace.test.js +60 -0
- package/dist/auth.d.ts +3 -60
- package/dist/auth.js +6 -88
- package/dist/deviceDogfood.d.ts +53 -0
- package/dist/deviceDogfood.js +137 -0
- package/dist/dogfoodPolicy.d.ts +25 -0
- package/dist/dogfoodPolicy.js +24 -0
- package/dist/index.d.ts +13 -4
- package/dist/index.js +24 -8
- package/dist/reloadActions.js +2 -2
- package/dist/types.d.ts +50 -7
- package/package.json +12 -3
- package/src/AuthOverlay.tsx +20 -106
- package/src/Discovery.ts +0 -6
- package/src/DogfoodRuntime.ts +373 -0
- package/src/FeedbackModal.tsx +445 -67
- package/src/LoginScreen.tsx +2 -22
- package/src/MachinePickerScreen.tsx +6 -21
- package/src/P2PClient.ts +347 -4
- package/src/P2PDogfoodDriver.ts +132 -0
- package/src/PairDeviceModal.tsx +2 -3
- package/src/VibeChatScreen.tsx +232 -42
- package/src/YaverFeedback.ts +133 -22
- package/src/YaverModeBadge.tsx +234 -0
- package/src/__tests__/AuthDevices.test.ts +1 -52
- package/src/__tests__/DogfoodRuntime.test.ts +135 -0
- package/src/__tests__/P2PDogfoodDriver.test.ts +80 -0
- package/src/__tests__/ReportIdentity.test.ts +36 -27
- package/src/__tests__/YaverFeedback.test.ts +15 -3
- package/src/__tests__/deviceDogfood.test.ts +77 -0
- package/src/__tests__/dogfoodPolicy.test.ts +34 -0
- package/src/_core/ansi.test.ts +250 -0
- package/src/_core/ansi.ts +475 -0
- package/src/_core/buildFeedbackPrompt.ts +18 -95
- package/src/_core/constants.ts +20 -6
- package/src/_core/device.ts +13 -30
- package/src/_core/endpoints.ts +0 -7
- package/src/_core/index.ts +4 -0
- package/src/_core/remoteless.ts +110 -0
- package/src/_core/trace.test.ts +58 -0
- package/src/_core/trace.ts +75 -0
- package/src/auth.ts +7 -156
- package/src/deviceDogfood.ts +171 -0
- package/src/dogfoodPolicy.ts +40 -0
- package/src/index.ts +40 -11
- package/src/reloadActions.ts +2 -2
- package/src/types.ts +45 -7
- package/dist/GuestOnboardingScreen.d.ts +0 -8
- package/dist/GuestOnboardingScreen.js +0 -282
- package/src/GuestOnboardingScreen.tsx +0 -307
package/dist/FeedbackModal.js
CHANGED
|
@@ -42,11 +42,14 @@ const upload_1 = require("./upload");
|
|
|
42
42
|
const P2PClient_1 = require("./P2PClient");
|
|
43
43
|
const AuthOverlay_1 = require("./AuthOverlay");
|
|
44
44
|
const QuickActionIcon_1 = require("./QuickActionIcon");
|
|
45
|
+
const YaverModeBadge_1 = require("./YaverModeBadge");
|
|
45
46
|
const VibeChatScreen_1 = require("./VibeChatScreen");
|
|
46
47
|
const DeployPanel_1 = require("./DeployPanel");
|
|
47
48
|
const auth_1 = require("./auth");
|
|
48
49
|
const reloadActions_1 = require("./reloadActions");
|
|
49
50
|
const preferences_1 = require("./preferences");
|
|
51
|
+
const DogfoodRuntime_1 = require("./DogfoodRuntime");
|
|
52
|
+
const P2PDogfoodDriver_1 = require("./P2PDogfoodDriver");
|
|
50
53
|
const PRIMARY_RUNNER_IDS = ['claude', 'codex', 'opencode'];
|
|
51
54
|
function normalizeRunnerStatusRows(rows) {
|
|
52
55
|
const byId = new Map();
|
|
@@ -85,6 +88,7 @@ function normalizeRunnerStatusRows(rows) {
|
|
|
85
88
|
version: row.version,
|
|
86
89
|
tone: 'warning',
|
|
87
90
|
statusLine: 'Not installed on the selected machine',
|
|
91
|
+
models: row.models,
|
|
88
92
|
detail,
|
|
89
93
|
};
|
|
90
94
|
}
|
|
@@ -101,6 +105,7 @@ function normalizeRunnerStatusRows(rows) {
|
|
|
101
105
|
statusLine: configured
|
|
102
106
|
? `${versionPrefix}Configured on the selected machine`
|
|
103
107
|
: `${versionPrefix}Needs provider config on the selected machine`,
|
|
108
|
+
models: row.models,
|
|
104
109
|
detail,
|
|
105
110
|
};
|
|
106
111
|
}
|
|
@@ -116,12 +121,34 @@ function normalizeRunnerStatusRows(rows) {
|
|
|
116
121
|
statusLine: authed
|
|
117
122
|
? `${versionPrefix}Signed in on the selected machine`
|
|
118
123
|
: `${versionPrefix}Not signed in on the selected machine`,
|
|
124
|
+
models: row.models,
|
|
119
125
|
detail,
|
|
120
126
|
actionLabel: authed ? 'Re-auth' : 'Sign in',
|
|
121
127
|
actionRunner: id,
|
|
122
128
|
};
|
|
123
129
|
});
|
|
124
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Renders the "inside Yaver" mark unless the app opted out.
|
|
133
|
+
*
|
|
134
|
+
* Lives here rather than in YaverModeBadge so the component stays a dumb view
|
|
135
|
+
* and the DEFAULT (`modeBadge !== false` → on) is expressed in exactly one
|
|
136
|
+
* place. Mounted from FeedbackModal because that is the component integrating
|
|
137
|
+
* apps already render — a default that required a new mount point would not be
|
|
138
|
+
* a default, it would be a feature request.
|
|
139
|
+
*/
|
|
140
|
+
const YaverModeBadgeGate = () => {
|
|
141
|
+
const [, refresh] = (0, react_1.useState)(0);
|
|
142
|
+
(0, react_1.useEffect)(() => {
|
|
143
|
+
const sub = react_native_1.DeviceEventEmitter.addListener('yaverFeedback:dogfoodChanged', () => refresh((n) => n + 1));
|
|
144
|
+
return () => sub.remove();
|
|
145
|
+
}, []);
|
|
146
|
+
const cfg = YaverFeedback_1.YaverFeedback.getConfig();
|
|
147
|
+
if (cfg?.modeBadge === false)
|
|
148
|
+
return null;
|
|
149
|
+
const dogfood = YaverFeedback_1.YaverFeedback.getDogfoodStatus();
|
|
150
|
+
return (<YaverModeBadge_1.YaverModeBadge position={cfg?.modeBadgePosition ?? 'bottom-left'} force={dogfood.active} dogfood={dogfood.active} dogfoodLabel={dogfood.label} onExitDogfood={() => YaverFeedback_1.YaverFeedback.exitDogfoodMode()}/>);
|
|
151
|
+
};
|
|
125
152
|
const FeedbackModal = () => {
|
|
126
153
|
const { width: winW, height: winH } = (0, react_native_1.useWindowDimensions)();
|
|
127
154
|
const isTablet = Math.min(winW, winH) >= 600;
|
|
@@ -129,6 +156,7 @@ const FeedbackModal = () => {
|
|
|
129
156
|
// looks empty on a 1024pt iPad. Mobile keeps 3-col.
|
|
130
157
|
const iconOptionWidthOverride = isTablet ? '18%' : undefined;
|
|
131
158
|
const [visible, setVisible] = (0, react_1.useState)(false);
|
|
159
|
+
const [dogfoodActive, setDogfoodActive] = (0, react_1.useState)(() => YaverFeedback_1.YaverFeedback.getDogfoodStatus().active);
|
|
132
160
|
const [action, setAction] = (0, react_1.useState)('idle');
|
|
133
161
|
const [error, setError] = (0, react_1.useState)(null);
|
|
134
162
|
const [toast, setToast] = (0, react_1.useState)(null);
|
|
@@ -168,8 +196,93 @@ const FeedbackModal = () => {
|
|
|
168
196
|
const [runnerStatusError, setRunnerStatusError] = (0, react_1.useState)(null);
|
|
169
197
|
const [preferredRunner, setPreferredRunnerState] = (0, react_1.useState)(null);
|
|
170
198
|
const [preferredModel, setPreferredModelState] = (0, react_1.useState)('');
|
|
199
|
+
const [activeTab, setActiveTab] = (0, react_1.useState)('chat');
|
|
171
200
|
const [showOpenCodeConfig, setShowOpenCodeConfig] = (0, react_1.useState)(false);
|
|
201
|
+
const scrollRef = (0, react_1.useRef)(null);
|
|
202
|
+
const [dogfoodEnrollment, setDogfoodEnrollment] = (0, react_1.useState)(null);
|
|
203
|
+
const [dogfoodProjects, setDogfoodProjects] = (0, react_1.useState)([]);
|
|
204
|
+
const [dogfoodProject, setDogfoodProject] = (0, react_1.useState)(null);
|
|
205
|
+
const [dogfoodLane, setDogfoodLane] = (0, react_1.useState)('browser');
|
|
206
|
+
const [dogfoodNativeAvailable, setDogfoodNativeAvailable] = (0, react_1.useState)(false);
|
|
207
|
+
const [dogfoodRuntime, setDogfoodRuntime] = (0, react_1.useState)(null);
|
|
208
|
+
const [dogfoodSetupLoading, setDogfoodSetupLoading] = (0, react_1.useState)(false);
|
|
209
|
+
const dogfoodControllerRef = (0, react_1.useRef)(null);
|
|
172
210
|
const mountedRef = (0, react_1.useRef)(true);
|
|
211
|
+
const loadDogfoodOnboarding = (0, react_1.useCallback)(async () => {
|
|
212
|
+
const onboarding = YaverFeedback_1.YaverFeedback.getDogfoodOnboarding();
|
|
213
|
+
if (!onboarding)
|
|
214
|
+
return;
|
|
215
|
+
setDogfoodSetupLoading(true);
|
|
216
|
+
setDogfoodEnrollment({ status: 'checking' });
|
|
217
|
+
try {
|
|
218
|
+
const enrolled = await YaverFeedback_1.YaverFeedback.enableDeviceDogfood(onboarding);
|
|
219
|
+
if (!mountedRef.current)
|
|
220
|
+
return;
|
|
221
|
+
setDogfoodEnrollment({ status: enrolled.status, installationId: enrolled.installationId });
|
|
222
|
+
if (enrolled.status !== 'active')
|
|
223
|
+
return;
|
|
224
|
+
let client = YaverFeedback_1.YaverFeedback.getP2PClient();
|
|
225
|
+
if (!client && await YaverFeedback_1.YaverFeedback.reconnect())
|
|
226
|
+
client = YaverFeedback_1.YaverFeedback.getP2PClient();
|
|
227
|
+
if (!client)
|
|
228
|
+
throw new Error('The selected Yaver machine is not reachable yet.');
|
|
229
|
+
const projects = await client.listDogfoodProjects();
|
|
230
|
+
if (!mountedRef.current)
|
|
231
|
+
return;
|
|
232
|
+
setDogfoodProjects(projects);
|
|
233
|
+
const hint = String(onboarding.projectName || '').trim().toLowerCase();
|
|
234
|
+
const preferred = projects.find((item) => item.name.toLowerCase() === hint)
|
|
235
|
+
|| projects.find((item) => hint && item.name.toLowerCase().includes(hint))
|
|
236
|
+
|| projects[0]
|
|
237
|
+
|| null;
|
|
238
|
+
setDogfoodProject((current) => current && projects.some((item) => item.path === current.path) ? current : preferred);
|
|
239
|
+
if (preferred)
|
|
240
|
+
setDogfoodLane((0, DogfoodRuntime_1.defaultDogfoodLane)(preferred.framework || onboarding.framework || 'expo'));
|
|
241
|
+
}
|
|
242
|
+
catch (cause) {
|
|
243
|
+
if (mountedRef.current)
|
|
244
|
+
setDogfoodEnrollment({ status: 'failed', error: cause instanceof Error ? cause.message : String(cause) });
|
|
245
|
+
}
|
|
246
|
+
finally {
|
|
247
|
+
if (mountedRef.current)
|
|
248
|
+
setDogfoodSetupLoading(false);
|
|
249
|
+
}
|
|
250
|
+
}, []);
|
|
251
|
+
(0, react_1.useEffect)(() => {
|
|
252
|
+
let cancelled = false;
|
|
253
|
+
setDogfoodNativeAvailable(false);
|
|
254
|
+
const client = YaverFeedback_1.YaverFeedback.getP2PClient();
|
|
255
|
+
if (!client || !dogfoodProject)
|
|
256
|
+
return () => { cancelled = true; };
|
|
257
|
+
const framework = dogfoodProject.framework || YaverFeedback_1.YaverFeedback.getDogfoodOnboarding()?.framework || 'expo';
|
|
258
|
+
void client.getDogfoodRemoteRuntimeCapabilities(dogfoodProject.path, framework)
|
|
259
|
+
.then((value) => {
|
|
260
|
+
if (!cancelled)
|
|
261
|
+
setDogfoodNativeAvailable(value.targets.some((target) => target.enabled && target.id !== 'browser-window'));
|
|
262
|
+
})
|
|
263
|
+
.catch(() => { });
|
|
264
|
+
return () => { cancelled = true; };
|
|
265
|
+
}, [dogfoodProject]);
|
|
266
|
+
const startDogfoodRuntime = (0, react_1.useCallback)(async () => {
|
|
267
|
+
const client = YaverFeedback_1.YaverFeedback.getP2PClient();
|
|
268
|
+
const onboarding = YaverFeedback_1.YaverFeedback.getDogfoodOnboarding();
|
|
269
|
+
if (!client || !dogfoodProject || !onboarding)
|
|
270
|
+
return;
|
|
271
|
+
await dogfoodControllerRef.current?.stop().catch(() => { });
|
|
272
|
+
const framework = dogfoodProject.framework || onboarding.framework || 'expo';
|
|
273
|
+
const controller = new DogfoodRuntime_1.DogfoodController({
|
|
274
|
+
name: dogfoodProject.name,
|
|
275
|
+
workDir: dogfoodProject.path,
|
|
276
|
+
framework,
|
|
277
|
+
lane: dogfoodLane,
|
|
278
|
+
}, (0, P2PDogfoodDriver_1.createP2PDogfoodDriver)(client), {
|
|
279
|
+
onChange: (snapshot) => { if (mountedRef.current)
|
|
280
|
+
setDogfoodRuntime(snapshot); },
|
|
281
|
+
});
|
|
282
|
+
dogfoodControllerRef.current = controller;
|
|
283
|
+
setDogfoodRuntime(controller.snapshot());
|
|
284
|
+
await controller.trigger().catch(() => { });
|
|
285
|
+
}, [dogfoodLane, dogfoodProject]);
|
|
173
286
|
/**
|
|
174
287
|
* Ask the machine what its dev server is doing, so the reload actions can
|
|
175
288
|
* be enabled/disabled against reality rather than against a guess.
|
|
@@ -225,8 +338,7 @@ const FeedbackModal = () => {
|
|
|
225
338
|
}
|
|
226
339
|
try {
|
|
227
340
|
const devices = await (0, auth_1.listReachableDevices)(cfg.authToken);
|
|
228
|
-
const
|
|
229
|
-
const device = all.find((candidate) => candidate.deviceId === cfg.preferredDeviceId) ?? null;
|
|
341
|
+
const device = devices.owned.find((candidate) => candidate.deviceId === cfg.preferredDeviceId) ?? null;
|
|
230
342
|
if (!device) {
|
|
231
343
|
if (mountedRef.current) {
|
|
232
344
|
setMachineCard({
|
|
@@ -245,9 +357,8 @@ const FeedbackModal = () => {
|
|
|
245
357
|
if (device.isOnline && !device.needsAuth && client) {
|
|
246
358
|
reachable = await client.health();
|
|
247
359
|
}
|
|
248
|
-
const hostHint = device.hostEmail ? ` via ${device.hostEmail}` : '';
|
|
249
360
|
let status = 'live';
|
|
250
|
-
let detail =
|
|
361
|
+
let detail = device.platform;
|
|
251
362
|
if (!device.isOnline) {
|
|
252
363
|
status = 'offline';
|
|
253
364
|
detail = 'Machine offline. Start `yaver serve` on the selected machine.';
|
|
@@ -320,7 +431,7 @@ const FeedbackModal = () => {
|
|
|
320
431
|
if (!client) {
|
|
321
432
|
throw new Error('Not connected to the selected machine yet.');
|
|
322
433
|
}
|
|
323
|
-
const rows = await client.
|
|
434
|
+
const rows = await client.getAvailableRunners();
|
|
324
435
|
if (mountedRef.current) {
|
|
325
436
|
setRunnerCards(normalizeRunnerStatusRows(rows));
|
|
326
437
|
}
|
|
@@ -358,13 +469,20 @@ const FeedbackModal = () => {
|
|
|
358
469
|
mountedRef.current = true;
|
|
359
470
|
const sub = react_native_1.DeviceEventEmitter.addListener('yaverFeedback:startReport', () => {
|
|
360
471
|
if (YaverFeedback_1.YaverFeedback.isEnabled()) {
|
|
472
|
+
const onboarding = YaverFeedback_1.YaverFeedback.getDogfoodOnboarding();
|
|
473
|
+
const directDogfood = YaverFeedback_1.YaverFeedback.getDogfoodStatus().active;
|
|
474
|
+
setDogfoodActive(directDogfood);
|
|
361
475
|
setVisible(true);
|
|
362
476
|
setError(null);
|
|
363
477
|
setToast(null);
|
|
364
478
|
setProgress(null);
|
|
365
479
|
setAction('idle');
|
|
366
|
-
setShowVibeInput(
|
|
480
|
+
setShowVibeInput(directDogfood);
|
|
367
481
|
setVibePrompt('');
|
|
482
|
+
if (onboarding) {
|
|
483
|
+
setActiveTab('settings');
|
|
484
|
+
void loadDogfoodOnboarding();
|
|
485
|
+
}
|
|
368
486
|
// Re-read the "user hid the quick icon" flag on every open so
|
|
369
487
|
// the re-enable row reflects the latest preference (the user
|
|
370
488
|
// might have hidden or shown it between opens).
|
|
@@ -384,6 +502,13 @@ const FeedbackModal = () => {
|
|
|
384
502
|
void loadRunnerStatuses();
|
|
385
503
|
}
|
|
386
504
|
});
|
|
505
|
+
const dogfoodSub = react_native_1.DeviceEventEmitter.addListener('yaverFeedback:dogfoodChanged', (payload) => {
|
|
506
|
+
if (!mountedRef.current)
|
|
507
|
+
return;
|
|
508
|
+
setDogfoodActive(payload?.active === true);
|
|
509
|
+
if (payload?.exited === true)
|
|
510
|
+
setVisible(false);
|
|
511
|
+
});
|
|
387
512
|
// Agent streams build / compile progress through the BlackBox
|
|
388
513
|
// SSE command channel as `command: "status"`; YaverFeedback re-emits
|
|
389
514
|
// it as `yaverFeedback:status`. Show the most recent message in the
|
|
@@ -407,9 +532,10 @@ const FeedbackModal = () => {
|
|
|
407
532
|
return () => {
|
|
408
533
|
mountedRef.current = false;
|
|
409
534
|
sub.remove();
|
|
535
|
+
dogfoodSub.remove();
|
|
410
536
|
statusSub.remove();
|
|
411
537
|
};
|
|
412
|
-
}, [loadRunnerStatuses, loadSelectedMachine]);
|
|
538
|
+
}, [loadDogfoodOnboarding, loadRunnerStatuses, loadSelectedMachine]);
|
|
413
539
|
(0, react_1.useEffect)(() => {
|
|
414
540
|
if (!visible)
|
|
415
541
|
return;
|
|
@@ -443,6 +569,12 @@ const FeedbackModal = () => {
|
|
|
443
569
|
hideSub.remove();
|
|
444
570
|
};
|
|
445
571
|
}, [visible]);
|
|
572
|
+
(0, react_1.useEffect)(() => {
|
|
573
|
+
if (!visible || !showVibeInput)
|
|
574
|
+
return;
|
|
575
|
+
const timer = setTimeout(() => scrollRef.current?.scrollToEnd({ animated: true }), keyboardInset > 0 ? 120 : 40);
|
|
576
|
+
return () => clearTimeout(timer);
|
|
577
|
+
}, [keyboardInset, showVibeInput, visible]);
|
|
446
578
|
const closeSoon = (0, react_1.useCallback)((delayMs = 1200) => {
|
|
447
579
|
setTimeout(() => {
|
|
448
580
|
if (mountedRef.current)
|
|
@@ -458,6 +590,9 @@ const FeedbackModal = () => {
|
|
|
458
590
|
setShowVibeInput(false);
|
|
459
591
|
setVibePrompt('');
|
|
460
592
|
setRunnerStatusError(null);
|
|
593
|
+
void dogfoodControllerRef.current?.stop().catch(() => { });
|
|
594
|
+
dogfoodControllerRef.current = null;
|
|
595
|
+
YaverFeedback_1.YaverFeedback.clearDogfoodOnboarding();
|
|
461
596
|
}, []);
|
|
462
597
|
// Helper: run a P2P call; on network failure, ask YaverFeedback to
|
|
463
598
|
// re-query Convex for the fresh IP and retry once. Solves the common
|
|
@@ -555,8 +690,11 @@ const FeedbackModal = () => {
|
|
|
555
690
|
throw new Error('Selected machine is offline. Start `yaver serve` on it first.');
|
|
556
691
|
}
|
|
557
692
|
let ackMessage = `${reloadAction.label} requested.`;
|
|
558
|
-
await runWithReconnect(async (
|
|
559
|
-
const
|
|
693
|
+
await runWithReconnect(async () => {
|
|
694
|
+
const renderClient = YaverFeedback_1.YaverFeedback.getRenderP2PClient();
|
|
695
|
+
if (!renderClient)
|
|
696
|
+
throw new Error('Render machine is not connected yet.');
|
|
697
|
+
const ack = await renderClient.reloadWithMode(reloadAction.mode, devSnapshot);
|
|
560
698
|
ackMessage = ack.message;
|
|
561
699
|
setToast(ack.message);
|
|
562
700
|
setProgress(0.2);
|
|
@@ -608,8 +746,11 @@ const FeedbackModal = () => {
|
|
|
608
746
|
// map this app to its MobileProject scan entry without needing
|
|
609
747
|
// `yaver dev start` to have been run.
|
|
610
748
|
let ackMessage = 'Reload request acknowledged.';
|
|
611
|
-
await runWithReconnect(async (
|
|
612
|
-
const
|
|
749
|
+
await runWithReconnect(async () => {
|
|
750
|
+
const renderClient = YaverFeedback_1.YaverFeedback.getRenderP2PClient();
|
|
751
|
+
if (!renderClient)
|
|
752
|
+
throw new Error('Render machine is not connected yet.');
|
|
753
|
+
const ack = await renderClient.reloadApp('bundle');
|
|
613
754
|
ackMessage = ack.message;
|
|
614
755
|
setToast(ack.message);
|
|
615
756
|
setProgress(0.2);
|
|
@@ -837,6 +978,7 @@ const FeedbackModal = () => {
|
|
|
837
978
|
taskId: result.taskId,
|
|
838
979
|
initialPrompt: promptText,
|
|
839
980
|
project: identity.projectName,
|
|
981
|
+
projectPath: identity.projectPath,
|
|
840
982
|
runner: preferredRunner ?? undefined,
|
|
841
983
|
model: preferredModel ?? undefined,
|
|
842
984
|
});
|
|
@@ -857,6 +999,7 @@ const FeedbackModal = () => {
|
|
|
857
999
|
}, [closeSoon, isRecordingVideo, lastVideo]);
|
|
858
1000
|
*/
|
|
859
1001
|
const busy = action !== 'idle';
|
|
1002
|
+
const machineRouting = YaverFeedback_1.YaverFeedback.getMachineRouting();
|
|
860
1003
|
const readyRunnerCount = runnerCards.filter((row) => row.ready || row.authConfigured).length;
|
|
861
1004
|
const missingRunnerCount = runnerCards.filter((row) => !row.installed).length;
|
|
862
1005
|
const needsAuthRunnerCount = runnerCards.filter((row) => row.installed && !row.authConfigured && !row.ready).length;
|
|
@@ -864,14 +1007,18 @@ const FeedbackModal = () => {
|
|
|
864
1007
|
// for the live chat screen. The chat manages its own SSE
|
|
865
1008
|
// subscription, multi-turn follow-ups, and Reload button. Closing
|
|
866
1009
|
// the chat returns to idle and clears the active vibe.
|
|
867
|
-
if (
|
|
1010
|
+
if (activeVibe) {
|
|
868
1011
|
const client = YaverFeedback_1.YaverFeedback.getP2PClient();
|
|
869
1012
|
return (<>
|
|
870
1013
|
<AuthOverlay_1.AuthOverlay />
|
|
871
1014
|
<QuickActionIcon_1.QuickActionIcon />
|
|
872
|
-
<
|
|
873
|
-
|
|
874
|
-
|
|
1015
|
+
<YaverModeBadgeGate />
|
|
1016
|
+
<react_native_1.Modal visible={visible} animationType="slide" transparent onRequestClose={handleClose}>
|
|
1017
|
+
{client ? (<VibeChatScreen_1.VibeChatScreen client={client} initialTaskId={activeVibe.taskId} initialUserPrompt={activeVibe.initialPrompt} project={activeVibe.project} projectPath={activeVibe.projectPath} runner={activeVibe.runner} model={activeVibe.model} voiceInputEnabled={YaverFeedback_1.YaverFeedback.getConfig()?.voiceInputEnabled === true} onClose={() => setActiveVibe(null)} onNewTopic={() => {
|
|
1018
|
+
setActiveVibe(null);
|
|
1019
|
+
setShowVibeInput(true);
|
|
1020
|
+
}} onMinimize={handleClose} codingMachine={YaverFeedback_1.YaverFeedback.getMachineRouting().codingDeviceId} renderMachine={YaverFeedback_1.YaverFeedback.getMachineRouting().renderDeviceId} onReload={async () => {
|
|
1021
|
+
const c = YaverFeedback_1.YaverFeedback.getRenderP2PClient();
|
|
875
1022
|
if (!c)
|
|
876
1023
|
throw new Error('Not connected');
|
|
877
1024
|
await c.reloadApp();
|
|
@@ -882,6 +1029,7 @@ const FeedbackModal = () => {
|
|
|
882
1029
|
return (<>
|
|
883
1030
|
<AuthOverlay_1.AuthOverlay />
|
|
884
1031
|
<QuickActionIcon_1.QuickActionIcon />
|
|
1032
|
+
<YaverModeBadgeGate />
|
|
885
1033
|
{visible && (<react_native_1.Modal visible={visible} animationType="slide" transparent onRequestClose={handleClose}>
|
|
886
1034
|
<react_native_1.Pressable style={styles.overlay} onPress={handleClose}>
|
|
887
1035
|
<react_native_1.KeyboardAvoidingView behavior={react_native_1.Platform.OS === 'ios' ? 'padding' : 'height'} keyboardVerticalOffset={react_native_1.Platform.OS === 'ios' ? 12 : 0} style={styles.kbAvoider} pointerEvents="box-none">
|
|
@@ -904,19 +1052,80 @@ const FeedbackModal = () => {
|
|
|
904
1052
|
e.stopPropagation();
|
|
905
1053
|
react_native_1.Keyboard.dismiss();
|
|
906
1054
|
}}>
|
|
907
|
-
<react_native_1.ScrollView style={styles.scroll} contentContainerStyle={[
|
|
1055
|
+
<react_native_1.ScrollView ref={scrollRef} style={styles.scroll} contentContainerStyle={[
|
|
908
1056
|
styles.scrollContent,
|
|
909
1057
|
showVibeInput && keyboardInset > 0
|
|
910
1058
|
? { paddingBottom: 8 + keyboardInset }
|
|
911
1059
|
: null,
|
|
912
|
-
]} keyboardShouldPersistTaps="handled" keyboardDismissMode={react_native_1.Platform.OS === 'ios' ? 'interactive' : 'on-drag'}>
|
|
1060
|
+
]} keyboardShouldPersistTaps="handled" keyboardDismissMode={react_native_1.Platform.OS === 'ios' ? 'interactive' : 'on-drag'} contentInsetAdjustmentBehavior="always" automaticallyAdjustKeyboardInsets={react_native_1.Platform.OS === 'ios'}>
|
|
913
1061
|
<react_native_1.View style={styles.header}>
|
|
914
|
-
<react_native_1.Text style={styles.title}>
|
|
1062
|
+
<react_native_1.Text style={styles.title}>
|
|
1063
|
+
{dogfoodActive ? `${YaverFeedback_1.YaverFeedback.getDogfoodStatus().label || 'App'} Developer Mode` : 'Send Feedback'}
|
|
1064
|
+
</react_native_1.Text>
|
|
915
1065
|
<react_native_1.Pressable onPress={handleClose} hitSlop={12} style={styles.closeBtn} accessibilityRole="button" accessibilityLabel="Close">
|
|
916
1066
|
<react_native_1.Text style={styles.closeIcon}>×</react_native_1.Text>
|
|
917
1067
|
</react_native_1.Pressable>
|
|
918
1068
|
</react_native_1.View>
|
|
919
1069
|
|
|
1070
|
+
<react_native_1.View style={styles.tabs} accessibilityRole="tablist">
|
|
1071
|
+
{['chat', 'settings'].map((tab) => (<react_native_1.Pressable key={tab} onPress={() => setActiveTab(tab)} style={[styles.tab, activeTab === tab && styles.tabSelected]} accessibilityRole="tab" accessibilityState={{ selected: activeTab === tab }}>
|
|
1072
|
+
<react_native_1.Text style={[styles.tabText, activeTab === tab && styles.tabTextSelected]}>{tab === 'chat' ? 'Chat' : 'Settings'}</react_native_1.Text>
|
|
1073
|
+
</react_native_1.Pressable>))}
|
|
1074
|
+
</react_native_1.View>
|
|
1075
|
+
|
|
1076
|
+
<react_native_1.View style={[styles.tabContent, activeTab !== 'settings' && styles.hidden]}>
|
|
1077
|
+
<>
|
|
1078
|
+
{YaverFeedback_1.YaverFeedback.getDogfoodOnboarding() ? (<react_native_1.View style={styles.dogfoodWizard}>
|
|
1079
|
+
<react_native_1.Text style={styles.dogfoodWizardTitle}>Dogfood this app</react_native_1.Text>
|
|
1080
|
+
<react_native_1.Text style={styles.dogfoodWizardHint}>
|
|
1081
|
+
OAuth ✓ · machine {machineCard.device ? '✓' : 'required'} · installation {dogfoodEnrollment?.status || 'checking'}
|
|
1082
|
+
</react_native_1.Text>
|
|
1083
|
+
{dogfoodEnrollment?.installationId ? (<react_native_1.Text selectable style={styles.dogfoodInstallationId}>
|
|
1084
|
+
This device · {dogfoodEnrollment.installationId}
|
|
1085
|
+
</react_native_1.Text>) : null}
|
|
1086
|
+
{dogfoodEnrollment?.status !== 'active' ? (<react_native_1.View style={styles.dogfoodPendingBox}>
|
|
1087
|
+
<react_native_1.Text style={styles.dogfoodPendingText}>
|
|
1088
|
+
{dogfoodEnrollment?.error
|
|
1089
|
+
|| 'Approve this installation from Yaver → Settings → Third-party app testing. A UUID alone never grants access.'}
|
|
1090
|
+
</react_native_1.Text>
|
|
1091
|
+
<react_native_1.Pressable onPress={() => void loadDogfoodOnboarding()} style={({ pressed }) => [styles.runnerRefreshBtn, pressed && styles.buttonPressed]}>
|
|
1092
|
+
<react_native_1.Text style={styles.runnerRefreshBtnText}>{dogfoodSetupLoading ? 'Checking…' : 'Check approval'}</react_native_1.Text>
|
|
1093
|
+
</react_native_1.Pressable>
|
|
1094
|
+
</react_native_1.View>) : (<>
|
|
1095
|
+
<react_native_1.Text style={styles.dogfoodStepLabel}>Project on selected machine</react_native_1.Text>
|
|
1096
|
+
<react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.dogfoodChoiceRow}>
|
|
1097
|
+
{dogfoodProjects.map((project) => (<react_native_1.Pressable key={project.path} onPress={() => {
|
|
1098
|
+
setDogfoodProject(project);
|
|
1099
|
+
setDogfoodLane((0, DogfoodRuntime_1.defaultDogfoodLane)(project.framework || YaverFeedback_1.YaverFeedback.getDogfoodOnboarding()?.framework || 'expo'));
|
|
1100
|
+
setDogfoodRuntime(null);
|
|
1101
|
+
}} style={[styles.dogfoodChoice, dogfoodProject?.path === project.path && styles.dogfoodChoiceSelected]}>
|
|
1102
|
+
<react_native_1.Text style={[styles.dogfoodChoiceText, dogfoodProject?.path === project.path && styles.dogfoodChoiceTextSelected]}>{project.name}</react_native_1.Text>
|
|
1103
|
+
</react_native_1.Pressable>))}
|
|
1104
|
+
</react_native_1.ScrollView>
|
|
1105
|
+
<react_native_1.Text style={styles.dogfoodStepLabel}>Runtime lane</react_native_1.Text>
|
|
1106
|
+
<react_native_1.View style={styles.dogfoodChoiceRow}>
|
|
1107
|
+
{(0, DogfoodRuntime_1.dogfoodLaneOptions)(dogfoodProject?.framework || YaverFeedback_1.YaverFeedback.getDogfoodOnboarding()?.framework || 'expo', { nativeRuntimeAvailable: dogfoodNativeAvailable }).map((option) => (<react_native_1.Pressable key={option.lane} onPress={() => option.supported && setDogfoodLane(option.lane)} style={[
|
|
1108
|
+
styles.dogfoodChoice,
|
|
1109
|
+
dogfoodLane === option.lane && styles.dogfoodChoiceSelected,
|
|
1110
|
+
!option.supported && styles.actionBtnDisabled,
|
|
1111
|
+
]} accessibilityState={{ disabled: !option.supported, selected: dogfoodLane === option.lane }}>
|
|
1112
|
+
<react_native_1.Text style={[styles.dogfoodChoiceText, dogfoodLane === option.lane && styles.dogfoodChoiceTextSelected]}>{option.label}</react_native_1.Text>
|
|
1113
|
+
</react_native_1.Pressable>))}
|
|
1114
|
+
</react_native_1.View>
|
|
1115
|
+
<react_native_1.Text style={styles.dogfoodWizardHint}>
|
|
1116
|
+
Runner: {[preferredRunner || 'automatic', preferredModel].filter(Boolean).join(' · ')}. Change it under Coding Agents below.
|
|
1117
|
+
</react_native_1.Text>
|
|
1118
|
+
<ActionRow label={dogfoodRuntime && !['idle', 'ready', 'failed', 'stopped'].includes(dogfoodRuntime.phase) ? dogfoodRuntime.message : 'Start Dogfood'} tint="#818cf8" onPress={() => void startDogfoodRuntime()} disabled={!dogfoodProject || !!(dogfoodRuntime && !['idle', 'ready', 'failed', 'stopped'].includes(dogfoodRuntime.phase))} busy={!!dogfoodRuntime && !['idle', 'ready', 'failed', 'stopped'].includes(dogfoodRuntime.phase)}/>
|
|
1119
|
+
{dogfoodRuntime ? (<react_native_1.View style={styles.dogfoodConsole}>
|
|
1120
|
+
<react_native_1.Text style={styles.dogfoodConsoleStatus}>{dogfoodRuntime.message}</react_native_1.Text>
|
|
1121
|
+
{dogfoodRuntime.logs.slice(-80).map((line, index) => (<react_native_1.Text key={`${line.at}-${index}`} selectable style={styles.dogfoodConsoleLine}>{line.text}</react_native_1.Text>))}
|
|
1122
|
+
{dogfoodRuntime.failure ? (<react_native_1.Text style={styles.dogfoodConsoleError}>{dogfoodRuntime.failure.error}{'\n'}{dogfoodRuntime.failure.remedy}</react_native_1.Text>) : null}
|
|
1123
|
+
{dogfoodRuntime.result?.url ? (<react_native_1.Pressable onPress={() => void react_native_1.Linking.openURL(dogfoodRuntime.result.url)} style={styles.dogfoodOpenPreview}>
|
|
1124
|
+
<react_native_1.Text style={styles.dogfoodOpenPreviewText}>Open dogfooded app</react_native_1.Text>
|
|
1125
|
+
</react_native_1.Pressable>) : null}
|
|
1126
|
+
</react_native_1.View>) : null}
|
|
1127
|
+
</>)}
|
|
1128
|
+
</react_native_1.View>) : null}
|
|
920
1129
|
<react_native_1.Pressable onPress={() => {
|
|
921
1130
|
if (!YaverFeedback_1.YaverFeedback.isAuthed()) {
|
|
922
1131
|
YaverFeedback_1.YaverFeedback.showLogin();
|
|
@@ -937,7 +1146,7 @@ const FeedbackModal = () => {
|
|
|
937
1146
|
machineCard.status === 'attention' && styles.machineDotAttention,
|
|
938
1147
|
machineCard.status === 'offline' && styles.machineDotOffline,
|
|
939
1148
|
]}/>
|
|
940
|
-
<react_native_1.Text style={styles.machineLabel}>
|
|
1149
|
+
<react_native_1.Text style={styles.machineLabel}>Coding Machine</react_native_1.Text>
|
|
941
1150
|
</react_native_1.View>
|
|
942
1151
|
<react_native_1.Text style={styles.machineAction}>
|
|
943
1152
|
{machineCard.loading ? 'Refreshing…' : 'Change'}
|
|
@@ -949,6 +1158,17 @@ const FeedbackModal = () => {
|
|
|
949
1158
|
<react_native_1.Text style={styles.machineMeta}>{machineCard.detail}</react_native_1.Text>
|
|
950
1159
|
</react_native_1.Pressable>
|
|
951
1160
|
|
|
1161
|
+
<react_native_1.View style={styles.machineRoutes}>
|
|
1162
|
+
<react_native_1.View style={styles.machineRouteCard}>
|
|
1163
|
+
<react_native_1.Text style={styles.machineRouteLabel}>Coding machine</react_native_1.Text>
|
|
1164
|
+
<react_native_1.Text style={styles.machineRouteValue} numberOfLines={1}>{machineRouting.codingDeviceId || machineCard.title}</react_native_1.Text>
|
|
1165
|
+
</react_native_1.View>
|
|
1166
|
+
<react_native_1.View style={styles.machineRouteCard}>
|
|
1167
|
+
<react_native_1.Text style={styles.machineRouteLabel}>Render machine</react_native_1.Text>
|
|
1168
|
+
<react_native_1.Text style={styles.machineRouteValue} numberOfLines={1}>{machineRouting.renderDeviceId || machineRouting.codingDeviceId || machineCard.title}</react_native_1.Text>
|
|
1169
|
+
</react_native_1.View>
|
|
1170
|
+
</react_native_1.View>
|
|
1171
|
+
|
|
952
1172
|
<react_native_1.View style={styles.runnerSection}>
|
|
953
1173
|
<react_native_1.View style={styles.runnerSectionHeader}>
|
|
954
1174
|
<react_native_1.View style={{ flex: 1 }}>
|
|
@@ -969,6 +1189,13 @@ const FeedbackModal = () => {
|
|
|
969
1189
|
</react_native_1.Pressable>
|
|
970
1190
|
</react_native_1.View>
|
|
971
1191
|
|
|
1192
|
+
<react_native_1.View style={styles.routingSummary}>
|
|
1193
|
+
<react_native_1.Text style={styles.routingSummaryLabel}>Vibing uses</react_native_1.Text>
|
|
1194
|
+
<react_native_1.Text style={styles.routingSummaryValue} numberOfLines={1}>
|
|
1195
|
+
{[preferredRunner || 'automatic runner', preferredModel].filter(Boolean).join(' · ')}
|
|
1196
|
+
</react_native_1.Text>
|
|
1197
|
+
</react_native_1.View>
|
|
1198
|
+
|
|
972
1199
|
{runnerCards.map((row) => (<react_native_1.View key={row.id} style={[
|
|
973
1200
|
styles.runnerCard,
|
|
974
1201
|
row.tone === 'ok' && styles.runnerCardOk,
|
|
@@ -987,13 +1214,29 @@ const FeedbackModal = () => {
|
|
|
987
1214
|
{row.statusLine}
|
|
988
1215
|
</react_native_1.Text>
|
|
989
1216
|
</react_native_1.View>
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
1217
|
+
<react_native_1.View style={styles.runnerCardActions}>
|
|
1218
|
+
{row.ready ? (<react_native_1.Pressable onPress={() => {
|
|
1219
|
+
const nextModel = row.models?.find((model) => model.isDefault)?.id || row.models?.[0]?.id || '';
|
|
1220
|
+
setPreferredRunnerState(row.id);
|
|
1221
|
+
setPreferredModelState(nextModel);
|
|
1222
|
+
void (0, preferences_1.setPreferredRunner)(row.id);
|
|
1223
|
+
void (0, preferences_1.setPreferredModel)(nextModel || null);
|
|
1224
|
+
}} style={({ pressed }) => [styles.runnerActionBtn, preferredRunner === row.id && styles.runnerActionBtnSelected, pressed && styles.buttonPressed]} accessibilityRole="button" accessibilityLabel={`Use ${row.name} for Vibing`}>
|
|
1225
|
+
<react_native_1.Text style={styles.runnerActionBtnText}>{preferredRunner === row.id ? 'Using' : 'Use'}</react_native_1.Text>
|
|
1226
|
+
</react_native_1.Pressable>) : null}
|
|
1227
|
+
{row.actionRunner ? (<react_native_1.Pressable onPress={() => setRunnerAuthModal(row.actionRunner ?? null)} style={({ pressed }) => [styles.runnerActionBtn, pressed && styles.buttonPressed]} accessibilityRole="button" accessibilityLabel={`${row.actionLabel} ${row.name}`}>
|
|
1228
|
+
<react_native_1.Text style={styles.runnerActionBtnText}>{row.actionLabel}</react_native_1.Text>
|
|
1229
|
+
</react_native_1.Pressable>) : null}
|
|
1230
|
+
</react_native_1.View>
|
|
996
1231
|
</react_native_1.View>
|
|
1232
|
+
{preferredRunner === row.id && (row.models?.length || 0) > 0 ? (<react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.modelChoiceRow}>
|
|
1233
|
+
{row.models.map((model) => (<react_native_1.Pressable key={model.id} onPress={() => {
|
|
1234
|
+
setPreferredModelState(model.id);
|
|
1235
|
+
void (0, preferences_1.setPreferredModel)(model.id);
|
|
1236
|
+
}} style={[styles.modelChoice, preferredModel === model.id && styles.modelChoiceSelected]} accessibilityRole="button" accessibilityLabel={`Use ${model.name || model.id} model`}>
|
|
1237
|
+
<react_native_1.Text style={[styles.modelChoiceText, preferredModel === model.id && styles.modelChoiceTextSelected]}>{model.name || model.id}</react_native_1.Text>
|
|
1238
|
+
</react_native_1.Pressable>))}
|
|
1239
|
+
</react_native_1.ScrollView>) : null}
|
|
997
1240
|
{row.detail ? (<react_native_1.Text style={styles.runnerCardDetail}>{row.detail}</react_native_1.Text>) : null}
|
|
998
1241
|
</react_native_1.View>))}
|
|
999
1242
|
|
|
@@ -1073,7 +1316,10 @@ const FeedbackModal = () => {
|
|
|
1073
1316
|
: reloadAction.disabledReason}
|
|
1074
1317
|
</react_native_1.Text>
|
|
1075
1318
|
</react_native_1.View>))}
|
|
1319
|
+
</>
|
|
1320
|
+
</react_native_1.View>
|
|
1076
1321
|
|
|
1322
|
+
<react_native_1.View style={[styles.tabContent, activeTab !== 'chat' && styles.hidden]}>
|
|
1077
1323
|
{/* 3. Vibing — expands to an input box on first tap
|
|
1078
1324
|
so the user says WHAT they want to vibe on, just
|
|
1079
1325
|
like the Yaver mobile app's Vibing tab. Second
|
|
@@ -1100,7 +1346,7 @@ const FeedbackModal = () => {
|
|
|
1100
1346
|
</react_native_1.Text>)}
|
|
1101
1347
|
|
|
1102
1348
|
{/* Screenshot & Fix */}
|
|
1103
|
-
<ActionRow label={action === 'capturing' ? 'Working…' : 'Screenshot & Fix'} tint="#22c55e" onPress={handleScreenshotAndFix} disabled={busy} busy={action === 'capturing'}/>
|
|
1349
|
+
{!dogfoodActive ? <ActionRow label={action === 'capturing' ? 'Working…' : 'Screenshot & Fix'} tint="#22c55e" onPress={handleScreenshotAndFix} disabled={busy} busy={action === 'capturing'}/> : null}
|
|
1104
1350
|
|
|
1105
1351
|
{/* Deploy — opens an inline panel that talks to
|
|
1106
1352
|
/fleet/deploy-options on the agent and lets the user
|
|
@@ -1108,7 +1354,8 @@ const FeedbackModal = () => {
|
|
|
1108
1354
|
it on. Capabilities (e.g. "Linux can't TestFlight")
|
|
1109
1355
|
come from the agent's doctor probes — no client-side
|
|
1110
1356
|
platform smarts here. */}
|
|
1111
|
-
{!showDeploy ? (<ActionRow label="Deploy" tint="#7f8cf7" onPress={() => setShowDeploy(true)} disabled={busy}/>) : (<DeployPanel_1.DeployPanel onClose={() => setShowDeploy(false)}/>)}
|
|
1357
|
+
{!dogfoodActive && (!showDeploy ? (<ActionRow label="Deploy" tint="#7f8cf7" onPress={() => setShowDeploy(true)} disabled={busy}/>) : (<DeployPanel_1.DeployPanel onClose={() => setShowDeploy(false)}/>))}
|
|
1358
|
+
</react_native_1.View>
|
|
1112
1359
|
|
|
1113
1360
|
{progress !== null && (<react_native_1.View style={styles.progressTrack}>
|
|
1114
1361
|
<react_native_1.View style={[
|
|
@@ -1149,6 +1396,24 @@ const ActionRow = ({ label, tint, onPress, disabled, busy, }) => (<react_native_
|
|
|
1149
1396
|
{busy ? (<react_native_1.ActivityIndicator color={tint} size="small"/>) : (<react_native_1.Text style={[styles.actionText, { color: tint }]}>{label}</react_native_1.Text>)}
|
|
1150
1397
|
</react_native_1.Pressable>);
|
|
1151
1398
|
const styles = react_native_1.StyleSheet.create({
|
|
1399
|
+
dogfoodWizard: { gap: 10, borderRadius: 14, borderWidth: 1, borderColor: 'rgba(129,140,248,0.38)', backgroundColor: 'rgba(129,140,248,0.08)', padding: 13 },
|
|
1400
|
+
dogfoodWizardTitle: { color: '#222229', fontSize: 17, fontWeight: '800' },
|
|
1401
|
+
dogfoodWizardHint: { color: '#6f6f7b', fontSize: 12, lineHeight: 17 },
|
|
1402
|
+
dogfoodInstallationId: { color: '#6555df', fontSize: 11, fontFamily: react_native_1.Platform.select({ ios: 'Menlo', android: 'monospace', default: 'monospace' }) },
|
|
1403
|
+
dogfoodPendingBox: { gap: 9, borderRadius: 11, padding: 10, backgroundColor: 'rgba(245,158,11,0.10)' },
|
|
1404
|
+
dogfoodPendingText: { color: '#8a5a10', fontSize: 12, lineHeight: 17 },
|
|
1405
|
+
dogfoodStepLabel: { color: '#555561', fontSize: 11, fontWeight: '800', textTransform: 'uppercase', letterSpacing: 0.7 },
|
|
1406
|
+
dogfoodChoiceRow: { flexDirection: 'row', gap: 7 },
|
|
1407
|
+
dogfoodChoice: { borderRadius: 9, borderWidth: 1, borderColor: '#d8d8e3', backgroundColor: '#fff', paddingHorizontal: 10, paddingVertical: 8 },
|
|
1408
|
+
dogfoodChoiceSelected: { borderColor: '#818cf8', backgroundColor: 'rgba(129,140,248,0.18)' },
|
|
1409
|
+
dogfoodChoiceText: { color: '#666671', fontSize: 12, fontWeight: '700' },
|
|
1410
|
+
dogfoodChoiceTextSelected: { color: '#5645d8' },
|
|
1411
|
+
dogfoodConsole: { maxHeight: 260, gap: 4, borderRadius: 11, padding: 10, backgroundColor: '#15151b' },
|
|
1412
|
+
dogfoodConsoleStatus: { color: '#a5b4fc', fontSize: 12, fontWeight: '800' },
|
|
1413
|
+
dogfoodConsoleLine: { color: '#d1d5db', fontSize: 10, lineHeight: 14, fontFamily: react_native_1.Platform.select({ ios: 'Menlo', android: 'monospace', default: 'monospace' }) },
|
|
1414
|
+
dogfoodConsoleError: { color: '#fca5a5', fontSize: 11, lineHeight: 16, marginTop: 5 },
|
|
1415
|
+
dogfoodOpenPreview: { alignSelf: 'flex-start', borderRadius: 9, paddingHorizontal: 11, paddingVertical: 8, marginTop: 6, backgroundColor: '#6555df' },
|
|
1416
|
+
dogfoodOpenPreviewText: { color: '#fff', fontSize: 12, fontWeight: '800' },
|
|
1152
1417
|
reloadRow: {
|
|
1153
1418
|
gap: 4,
|
|
1154
1419
|
},
|
|
@@ -1167,7 +1432,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1167
1432
|
gap: 10,
|
|
1168
1433
|
},
|
|
1169
1434
|
vibeInput: {
|
|
1170
|
-
color: '#
|
|
1435
|
+
color: '#24242b',
|
|
1171
1436
|
fontSize: 15,
|
|
1172
1437
|
minHeight: 64,
|
|
1173
1438
|
textAlignVertical: 'top',
|
|
@@ -1218,7 +1483,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1218
1483
|
justifyContent: 'flex-end',
|
|
1219
1484
|
},
|
|
1220
1485
|
modal: {
|
|
1221
|
-
backgroundColor: '#
|
|
1486
|
+
backgroundColor: '#f8f8fb',
|
|
1222
1487
|
borderTopLeftRadius: 22,
|
|
1223
1488
|
borderTopRightRadius: 22,
|
|
1224
1489
|
padding: 22,
|
|
@@ -1242,7 +1507,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1242
1507
|
title: {
|
|
1243
1508
|
fontSize: 20,
|
|
1244
1509
|
fontWeight: '700',
|
|
1245
|
-
color: '#
|
|
1510
|
+
color: '#17171d',
|
|
1246
1511
|
},
|
|
1247
1512
|
closeBtn: {
|
|
1248
1513
|
width: 36,
|
|
@@ -1250,10 +1515,10 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1250
1515
|
borderRadius: 18,
|
|
1251
1516
|
alignItems: 'center',
|
|
1252
1517
|
justifyContent: 'center',
|
|
1253
|
-
backgroundColor: '
|
|
1518
|
+
backgroundColor: '#ededf3',
|
|
1254
1519
|
},
|
|
1255
1520
|
closeIcon: {
|
|
1256
|
-
color: '#
|
|
1521
|
+
color: '#656570',
|
|
1257
1522
|
fontSize: 22,
|
|
1258
1523
|
lineHeight: 24,
|
|
1259
1524
|
fontWeight: '400',
|
|
@@ -1272,12 +1537,19 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1272
1537
|
fontSize: 15,
|
|
1273
1538
|
fontWeight: '700',
|
|
1274
1539
|
},
|
|
1540
|
+
tabs: { flexDirection: 'row', gap: 6, padding: 3, borderRadius: 12, backgroundColor: '#ededf3' },
|
|
1541
|
+
tab: { flex: 1, minHeight: 36, borderRadius: 9, alignItems: 'center', justifyContent: 'center' },
|
|
1542
|
+
tabSelected: { backgroundColor: '#fff' },
|
|
1543
|
+
tabText: { color: '#858590', fontSize: 12, fontWeight: '700' },
|
|
1544
|
+
tabTextSelected: { color: '#6252e8' },
|
|
1545
|
+
tabContent: { gap: 12 },
|
|
1546
|
+
hidden: { display: 'none' },
|
|
1275
1547
|
machineCard: {
|
|
1276
1548
|
borderRadius: 14,
|
|
1277
1549
|
borderWidth: 1,
|
|
1278
1550
|
padding: 14,
|
|
1279
|
-
backgroundColor: '
|
|
1280
|
-
borderColor: '
|
|
1551
|
+
backgroundColor: '#fff',
|
|
1552
|
+
borderColor: '#e1e1e8',
|
|
1281
1553
|
},
|
|
1282
1554
|
machineCardLive: {
|
|
1283
1555
|
backgroundColor: 'rgba(34,197,94,0.10)',
|
|
@@ -1291,6 +1563,10 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1291
1563
|
backgroundColor: 'rgba(239,68,68,0.10)',
|
|
1292
1564
|
borderColor: 'rgba(239,68,68,0.35)',
|
|
1293
1565
|
},
|
|
1566
|
+
machineRoutes: { flexDirection: 'row', gap: 8 },
|
|
1567
|
+
machineRouteCard: { flex: 1, minWidth: 0, borderRadius: 11, padding: 10, gap: 3, backgroundColor: '#fff', borderWidth: 1, borderColor: '#e1e1e8' },
|
|
1568
|
+
machineRouteLabel: { color: '#7b7b86', fontSize: 10, fontWeight: '700', textTransform: 'uppercase' },
|
|
1569
|
+
machineRouteValue: { color: '#222229', fontSize: 12, fontWeight: '700' },
|
|
1294
1570
|
machineHeader: {
|
|
1295
1571
|
flexDirection: 'row',
|
|
1296
1572
|
alignItems: 'center',
|
|
@@ -1318,7 +1594,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1318
1594
|
backgroundColor: '#ef4444',
|
|
1319
1595
|
},
|
|
1320
1596
|
machineLabel: {
|
|
1321
|
-
color: '#
|
|
1597
|
+
color: '#73737e',
|
|
1322
1598
|
fontSize: 12,
|
|
1323
1599
|
fontWeight: '700',
|
|
1324
1600
|
textTransform: 'uppercase',
|
|
@@ -1330,12 +1606,12 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1330
1606
|
fontWeight: '700',
|
|
1331
1607
|
},
|
|
1332
1608
|
machineName: {
|
|
1333
|
-
color: '#
|
|
1609
|
+
color: '#222229',
|
|
1334
1610
|
fontSize: 16,
|
|
1335
1611
|
fontWeight: '700',
|
|
1336
1612
|
},
|
|
1337
1613
|
machineMeta: {
|
|
1338
|
-
color: '#
|
|
1614
|
+
color: '#73737e',
|
|
1339
1615
|
fontSize: 12,
|
|
1340
1616
|
marginTop: 4,
|
|
1341
1617
|
lineHeight: 17,
|
|
@@ -1350,33 +1626,33 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1350
1626
|
gap: 10,
|
|
1351
1627
|
},
|
|
1352
1628
|
runnerSectionTitle: {
|
|
1353
|
-
color: '#
|
|
1629
|
+
color: '#222229',
|
|
1354
1630
|
fontSize: 16,
|
|
1355
1631
|
fontWeight: '700',
|
|
1356
1632
|
},
|
|
1357
1633
|
runnerSectionSubtitle: {
|
|
1358
1634
|
marginTop: 2,
|
|
1359
|
-
color: '#
|
|
1635
|
+
color: '#83838e',
|
|
1360
1636
|
fontSize: 12,
|
|
1361
1637
|
},
|
|
1362
1638
|
runnerRefreshBtn: {
|
|
1363
1639
|
borderRadius: 10,
|
|
1364
1640
|
borderWidth: 1,
|
|
1365
|
-
borderColor: '
|
|
1366
|
-
backgroundColor: '
|
|
1641
|
+
borderColor: '#dedee7',
|
|
1642
|
+
backgroundColor: '#fff',
|
|
1367
1643
|
paddingHorizontal: 10,
|
|
1368
1644
|
paddingVertical: 8,
|
|
1369
1645
|
},
|
|
1370
1646
|
runnerRefreshBtnText: {
|
|
1371
|
-
color: '#
|
|
1647
|
+
color: '#5f5f69',
|
|
1372
1648
|
fontSize: 12,
|
|
1373
1649
|
fontWeight: '600',
|
|
1374
1650
|
},
|
|
1375
1651
|
runnerCard: {
|
|
1376
1652
|
borderRadius: 12,
|
|
1377
1653
|
borderWidth: 1,
|
|
1378
|
-
borderColor: '
|
|
1379
|
-
backgroundColor: '
|
|
1654
|
+
borderColor: '#e2e2e9',
|
|
1655
|
+
backgroundColor: '#fff',
|
|
1380
1656
|
paddingHorizontal: 12,
|
|
1381
1657
|
paddingVertical: 11,
|
|
1382
1658
|
gap: 6,
|
|
@@ -1398,15 +1674,16 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1398
1674
|
alignItems: 'center',
|
|
1399
1675
|
gap: 10,
|
|
1400
1676
|
},
|
|
1677
|
+
runnerCardActions: { flexDirection: 'row', alignItems: 'center', gap: 6 },
|
|
1401
1678
|
runnerCardTitle: {
|
|
1402
|
-
color: '#
|
|
1679
|
+
color: '#222229',
|
|
1403
1680
|
fontSize: 14,
|
|
1404
1681
|
fontWeight: '700',
|
|
1405
1682
|
},
|
|
1406
1683
|
runnerCardStatus: {
|
|
1407
1684
|
marginTop: 2,
|
|
1408
1685
|
fontSize: 12,
|
|
1409
|
-
color: '#
|
|
1686
|
+
color: '#666671',
|
|
1410
1687
|
},
|
|
1411
1688
|
runnerCardStatusOk: {
|
|
1412
1689
|
color: '#86efac',
|
|
@@ -1418,7 +1695,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1418
1695
|
color: '#fca5a5',
|
|
1419
1696
|
},
|
|
1420
1697
|
runnerCardDetail: {
|
|
1421
|
-
color: '#
|
|
1698
|
+
color: '#858590',
|
|
1422
1699
|
fontSize: 11,
|
|
1423
1700
|
lineHeight: 16,
|
|
1424
1701
|
},
|
|
@@ -1435,6 +1712,15 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1435
1712
|
fontSize: 12,
|
|
1436
1713
|
fontWeight: '700',
|
|
1437
1714
|
},
|
|
1715
|
+
runnerActionBtnSelected: { borderColor: '#818cf8', backgroundColor: 'rgba(79,70,229,0.44)' },
|
|
1716
|
+
routingSummary: { flexDirection: 'row', alignItems: 'center', gap: 8, paddingHorizontal: 2 },
|
|
1717
|
+
routingSummaryLabel: { color: '#7c7c87', fontSize: 11, fontWeight: '600' },
|
|
1718
|
+
routingSummaryValue: { flex: 1, color: '#6555df', fontSize: 12, fontWeight: '700', textAlign: 'right' },
|
|
1719
|
+
modelChoiceRow: { gap: 6, paddingTop: 2 },
|
|
1720
|
+
modelChoice: { borderRadius: 9, borderWidth: 1, borderColor: 'rgba(148,163,184,0.18)', paddingHorizontal: 9, paddingVertical: 6 },
|
|
1721
|
+
modelChoiceSelected: { borderColor: '#818cf8', backgroundColor: 'rgba(79,70,229,0.30)' },
|
|
1722
|
+
modelChoiceText: { color: '#73737e', fontSize: 11 },
|
|
1723
|
+
modelChoiceTextSelected: { color: '#5e4ce6', fontWeight: '700' },
|
|
1438
1724
|
runnerSectionError: {
|
|
1439
1725
|
color: '#fca5a5',
|
|
1440
1726
|
fontSize: 12,
|
|
@@ -1446,7 +1732,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1446
1732
|
progressTrack: {
|
|
1447
1733
|
height: 6,
|
|
1448
1734
|
borderRadius: 3,
|
|
1449
|
-
backgroundColor: '
|
|
1735
|
+
backgroundColor: '#e5e5eb',
|
|
1450
1736
|
overflow: 'hidden',
|
|
1451
1737
|
marginTop: 4,
|
|
1452
1738
|
},
|
|
@@ -1473,10 +1759,10 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1473
1759
|
paddingVertical: 6,
|
|
1474
1760
|
paddingHorizontal: 10,
|
|
1475
1761
|
borderRadius: 10,
|
|
1476
|
-
backgroundColor: '
|
|
1762
|
+
backgroundColor: '#ededf3',
|
|
1477
1763
|
},
|
|
1478
1764
|
quickIconToggleText: {
|
|
1479
|
-
color: '#
|
|
1765
|
+
color: '#5f5f69',
|
|
1480
1766
|
fontSize: 12,
|
|
1481
1767
|
fontWeight: '700',
|
|
1482
1768
|
},
|
|
@@ -1488,25 +1774,25 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1488
1774
|
padding: 12,
|
|
1489
1775
|
},
|
|
1490
1776
|
quickIconNoteText: {
|
|
1491
|
-
color: '#
|
|
1777
|
+
color: '#8a5a12',
|
|
1492
1778
|
fontSize: 12,
|
|
1493
1779
|
lineHeight: 17,
|
|
1494
1780
|
},
|
|
1495
1781
|
iconSelector: {
|
|
1496
1782
|
borderRadius: 12,
|
|
1497
1783
|
borderWidth: 1,
|
|
1498
|
-
borderColor: '
|
|
1499
|
-
backgroundColor: '
|
|
1784
|
+
borderColor: '#e1e1e8',
|
|
1785
|
+
backgroundColor: '#fff',
|
|
1500
1786
|
padding: 12,
|
|
1501
1787
|
gap: 10,
|
|
1502
1788
|
},
|
|
1503
1789
|
iconSelectorTitle: {
|
|
1504
|
-
color: '#
|
|
1790
|
+
color: '#222229',
|
|
1505
1791
|
fontSize: 13,
|
|
1506
1792
|
fontWeight: '700',
|
|
1507
1793
|
},
|
|
1508
1794
|
iconSelectorText: {
|
|
1509
|
-
color: '#
|
|
1795
|
+
color: '#73737e',
|
|
1510
1796
|
fontSize: 12,
|
|
1511
1797
|
lineHeight: 17,
|
|
1512
1798
|
},
|
|
@@ -1520,8 +1806,8 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1520
1806
|
minWidth: 84,
|
|
1521
1807
|
borderRadius: 12,
|
|
1522
1808
|
borderWidth: 1,
|
|
1523
|
-
borderColor: '
|
|
1524
|
-
backgroundColor: '
|
|
1809
|
+
borderColor: '#e4e4ea',
|
|
1810
|
+
backgroundColor: '#f8f8fb',
|
|
1525
1811
|
paddingVertical: 10,
|
|
1526
1812
|
paddingHorizontal: 8,
|
|
1527
1813
|
alignItems: 'center',
|
|
@@ -1548,7 +1834,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1548
1834
|
fontWeight: '700',
|
|
1549
1835
|
},
|
|
1550
1836
|
iconOptionText: {
|
|
1551
|
-
color: '#
|
|
1837
|
+
color: '#555561',
|
|
1552
1838
|
fontSize: 11,
|
|
1553
1839
|
fontWeight: '600',
|
|
1554
1840
|
},
|
|
@@ -1556,14 +1842,14 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1556
1842
|
marginTop: 4,
|
|
1557
1843
|
borderRadius: 14,
|
|
1558
1844
|
borderWidth: 1,
|
|
1559
|
-
borderColor: '
|
|
1845
|
+
borderColor: '#e1e1e8',
|
|
1560
1846
|
paddingVertical: 15,
|
|
1561
1847
|
alignItems: 'center',
|
|
1562
1848
|
justifyContent: 'center',
|
|
1563
|
-
backgroundColor: '
|
|
1849
|
+
backgroundColor: '#fff',
|
|
1564
1850
|
},
|
|
1565
1851
|
cancelBtnText: {
|
|
1566
|
-
color: '#
|
|
1852
|
+
color: '#555561',
|
|
1567
1853
|
fontSize: 15,
|
|
1568
1854
|
fontWeight: '700',
|
|
1569
1855
|
},
|