yaver-feedback-react-native 0.9.0 → 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/app.plugin.js +126 -9
- package/dist/AuthOverlay.d.ts +1 -14
- package/dist/AuthOverlay.js +9 -62
- package/dist/BlackBox.js +9 -1
- package/dist/DeployPanel.js +65 -0
- package/dist/Discovery.js +13 -8
- package/dist/DogfoodRuntime.d.ts +124 -0
- package/dist/DogfoodRuntime.js +273 -0
- package/dist/FeedbackModal.js +505 -65
- 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 +178 -2
- package/dist/P2PClient.js +493 -3
- package/dist/P2PDogfoodDriver.d.ts +12 -0
- package/dist/P2PDogfoodDriver.js +118 -0
- package/dist/PairDeviceModal.d.ts +2 -3
- package/dist/ShakeDetector.js +2 -0
- package/dist/VibeChatScreen.d.ts +11 -1
- package/dist/VibeChatScreen.js +200 -41
- package/dist/YaverFeedback.d.ts +132 -0
- package/dist/YaverFeedback.js +633 -65
- package/dist/YaverModeBadge.d.ts +22 -0
- package/dist/YaverModeBadge.js +219 -0
- package/dist/__tests__/AuthDevices.test.js +1 -48
- package/dist/__tests__/BlackBox.relayPassword.test.d.ts +1 -0
- package/dist/__tests__/BlackBox.relayPassword.test.js +105 -0
- package/dist/__tests__/BlackBoxAutoStart.test.d.ts +1 -0
- package/dist/__tests__/BlackBoxAutoStart.test.js +91 -0
- package/dist/__tests__/BlackBoxAutoStartColdStart.test.d.ts +1 -0
- package/dist/__tests__/BlackBoxAutoStartColdStart.test.js +156 -0
- package/dist/__tests__/BrowserLaneIcon.test.d.ts +3 -0
- package/dist/__tests__/BrowserLaneIcon.test.js +80 -0
- package/dist/__tests__/DogfoodRuntime.test.d.ts +1 -0
- package/dist/__tests__/DogfoodRuntime.test.js +116 -0
- package/dist/__tests__/P2PClient.test.js +2 -2
- 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 -0
- package/dist/__tests__/ReportIdentity.test.js +180 -0
- package/dist/__tests__/SDKToken.test.js +1 -1
- package/dist/__tests__/ShakeToggle.test.d.ts +1 -0
- package/dist/__tests__/ShakeToggle.test.js +121 -0
- 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/__tests__/pickTargetDevice.test.d.ts +1 -0
- package/dist/__tests__/pickTargetDevice.test.js +89 -0
- package/dist/__tests__/reloadActions.test.d.ts +1 -0
- package/dist/__tests__/reloadActions.test.js +129 -0
- package/dist/__tests__/reloadActionsParity.test.d.ts +1 -0
- package/dist/__tests__/reloadActionsParity.test.js +42 -0
- package/dist/__tests__/types.test.js +5 -5
- 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 +1 -5
- package/dist/_core/device.js +5 -14
- 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 +17 -4
- package/dist/index.js +33 -7
- package/dist/reloadActions.d.ts +88 -0
- package/dist/reloadActions.js +200 -0
- package/dist/storeShots.d.ts +67 -0
- package/dist/storeShots.js +137 -0
- package/dist/types.d.ts +208 -8
- package/package.json +13 -4
- package/src/AuthOverlay.tsx +20 -106
- package/src/BlackBox.ts +10 -1
- package/src/DeployPanel.tsx +74 -0
- package/src/Discovery.ts +13 -8
- package/src/DogfoodRuntime.ts +373 -0
- package/src/FeedbackModal.tsx +619 -79
- package/src/LoginScreen.tsx +2 -22
- package/src/MachinePickerScreen.tsx +6 -21
- package/src/P2PClient.ts +580 -4
- package/src/P2PDogfoodDriver.ts +132 -0
- package/src/PairDeviceModal.tsx +2 -3
- package/src/ShakeDetector.ts +1 -0
- package/src/VibeChatScreen.tsx +232 -42
- package/src/YaverFeedback.ts +631 -68
- package/src/YaverModeBadge.tsx +234 -0
- package/src/__tests__/AuthDevices.test.ts +1 -52
- package/src/__tests__/BlackBox.relayPassword.test.ts +129 -0
- package/src/__tests__/BlackBoxAutoStart.test.ts +111 -0
- package/src/__tests__/BlackBoxAutoStartColdStart.test.ts +191 -0
- package/src/__tests__/BrowserLaneIcon.test.ts +85 -0
- package/src/__tests__/DogfoodRuntime.test.ts +135 -0
- package/src/__tests__/P2PClient.test.ts +2 -2
- package/src/__tests__/P2PDogfoodDriver.test.ts +80 -0
- package/src/__tests__/ReportIdentity.test.ts +212 -0
- package/src/__tests__/SDKToken.test.ts +1 -1
- package/src/__tests__/ShakeToggle.test.ts +153 -0
- 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/__tests__/pickTargetDevice.test.ts +101 -0
- package/src/__tests__/reloadActions.test.ts +171 -0
- package/src/__tests__/reloadActionsParity.test.ts +49 -0
- package/src/__tests__/types.test.ts +5 -5
- 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 +5 -16
- 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 +61 -11
- package/src/reloadActions.ts +273 -0
- package/src/storeShots.ts +189 -0
- package/src/types.ts +209 -8
- package/dist/GuestOnboardingScreen.d.ts +0 -8
- package/dist/GuestOnboardingScreen.js +0 -282
- package/src/GuestOnboardingScreen.tsx +0 -307
package/dist/FeedbackModal.js
CHANGED
|
@@ -39,12 +39,17 @@ const react_native_1 = require("react-native");
|
|
|
39
39
|
const YaverFeedback_1 = require("./YaverFeedback");
|
|
40
40
|
const capture_1 = require("./capture");
|
|
41
41
|
const upload_1 = require("./upload");
|
|
42
|
+
const P2PClient_1 = require("./P2PClient");
|
|
42
43
|
const AuthOverlay_1 = require("./AuthOverlay");
|
|
43
44
|
const QuickActionIcon_1 = require("./QuickActionIcon");
|
|
45
|
+
const YaverModeBadge_1 = require("./YaverModeBadge");
|
|
44
46
|
const VibeChatScreen_1 = require("./VibeChatScreen");
|
|
45
47
|
const DeployPanel_1 = require("./DeployPanel");
|
|
46
48
|
const auth_1 = require("./auth");
|
|
49
|
+
const reloadActions_1 = require("./reloadActions");
|
|
47
50
|
const preferences_1 = require("./preferences");
|
|
51
|
+
const DogfoodRuntime_1 = require("./DogfoodRuntime");
|
|
52
|
+
const P2PDogfoodDriver_1 = require("./P2PDogfoodDriver");
|
|
48
53
|
const PRIMARY_RUNNER_IDS = ['claude', 'codex', 'opencode'];
|
|
49
54
|
function normalizeRunnerStatusRows(rows) {
|
|
50
55
|
const byId = new Map();
|
|
@@ -83,6 +88,7 @@ function normalizeRunnerStatusRows(rows) {
|
|
|
83
88
|
version: row.version,
|
|
84
89
|
tone: 'warning',
|
|
85
90
|
statusLine: 'Not installed on the selected machine',
|
|
91
|
+
models: row.models,
|
|
86
92
|
detail,
|
|
87
93
|
};
|
|
88
94
|
}
|
|
@@ -99,6 +105,7 @@ function normalizeRunnerStatusRows(rows) {
|
|
|
99
105
|
statusLine: configured
|
|
100
106
|
? `${versionPrefix}Configured on the selected machine`
|
|
101
107
|
: `${versionPrefix}Needs provider config on the selected machine`,
|
|
108
|
+
models: row.models,
|
|
102
109
|
detail,
|
|
103
110
|
};
|
|
104
111
|
}
|
|
@@ -114,12 +121,34 @@ function normalizeRunnerStatusRows(rows) {
|
|
|
114
121
|
statusLine: authed
|
|
115
122
|
? `${versionPrefix}Signed in on the selected machine`
|
|
116
123
|
: `${versionPrefix}Not signed in on the selected machine`,
|
|
124
|
+
models: row.models,
|
|
117
125
|
detail,
|
|
118
126
|
actionLabel: authed ? 'Re-auth' : 'Sign in',
|
|
119
127
|
actionRunner: id,
|
|
120
128
|
};
|
|
121
129
|
});
|
|
122
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
|
+
};
|
|
123
152
|
const FeedbackModal = () => {
|
|
124
153
|
const { width: winW, height: winH } = (0, react_native_1.useWindowDimensions)();
|
|
125
154
|
const isTablet = Math.min(winW, winH) >= 600;
|
|
@@ -127,6 +156,7 @@ const FeedbackModal = () => {
|
|
|
127
156
|
// looks empty on a 1024pt iPad. Mobile keeps 3-col.
|
|
128
157
|
const iconOptionWidthOverride = isTablet ? '18%' : undefined;
|
|
129
158
|
const [visible, setVisible] = (0, react_1.useState)(false);
|
|
159
|
+
const [dogfoodActive, setDogfoodActive] = (0, react_1.useState)(() => YaverFeedback_1.YaverFeedback.getDogfoodStatus().active);
|
|
130
160
|
const [action, setAction] = (0, react_1.useState)('idle');
|
|
131
161
|
const [error, setError] = (0, react_1.useState)(null);
|
|
132
162
|
const [toast, setToast] = (0, react_1.useState)(null);
|
|
@@ -136,6 +166,11 @@ const FeedbackModal = () => {
|
|
|
136
166
|
// is our guaranteed UI for bringing the icon back — we surface a
|
|
137
167
|
// small "Show quick icon" row when this is true.
|
|
138
168
|
const [quickIconHidden, setQuickIconHidden] = (0, react_1.useState)(false);
|
|
169
|
+
// Dev-server snapshot behind the reload buttons. `null` means "we have not
|
|
170
|
+
// been able to ask" — rendered as "not connected", never as "no dev server".
|
|
171
|
+
const [devSnapshot, setDevSnapshot] = (0, react_1.useState)(null);
|
|
172
|
+
// Which reload action is in flight, so only that button spins.
|
|
173
|
+
const [reloadingId, setReloadingId] = (0, react_1.useState)(null);
|
|
139
174
|
const [runnerAuthModal, setRunnerAuthModal] = (0, react_1.useState)(null);
|
|
140
175
|
// Vibing-input mode: same expand-on-tap pattern as email login.
|
|
141
176
|
// Tap "Vibing" once → the button reveals an input + Send; that lets
|
|
@@ -161,8 +196,115 @@ const FeedbackModal = () => {
|
|
|
161
196
|
const [runnerStatusError, setRunnerStatusError] = (0, react_1.useState)(null);
|
|
162
197
|
const [preferredRunner, setPreferredRunnerState] = (0, react_1.useState)(null);
|
|
163
198
|
const [preferredModel, setPreferredModelState] = (0, react_1.useState)('');
|
|
199
|
+
const [activeTab, setActiveTab] = (0, react_1.useState)('chat');
|
|
164
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);
|
|
165
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]);
|
|
286
|
+
/**
|
|
287
|
+
* Ask the machine what its dev server is doing, so the reload actions can
|
|
288
|
+
* be enabled/disabled against reality rather than against a guess.
|
|
289
|
+
*
|
|
290
|
+
* Best-effort and deliberately null-on-failure: null means "we could not
|
|
291
|
+
* ask", which the seam renders as "not connected to a machine yet" — a
|
|
292
|
+
* different sentence from "no dev server is running", because they have
|
|
293
|
+
* different fixes.
|
|
294
|
+
*/
|
|
295
|
+
const refreshDevSnapshot = (0, react_1.useCallback)(async () => {
|
|
296
|
+
try {
|
|
297
|
+
const client = YaverFeedback_1.YaverFeedback.getP2PClient();
|
|
298
|
+
if (!client) {
|
|
299
|
+
setDevSnapshot(null);
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
setDevSnapshot(await client.getDevServerStatus());
|
|
303
|
+
}
|
|
304
|
+
catch {
|
|
305
|
+
setDevSnapshot(null);
|
|
306
|
+
}
|
|
307
|
+
}, []);
|
|
166
308
|
const loadSelectedMachine = (0, react_1.useCallback)(async () => {
|
|
167
309
|
const cfg = YaverFeedback_1.YaverFeedback.getConfig();
|
|
168
310
|
if (!cfg?.authToken) {
|
|
@@ -196,8 +338,7 @@ const FeedbackModal = () => {
|
|
|
196
338
|
}
|
|
197
339
|
try {
|
|
198
340
|
const devices = await (0, auth_1.listReachableDevices)(cfg.authToken);
|
|
199
|
-
const
|
|
200
|
-
const device = all.find((candidate) => candidate.deviceId === cfg.preferredDeviceId) ?? null;
|
|
341
|
+
const device = devices.owned.find((candidate) => candidate.deviceId === cfg.preferredDeviceId) ?? null;
|
|
201
342
|
if (!device) {
|
|
202
343
|
if (mountedRef.current) {
|
|
203
344
|
setMachineCard({
|
|
@@ -216,9 +357,8 @@ const FeedbackModal = () => {
|
|
|
216
357
|
if (device.isOnline && !device.needsAuth && client) {
|
|
217
358
|
reachable = await client.health();
|
|
218
359
|
}
|
|
219
|
-
const hostHint = device.hostEmail ? ` via ${device.hostEmail}` : '';
|
|
220
360
|
let status = 'live';
|
|
221
|
-
let detail =
|
|
361
|
+
let detail = device.platform;
|
|
222
362
|
if (!device.isOnline) {
|
|
223
363
|
status = 'offline';
|
|
224
364
|
detail = 'Machine offline. Start `yaver serve` on the selected machine.';
|
|
@@ -291,7 +431,7 @@ const FeedbackModal = () => {
|
|
|
291
431
|
if (!client) {
|
|
292
432
|
throw new Error('Not connected to the selected machine yet.');
|
|
293
433
|
}
|
|
294
|
-
const rows = await client.
|
|
434
|
+
const rows = await client.getAvailableRunners();
|
|
295
435
|
if (mountedRef.current) {
|
|
296
436
|
setRunnerCards(normalizeRunnerStatusRows(rows));
|
|
297
437
|
}
|
|
@@ -329,13 +469,20 @@ const FeedbackModal = () => {
|
|
|
329
469
|
mountedRef.current = true;
|
|
330
470
|
const sub = react_native_1.DeviceEventEmitter.addListener('yaverFeedback:startReport', () => {
|
|
331
471
|
if (YaverFeedback_1.YaverFeedback.isEnabled()) {
|
|
472
|
+
const onboarding = YaverFeedback_1.YaverFeedback.getDogfoodOnboarding();
|
|
473
|
+
const directDogfood = YaverFeedback_1.YaverFeedback.getDogfoodStatus().active;
|
|
474
|
+
setDogfoodActive(directDogfood);
|
|
332
475
|
setVisible(true);
|
|
333
476
|
setError(null);
|
|
334
477
|
setToast(null);
|
|
335
478
|
setProgress(null);
|
|
336
479
|
setAction('idle');
|
|
337
|
-
setShowVibeInput(
|
|
480
|
+
setShowVibeInput(directDogfood);
|
|
338
481
|
setVibePrompt('');
|
|
482
|
+
if (onboarding) {
|
|
483
|
+
setActiveTab('settings');
|
|
484
|
+
void loadDogfoodOnboarding();
|
|
485
|
+
}
|
|
339
486
|
// Re-read the "user hid the quick icon" flag on every open so
|
|
340
487
|
// the re-enable row reflects the latest preference (the user
|
|
341
488
|
// might have hidden or shown it between opens).
|
|
@@ -355,6 +502,13 @@ const FeedbackModal = () => {
|
|
|
355
502
|
void loadRunnerStatuses();
|
|
356
503
|
}
|
|
357
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
|
+
});
|
|
358
512
|
// Agent streams build / compile progress through the BlackBox
|
|
359
513
|
// SSE command channel as `command: "status"`; YaverFeedback re-emits
|
|
360
514
|
// it as `yaverFeedback:status`. Show the most recent message in the
|
|
@@ -378,18 +532,25 @@ const FeedbackModal = () => {
|
|
|
378
532
|
return () => {
|
|
379
533
|
mountedRef.current = false;
|
|
380
534
|
sub.remove();
|
|
535
|
+
dogfoodSub.remove();
|
|
381
536
|
statusSub.remove();
|
|
382
537
|
};
|
|
383
|
-
}, [loadRunnerStatuses, loadSelectedMachine]);
|
|
538
|
+
}, [loadDogfoodOnboarding, loadRunnerStatuses, loadSelectedMachine]);
|
|
384
539
|
(0, react_1.useEffect)(() => {
|
|
385
540
|
if (!visible)
|
|
386
541
|
return;
|
|
542
|
+
// Poll the dev server alongside the machine + runners. A reload button
|
|
543
|
+
// whose enabled state was decided once, when the sheet opened, goes
|
|
544
|
+
// stale the moment the user starts Metro from another surface — and a
|
|
545
|
+
// stale "no dev server is running" reads as the product being broken.
|
|
546
|
+
void refreshDevSnapshot();
|
|
387
547
|
const interval = setInterval(() => {
|
|
388
548
|
void loadSelectedMachine();
|
|
389
549
|
void loadRunnerStatuses();
|
|
550
|
+
void refreshDevSnapshot();
|
|
390
551
|
}, 5000);
|
|
391
552
|
return () => clearInterval(interval);
|
|
392
|
-
}, [loadRunnerStatuses, loadSelectedMachine, visible]);
|
|
553
|
+
}, [loadRunnerStatuses, loadSelectedMachine, refreshDevSnapshot, visible]);
|
|
393
554
|
(0, react_1.useEffect)(() => {
|
|
394
555
|
if (!visible) {
|
|
395
556
|
setKeyboardInset(0);
|
|
@@ -408,6 +569,12 @@ const FeedbackModal = () => {
|
|
|
408
569
|
hideSub.remove();
|
|
409
570
|
};
|
|
410
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]);
|
|
411
578
|
const closeSoon = (0, react_1.useCallback)((delayMs = 1200) => {
|
|
412
579
|
setTimeout(() => {
|
|
413
580
|
if (mountedRef.current)
|
|
@@ -423,6 +590,9 @@ const FeedbackModal = () => {
|
|
|
423
590
|
setShowVibeInput(false);
|
|
424
591
|
setVibePrompt('');
|
|
425
592
|
setRunnerStatusError(null);
|
|
593
|
+
void dogfoodControllerRef.current?.stop().catch(() => { });
|
|
594
|
+
dogfoodControllerRef.current = null;
|
|
595
|
+
YaverFeedback_1.YaverFeedback.clearDogfoodOnboarding();
|
|
426
596
|
}, []);
|
|
427
597
|
// Helper: run a P2P call; on network failure, ask YaverFeedback to
|
|
428
598
|
// re-query Convex for the fresh IP and retry once. Solves the common
|
|
@@ -473,7 +643,84 @@ const FeedbackModal = () => {
|
|
|
473
643
|
await fn(fresh);
|
|
474
644
|
}
|
|
475
645
|
}, []);
|
|
476
|
-
// ─── 1.
|
|
646
|
+
// ─── 1. Reload ─────────────────────────────────────────────────────
|
|
647
|
+
//
|
|
648
|
+
// Three actions now, not one: Hot Reload (mode=fast), Full Reload
|
|
649
|
+
// (mode=full — Flutter's hot RESTART), and Rebuild Bundle
|
|
650
|
+
// (/dev/reload-app, the only one that works with Metro down).
|
|
651
|
+
//
|
|
652
|
+
// WHICH of them render, and which are disabled with what reason, is
|
|
653
|
+
// decided by the pure `reloadActions()` seam — never inline here, so the
|
|
654
|
+
// same policy holds on web, Flutter, Unity, Swift and Kotlin. In
|
|
655
|
+
// particular: a production build (`__DEV__ === false`) gets NONE of them.
|
|
656
|
+
const availableReloadActions = (0, reloadActions_1.reloadActions)(devSnapshot, {
|
|
657
|
+
// __DEV__ is React Native's own build flag. A release bundle sets it
|
|
658
|
+
// false, so a shipped app renders no reload UI at all — which is the
|
|
659
|
+
// point, and is what reloadActions.test.ts pins.
|
|
660
|
+
isDevBuild: typeof __DEV__ !== 'undefined' && __DEV__ === true,
|
|
661
|
+
connected: devSnapshot !== null,
|
|
662
|
+
machineLabel: machineCard.device?.name || undefined,
|
|
663
|
+
includeRebuild: true,
|
|
664
|
+
});
|
|
665
|
+
const handleReloadAction = (0, react_1.useCallback)(async (reloadAction) => {
|
|
666
|
+
if (!reloadAction.enabled) {
|
|
667
|
+
// Pressing a disabled action must SAY why. A row that does nothing
|
|
668
|
+
// is the same defect as a spinner that never resolves.
|
|
669
|
+
setToast(reloadAction.disabledReason || 'Reload is unavailable right now.');
|
|
670
|
+
setError(reloadAction.disabledReason || null);
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
setReloadingId(reloadAction.id);
|
|
674
|
+
setAction('hot-reloading');
|
|
675
|
+
setError(null);
|
|
676
|
+
setProgress(0);
|
|
677
|
+
setToast(`${reloadAction.label}…`);
|
|
678
|
+
try {
|
|
679
|
+
await loadSelectedMachine();
|
|
680
|
+
const selected = await YaverFeedback_1.YaverFeedback.getSelectedRemoteDevice();
|
|
681
|
+
if (!selected) {
|
|
682
|
+
YaverFeedback_1.YaverFeedback.showMachinePicker();
|
|
683
|
+
throw new Error('No machine selected. Pick a machine and try again.');
|
|
684
|
+
}
|
|
685
|
+
if (selected.needsAuth) {
|
|
686
|
+
YaverFeedback_1.YaverFeedback.showMachinePicker();
|
|
687
|
+
throw new Error('Selected machine needs pairing again.');
|
|
688
|
+
}
|
|
689
|
+
if (!selected.isOnline) {
|
|
690
|
+
throw new Error('Selected machine is offline. Start `yaver serve` on it first.');
|
|
691
|
+
}
|
|
692
|
+
let ackMessage = `${reloadAction.label} requested.`;
|
|
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);
|
|
698
|
+
ackMessage = ack.message;
|
|
699
|
+
setToast(ack.message);
|
|
700
|
+
setProgress(0.2);
|
|
701
|
+
});
|
|
702
|
+
setToast(ackMessage);
|
|
703
|
+
if (reloadAction.mode === 'bundle')
|
|
704
|
+
closeSoon(2500);
|
|
705
|
+
}
|
|
706
|
+
catch (err) {
|
|
707
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
708
|
+
setError(message);
|
|
709
|
+
setToast(message.toLowerCase().indexOf('session expired') >= 0
|
|
710
|
+
? 'Session expired. Sign in again.'
|
|
711
|
+
: message);
|
|
712
|
+
await loadSelectedMachine();
|
|
713
|
+
setProgress(null);
|
|
714
|
+
}
|
|
715
|
+
finally {
|
|
716
|
+
if (mountedRef.current) {
|
|
717
|
+
setAction('idle');
|
|
718
|
+
setReloadingId(null);
|
|
719
|
+
void refreshDevSnapshot();
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
}, [closeSoon, devSnapshot, loadSelectedMachine, refreshDevSnapshot, runWithReconnect]);
|
|
723
|
+
/** Kept for the legacy one-tap path (BlackBox command, chat Reload button). */
|
|
477
724
|
const handleHotReload = (0, react_1.useCallback)(async () => {
|
|
478
725
|
setAction('hot-reloading');
|
|
479
726
|
setError(null);
|
|
@@ -499,8 +746,11 @@ const FeedbackModal = () => {
|
|
|
499
746
|
// map this app to its MobileProject scan entry without needing
|
|
500
747
|
// `yaver dev start` to have been run.
|
|
501
748
|
let ackMessage = 'Reload request acknowledged.';
|
|
502
|
-
await runWithReconnect(async (
|
|
503
|
-
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');
|
|
504
754
|
ackMessage = ack.message;
|
|
505
755
|
setToast(ack.message);
|
|
506
756
|
setProgress(0.2);
|
|
@@ -579,19 +829,36 @@ const FeedbackModal = () => {
|
|
|
579
829
|
try {
|
|
580
830
|
const { Dimensions } = require('react-native');
|
|
581
831
|
const { width, height } = Dimensions.get('window');
|
|
832
|
+
const cfg = YaverFeedback_1.YaverFeedback.getConfig();
|
|
833
|
+
const identity = (0, P2PClient_1.resolveReportIdentity)({
|
|
834
|
+
projectName: cfg?.projectName,
|
|
835
|
+
bundleId: cfg?.bundleId,
|
|
836
|
+
surface: cfg?.surface,
|
|
837
|
+
surfaces: cfg?.surfaces,
|
|
838
|
+
stack: cfg?.stack,
|
|
839
|
+
stacks: cfg?.stacks,
|
|
840
|
+
testSurfaces: cfg?.testSurfaces,
|
|
841
|
+
feedbackSdk: cfg?.feedbackSdk,
|
|
842
|
+
feedbackTransport: cfg?.feedbackTransport,
|
|
843
|
+
voiceCapabilities: cfg?.voiceCapabilities,
|
|
844
|
+
sttProvider: cfg?.sttProvider,
|
|
845
|
+
ttsProvider: cfg?.ttsProvider,
|
|
846
|
+
});
|
|
582
847
|
const deviceInfo = {
|
|
583
848
|
platform: react_native_1.Platform.OS,
|
|
584
849
|
osVersion: String(react_native_1.Platform.Version),
|
|
585
850
|
model: react_native_1.Platform.OS === 'ios' ? 'iOS Device' : 'Android Device',
|
|
586
851
|
screenWidth: width,
|
|
587
852
|
screenHeight: height,
|
|
853
|
+
appName: identity.appName,
|
|
588
854
|
};
|
|
589
855
|
const capturedErrors = YaverFeedback_1.YaverFeedback.getCapturedErrors();
|
|
590
856
|
const bundle = {
|
|
591
857
|
metadata: {
|
|
592
858
|
timestamp: new Date().toISOString(),
|
|
593
|
-
|
|
594
|
-
app:
|
|
859
|
+
deviceInfo,
|
|
860
|
+
app: identity.app,
|
|
861
|
+
project: identity.project,
|
|
595
862
|
userNote: '[Screenshot + Fix]',
|
|
596
863
|
},
|
|
597
864
|
screenshots: [path],
|
|
@@ -711,6 +978,7 @@ const FeedbackModal = () => {
|
|
|
711
978
|
taskId: result.taskId,
|
|
712
979
|
initialPrompt: promptText,
|
|
713
980
|
project: identity.projectName,
|
|
981
|
+
projectPath: identity.projectPath,
|
|
714
982
|
runner: preferredRunner ?? undefined,
|
|
715
983
|
model: preferredModel ?? undefined,
|
|
716
984
|
});
|
|
@@ -731,6 +999,7 @@ const FeedbackModal = () => {
|
|
|
731
999
|
}, [closeSoon, isRecordingVideo, lastVideo]);
|
|
732
1000
|
*/
|
|
733
1001
|
const busy = action !== 'idle';
|
|
1002
|
+
const machineRouting = YaverFeedback_1.YaverFeedback.getMachineRouting();
|
|
734
1003
|
const readyRunnerCount = runnerCards.filter((row) => row.ready || row.authConfigured).length;
|
|
735
1004
|
const missingRunnerCount = runnerCards.filter((row) => !row.installed).length;
|
|
736
1005
|
const needsAuthRunnerCount = runnerCards.filter((row) => row.installed && !row.authConfigured && !row.ready).length;
|
|
@@ -738,14 +1007,18 @@ const FeedbackModal = () => {
|
|
|
738
1007
|
// for the live chat screen. The chat manages its own SSE
|
|
739
1008
|
// subscription, multi-turn follow-ups, and Reload button. Closing
|
|
740
1009
|
// the chat returns to idle and clears the active vibe.
|
|
741
|
-
if (
|
|
1010
|
+
if (activeVibe) {
|
|
742
1011
|
const client = YaverFeedback_1.YaverFeedback.getP2PClient();
|
|
743
1012
|
return (<>
|
|
744
1013
|
<AuthOverlay_1.AuthOverlay />
|
|
745
1014
|
<QuickActionIcon_1.QuickActionIcon />
|
|
746
|
-
<
|
|
747
|
-
|
|
748
|
-
|
|
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();
|
|
749
1022
|
if (!c)
|
|
750
1023
|
throw new Error('Not connected');
|
|
751
1024
|
await c.reloadApp();
|
|
@@ -756,6 +1029,7 @@ const FeedbackModal = () => {
|
|
|
756
1029
|
return (<>
|
|
757
1030
|
<AuthOverlay_1.AuthOverlay />
|
|
758
1031
|
<QuickActionIcon_1.QuickActionIcon />
|
|
1032
|
+
<YaverModeBadgeGate />
|
|
759
1033
|
{visible && (<react_native_1.Modal visible={visible} animationType="slide" transparent onRequestClose={handleClose}>
|
|
760
1034
|
<react_native_1.Pressable style={styles.overlay} onPress={handleClose}>
|
|
761
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">
|
|
@@ -778,19 +1052,80 @@ const FeedbackModal = () => {
|
|
|
778
1052
|
e.stopPropagation();
|
|
779
1053
|
react_native_1.Keyboard.dismiss();
|
|
780
1054
|
}}>
|
|
781
|
-
<react_native_1.ScrollView style={styles.scroll} contentContainerStyle={[
|
|
1055
|
+
<react_native_1.ScrollView ref={scrollRef} style={styles.scroll} contentContainerStyle={[
|
|
782
1056
|
styles.scrollContent,
|
|
783
1057
|
showVibeInput && keyboardInset > 0
|
|
784
1058
|
? { paddingBottom: 8 + keyboardInset }
|
|
785
1059
|
: null,
|
|
786
|
-
]} 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'}>
|
|
787
1061
|
<react_native_1.View style={styles.header}>
|
|
788
|
-
<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>
|
|
789
1065
|
<react_native_1.Pressable onPress={handleClose} hitSlop={12} style={styles.closeBtn} accessibilityRole="button" accessibilityLabel="Close">
|
|
790
1066
|
<react_native_1.Text style={styles.closeIcon}>×</react_native_1.Text>
|
|
791
1067
|
</react_native_1.Pressable>
|
|
792
1068
|
</react_native_1.View>
|
|
793
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}
|
|
794
1129
|
<react_native_1.Pressable onPress={() => {
|
|
795
1130
|
if (!YaverFeedback_1.YaverFeedback.isAuthed()) {
|
|
796
1131
|
YaverFeedback_1.YaverFeedback.showLogin();
|
|
@@ -811,7 +1146,7 @@ const FeedbackModal = () => {
|
|
|
811
1146
|
machineCard.status === 'attention' && styles.machineDotAttention,
|
|
812
1147
|
machineCard.status === 'offline' && styles.machineDotOffline,
|
|
813
1148
|
]}/>
|
|
814
|
-
<react_native_1.Text style={styles.machineLabel}>
|
|
1149
|
+
<react_native_1.Text style={styles.machineLabel}>Coding Machine</react_native_1.Text>
|
|
815
1150
|
</react_native_1.View>
|
|
816
1151
|
<react_native_1.Text style={styles.machineAction}>
|
|
817
1152
|
{machineCard.loading ? 'Refreshing…' : 'Change'}
|
|
@@ -823,6 +1158,17 @@ const FeedbackModal = () => {
|
|
|
823
1158
|
<react_native_1.Text style={styles.machineMeta}>{machineCard.detail}</react_native_1.Text>
|
|
824
1159
|
</react_native_1.Pressable>
|
|
825
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
|
+
|
|
826
1172
|
<react_native_1.View style={styles.runnerSection}>
|
|
827
1173
|
<react_native_1.View style={styles.runnerSectionHeader}>
|
|
828
1174
|
<react_native_1.View style={{ flex: 1 }}>
|
|
@@ -843,6 +1189,13 @@ const FeedbackModal = () => {
|
|
|
843
1189
|
</react_native_1.Pressable>
|
|
844
1190
|
</react_native_1.View>
|
|
845
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
|
+
|
|
846
1199
|
{runnerCards.map((row) => (<react_native_1.View key={row.id} style={[
|
|
847
1200
|
styles.runnerCard,
|
|
848
1201
|
row.tone === 'ok' && styles.runnerCardOk,
|
|
@@ -861,13 +1214,29 @@ const FeedbackModal = () => {
|
|
|
861
1214
|
{row.statusLine}
|
|
862
1215
|
</react_native_1.Text>
|
|
863
1216
|
</react_native_1.View>
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
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>
|
|
870
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}
|
|
871
1240
|
{row.detail ? (<react_native_1.Text style={styles.runnerCardDetail}>{row.detail}</react_native_1.Text>) : null}
|
|
872
1241
|
</react_native_1.View>))}
|
|
873
1242
|
|
|
@@ -926,9 +1295,31 @@ const FeedbackModal = () => {
|
|
|
926
1295
|
</react_native_1.View>
|
|
927
1296
|
</react_native_1.View>
|
|
928
1297
|
|
|
929
|
-
{/* 1.
|
|
930
|
-
|
|
1298
|
+
{/* 1. Reload — Hot / Full / Rebuild Bundle.
|
|
1299
|
+
Rendered from the shared decision seam, so a production
|
|
1300
|
+
build (__DEV__ false) renders nothing here at all, and a
|
|
1301
|
+
blocked action shows greyed WITH its reason underneath
|
|
1302
|
+
rather than vanishing. */}
|
|
1303
|
+
{availableReloadActions.map((reloadAction) => (<react_native_1.View key={reloadAction.id} style={styles.reloadRow}>
|
|
1304
|
+
<ActionRow label={reloadingId === reloadAction.id
|
|
1305
|
+
? `${reloadAction.label}…`
|
|
1306
|
+
: reloadAction.label} tint={reloadAction.id === 'rebuild' ? '#38bdf8' : '#fbbf24'} onPress={() => {
|
|
1307
|
+
void handleReloadAction(reloadAction);
|
|
1308
|
+
}}
|
|
1309
|
+
// Never `disabled` at the Pressable level for a blocked
|
|
1310
|
+
// action: we WANT the tap so we can say why. Only a
|
|
1311
|
+
// genuinely busy modal blocks the press.
|
|
1312
|
+
disabled={busy && reloadingId !== reloadAction.id} busy={reloadingId === reloadAction.id}/>
|
|
1313
|
+
<react_native_1.Text style={styles.reloadHint}>
|
|
1314
|
+
{reloadAction.enabled
|
|
1315
|
+
? reloadAction.hint
|
|
1316
|
+
: reloadAction.disabledReason}
|
|
1317
|
+
</react_native_1.Text>
|
|
1318
|
+
</react_native_1.View>))}
|
|
1319
|
+
</>
|
|
1320
|
+
</react_native_1.View>
|
|
931
1321
|
|
|
1322
|
+
<react_native_1.View style={[styles.tabContent, activeTab !== 'chat' && styles.hidden]}>
|
|
932
1323
|
{/* 3. Vibing — expands to an input box on first tap
|
|
933
1324
|
so the user says WHAT they want to vibe on, just
|
|
934
1325
|
like the Yaver mobile app's Vibing tab. Second
|
|
@@ -955,7 +1346,7 @@ const FeedbackModal = () => {
|
|
|
955
1346
|
</react_native_1.Text>)}
|
|
956
1347
|
|
|
957
1348
|
{/* Screenshot & Fix */}
|
|
958
|
-
<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}
|
|
959
1350
|
|
|
960
1351
|
{/* Deploy — opens an inline panel that talks to
|
|
961
1352
|
/fleet/deploy-options on the agent and lets the user
|
|
@@ -963,7 +1354,8 @@ const FeedbackModal = () => {
|
|
|
963
1354
|
it on. Capabilities (e.g. "Linux can't TestFlight")
|
|
964
1355
|
come from the agent's doctor probes — no client-side
|
|
965
1356
|
platform smarts here. */}
|
|
966
|
-
{!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>
|
|
967
1359
|
|
|
968
1360
|
{progress !== null && (<react_native_1.View style={styles.progressTrack}>
|
|
969
1361
|
<react_native_1.View style={[
|
|
@@ -1004,6 +1396,33 @@ const ActionRow = ({ label, tint, onPress, disabled, busy, }) => (<react_native_
|
|
|
1004
1396
|
{busy ? (<react_native_1.ActivityIndicator color={tint} size="small"/>) : (<react_native_1.Text style={[styles.actionText, { color: tint }]}>{label}</react_native_1.Text>)}
|
|
1005
1397
|
</react_native_1.Pressable>);
|
|
1006
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' },
|
|
1417
|
+
reloadRow: {
|
|
1418
|
+
gap: 4,
|
|
1419
|
+
},
|
|
1420
|
+
reloadHint: {
|
|
1421
|
+
color: '#8b8b93',
|
|
1422
|
+
fontSize: 11,
|
|
1423
|
+
lineHeight: 15,
|
|
1424
|
+
paddingHorizontal: 4,
|
|
1425
|
+
},
|
|
1007
1426
|
vibeInputRow: {
|
|
1008
1427
|
backgroundColor: 'rgba(129,140,248,0.08)',
|
|
1009
1428
|
borderColor: 'rgba(129,140,248,0.4)',
|
|
@@ -1013,7 +1432,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1013
1432
|
gap: 10,
|
|
1014
1433
|
},
|
|
1015
1434
|
vibeInput: {
|
|
1016
|
-
color: '#
|
|
1435
|
+
color: '#24242b',
|
|
1017
1436
|
fontSize: 15,
|
|
1018
1437
|
minHeight: 64,
|
|
1019
1438
|
textAlignVertical: 'top',
|
|
@@ -1064,7 +1483,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1064
1483
|
justifyContent: 'flex-end',
|
|
1065
1484
|
},
|
|
1066
1485
|
modal: {
|
|
1067
|
-
backgroundColor: '#
|
|
1486
|
+
backgroundColor: '#f8f8fb',
|
|
1068
1487
|
borderTopLeftRadius: 22,
|
|
1069
1488
|
borderTopRightRadius: 22,
|
|
1070
1489
|
padding: 22,
|
|
@@ -1088,7 +1507,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1088
1507
|
title: {
|
|
1089
1508
|
fontSize: 20,
|
|
1090
1509
|
fontWeight: '700',
|
|
1091
|
-
color: '#
|
|
1510
|
+
color: '#17171d',
|
|
1092
1511
|
},
|
|
1093
1512
|
closeBtn: {
|
|
1094
1513
|
width: 36,
|
|
@@ -1096,10 +1515,10 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1096
1515
|
borderRadius: 18,
|
|
1097
1516
|
alignItems: 'center',
|
|
1098
1517
|
justifyContent: 'center',
|
|
1099
|
-
backgroundColor: '
|
|
1518
|
+
backgroundColor: '#ededf3',
|
|
1100
1519
|
},
|
|
1101
1520
|
closeIcon: {
|
|
1102
|
-
color: '#
|
|
1521
|
+
color: '#656570',
|
|
1103
1522
|
fontSize: 22,
|
|
1104
1523
|
lineHeight: 24,
|
|
1105
1524
|
fontWeight: '400',
|
|
@@ -1118,12 +1537,19 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1118
1537
|
fontSize: 15,
|
|
1119
1538
|
fontWeight: '700',
|
|
1120
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' },
|
|
1121
1547
|
machineCard: {
|
|
1122
1548
|
borderRadius: 14,
|
|
1123
1549
|
borderWidth: 1,
|
|
1124
1550
|
padding: 14,
|
|
1125
|
-
backgroundColor: '
|
|
1126
|
-
borderColor: '
|
|
1551
|
+
backgroundColor: '#fff',
|
|
1552
|
+
borderColor: '#e1e1e8',
|
|
1127
1553
|
},
|
|
1128
1554
|
machineCardLive: {
|
|
1129
1555
|
backgroundColor: 'rgba(34,197,94,0.10)',
|
|
@@ -1137,6 +1563,10 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1137
1563
|
backgroundColor: 'rgba(239,68,68,0.10)',
|
|
1138
1564
|
borderColor: 'rgba(239,68,68,0.35)',
|
|
1139
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' },
|
|
1140
1570
|
machineHeader: {
|
|
1141
1571
|
flexDirection: 'row',
|
|
1142
1572
|
alignItems: 'center',
|
|
@@ -1164,7 +1594,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1164
1594
|
backgroundColor: '#ef4444',
|
|
1165
1595
|
},
|
|
1166
1596
|
machineLabel: {
|
|
1167
|
-
color: '#
|
|
1597
|
+
color: '#73737e',
|
|
1168
1598
|
fontSize: 12,
|
|
1169
1599
|
fontWeight: '700',
|
|
1170
1600
|
textTransform: 'uppercase',
|
|
@@ -1176,12 +1606,12 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1176
1606
|
fontWeight: '700',
|
|
1177
1607
|
},
|
|
1178
1608
|
machineName: {
|
|
1179
|
-
color: '#
|
|
1609
|
+
color: '#222229',
|
|
1180
1610
|
fontSize: 16,
|
|
1181
1611
|
fontWeight: '700',
|
|
1182
1612
|
},
|
|
1183
1613
|
machineMeta: {
|
|
1184
|
-
color: '#
|
|
1614
|
+
color: '#73737e',
|
|
1185
1615
|
fontSize: 12,
|
|
1186
1616
|
marginTop: 4,
|
|
1187
1617
|
lineHeight: 17,
|
|
@@ -1196,33 +1626,33 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1196
1626
|
gap: 10,
|
|
1197
1627
|
},
|
|
1198
1628
|
runnerSectionTitle: {
|
|
1199
|
-
color: '#
|
|
1629
|
+
color: '#222229',
|
|
1200
1630
|
fontSize: 16,
|
|
1201
1631
|
fontWeight: '700',
|
|
1202
1632
|
},
|
|
1203
1633
|
runnerSectionSubtitle: {
|
|
1204
1634
|
marginTop: 2,
|
|
1205
|
-
color: '#
|
|
1635
|
+
color: '#83838e',
|
|
1206
1636
|
fontSize: 12,
|
|
1207
1637
|
},
|
|
1208
1638
|
runnerRefreshBtn: {
|
|
1209
1639
|
borderRadius: 10,
|
|
1210
1640
|
borderWidth: 1,
|
|
1211
|
-
borderColor: '
|
|
1212
|
-
backgroundColor: '
|
|
1641
|
+
borderColor: '#dedee7',
|
|
1642
|
+
backgroundColor: '#fff',
|
|
1213
1643
|
paddingHorizontal: 10,
|
|
1214
1644
|
paddingVertical: 8,
|
|
1215
1645
|
},
|
|
1216
1646
|
runnerRefreshBtnText: {
|
|
1217
|
-
color: '#
|
|
1647
|
+
color: '#5f5f69',
|
|
1218
1648
|
fontSize: 12,
|
|
1219
1649
|
fontWeight: '600',
|
|
1220
1650
|
},
|
|
1221
1651
|
runnerCard: {
|
|
1222
1652
|
borderRadius: 12,
|
|
1223
1653
|
borderWidth: 1,
|
|
1224
|
-
borderColor: '
|
|
1225
|
-
backgroundColor: '
|
|
1654
|
+
borderColor: '#e2e2e9',
|
|
1655
|
+
backgroundColor: '#fff',
|
|
1226
1656
|
paddingHorizontal: 12,
|
|
1227
1657
|
paddingVertical: 11,
|
|
1228
1658
|
gap: 6,
|
|
@@ -1244,15 +1674,16 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1244
1674
|
alignItems: 'center',
|
|
1245
1675
|
gap: 10,
|
|
1246
1676
|
},
|
|
1677
|
+
runnerCardActions: { flexDirection: 'row', alignItems: 'center', gap: 6 },
|
|
1247
1678
|
runnerCardTitle: {
|
|
1248
|
-
color: '#
|
|
1679
|
+
color: '#222229',
|
|
1249
1680
|
fontSize: 14,
|
|
1250
1681
|
fontWeight: '700',
|
|
1251
1682
|
},
|
|
1252
1683
|
runnerCardStatus: {
|
|
1253
1684
|
marginTop: 2,
|
|
1254
1685
|
fontSize: 12,
|
|
1255
|
-
color: '#
|
|
1686
|
+
color: '#666671',
|
|
1256
1687
|
},
|
|
1257
1688
|
runnerCardStatusOk: {
|
|
1258
1689
|
color: '#86efac',
|
|
@@ -1264,7 +1695,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1264
1695
|
color: '#fca5a5',
|
|
1265
1696
|
},
|
|
1266
1697
|
runnerCardDetail: {
|
|
1267
|
-
color: '#
|
|
1698
|
+
color: '#858590',
|
|
1268
1699
|
fontSize: 11,
|
|
1269
1700
|
lineHeight: 16,
|
|
1270
1701
|
},
|
|
@@ -1281,6 +1712,15 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1281
1712
|
fontSize: 12,
|
|
1282
1713
|
fontWeight: '700',
|
|
1283
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' },
|
|
1284
1724
|
runnerSectionError: {
|
|
1285
1725
|
color: '#fca5a5',
|
|
1286
1726
|
fontSize: 12,
|
|
@@ -1292,7 +1732,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1292
1732
|
progressTrack: {
|
|
1293
1733
|
height: 6,
|
|
1294
1734
|
borderRadius: 3,
|
|
1295
|
-
backgroundColor: '
|
|
1735
|
+
backgroundColor: '#e5e5eb',
|
|
1296
1736
|
overflow: 'hidden',
|
|
1297
1737
|
marginTop: 4,
|
|
1298
1738
|
},
|
|
@@ -1319,10 +1759,10 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1319
1759
|
paddingVertical: 6,
|
|
1320
1760
|
paddingHorizontal: 10,
|
|
1321
1761
|
borderRadius: 10,
|
|
1322
|
-
backgroundColor: '
|
|
1762
|
+
backgroundColor: '#ededf3',
|
|
1323
1763
|
},
|
|
1324
1764
|
quickIconToggleText: {
|
|
1325
|
-
color: '#
|
|
1765
|
+
color: '#5f5f69',
|
|
1326
1766
|
fontSize: 12,
|
|
1327
1767
|
fontWeight: '700',
|
|
1328
1768
|
},
|
|
@@ -1334,25 +1774,25 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1334
1774
|
padding: 12,
|
|
1335
1775
|
},
|
|
1336
1776
|
quickIconNoteText: {
|
|
1337
|
-
color: '#
|
|
1777
|
+
color: '#8a5a12',
|
|
1338
1778
|
fontSize: 12,
|
|
1339
1779
|
lineHeight: 17,
|
|
1340
1780
|
},
|
|
1341
1781
|
iconSelector: {
|
|
1342
1782
|
borderRadius: 12,
|
|
1343
1783
|
borderWidth: 1,
|
|
1344
|
-
borderColor: '
|
|
1345
|
-
backgroundColor: '
|
|
1784
|
+
borderColor: '#e1e1e8',
|
|
1785
|
+
backgroundColor: '#fff',
|
|
1346
1786
|
padding: 12,
|
|
1347
1787
|
gap: 10,
|
|
1348
1788
|
},
|
|
1349
1789
|
iconSelectorTitle: {
|
|
1350
|
-
color: '#
|
|
1790
|
+
color: '#222229',
|
|
1351
1791
|
fontSize: 13,
|
|
1352
1792
|
fontWeight: '700',
|
|
1353
1793
|
},
|
|
1354
1794
|
iconSelectorText: {
|
|
1355
|
-
color: '#
|
|
1795
|
+
color: '#73737e',
|
|
1356
1796
|
fontSize: 12,
|
|
1357
1797
|
lineHeight: 17,
|
|
1358
1798
|
},
|
|
@@ -1366,8 +1806,8 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1366
1806
|
minWidth: 84,
|
|
1367
1807
|
borderRadius: 12,
|
|
1368
1808
|
borderWidth: 1,
|
|
1369
|
-
borderColor: '
|
|
1370
|
-
backgroundColor: '
|
|
1809
|
+
borderColor: '#e4e4ea',
|
|
1810
|
+
backgroundColor: '#f8f8fb',
|
|
1371
1811
|
paddingVertical: 10,
|
|
1372
1812
|
paddingHorizontal: 8,
|
|
1373
1813
|
alignItems: 'center',
|
|
@@ -1394,7 +1834,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1394
1834
|
fontWeight: '700',
|
|
1395
1835
|
},
|
|
1396
1836
|
iconOptionText: {
|
|
1397
|
-
color: '#
|
|
1837
|
+
color: '#555561',
|
|
1398
1838
|
fontSize: 11,
|
|
1399
1839
|
fontWeight: '600',
|
|
1400
1840
|
},
|
|
@@ -1402,14 +1842,14 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1402
1842
|
marginTop: 4,
|
|
1403
1843
|
borderRadius: 14,
|
|
1404
1844
|
borderWidth: 1,
|
|
1405
|
-
borderColor: '
|
|
1845
|
+
borderColor: '#e1e1e8',
|
|
1406
1846
|
paddingVertical: 15,
|
|
1407
1847
|
alignItems: 'center',
|
|
1408
1848
|
justifyContent: 'center',
|
|
1409
|
-
backgroundColor: '
|
|
1849
|
+
backgroundColor: '#fff',
|
|
1410
1850
|
},
|
|
1411
1851
|
cancelBtnText: {
|
|
1412
|
-
color: '#
|
|
1852
|
+
color: '#555561',
|
|
1413
1853
|
fontSize: 15,
|
|
1414
1854
|
fontWeight: '700',
|
|
1415
1855
|
},
|