@comergehq/studio 0.1.26 → 0.1.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1576 -601
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1292 -317
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
- package/src/components/chat/AgentProgressCard.tsx +82 -0
- package/src/components/chat/BundleProgressCard.tsx +75 -0
- package/src/components/chat/ChatMessageBubble.tsx +48 -4
- package/src/components/chat/ChatMessageList.tsx +56 -36
- package/src/components/comments/useAppComments.ts +12 -0
- package/src/data/agent-progress/repository.ts +179 -0
- package/src/data/agent-progress/types.ts +67 -0
- package/src/studio/ComergeStudio.tsx +23 -2
- package/src/studio/analytics/client.ts +103 -0
- package/src/studio/analytics/events.ts +98 -0
- package/src/studio/analytics/track.ts +237 -0
- package/src/studio/bootstrap/StudioBootstrap.tsx +8 -2
- package/src/studio/bootstrap/useStudioBootstrap.ts +18 -2
- package/src/studio/hooks/useAgentRunProgress.ts +357 -0
- package/src/studio/hooks/useAppStats.ts +14 -2
- package/src/studio/hooks/useBundleManager.ts +43 -5
- package/src/studio/hooks/useMergeRequests.ts +63 -14
- package/src/studio/hooks/useStudioActions.ts +34 -1
- package/src/studio/ui/ChatPanel.tsx +13 -2
- package/src/studio/ui/PreviewPanel.tsx +10 -0
- package/src/studio/ui/RuntimeRenderer.tsx +6 -1
- package/src/studio/ui/StudioOverlay.tsx +3 -0
- package/src/studio/ui/preview-panel/usePreviewPanelData.ts +1 -0
package/dist/index.js
CHANGED
|
@@ -37,12 +37,12 @@ __export(index_exports, {
|
|
|
37
37
|
module.exports = __toCommonJS(index_exports);
|
|
38
38
|
|
|
39
39
|
// src/studio/ComergeStudio.tsx
|
|
40
|
-
var
|
|
41
|
-
var
|
|
40
|
+
var React49 = __toESM(require("react"));
|
|
41
|
+
var import_react_native60 = require("react-native");
|
|
42
42
|
var import_bottom_sheet6 = require("@gorhom/bottom-sheet");
|
|
43
43
|
|
|
44
44
|
// src/studio/bootstrap/StudioBootstrap.tsx
|
|
45
|
-
var
|
|
45
|
+
var import_react_native4 = require("react-native");
|
|
46
46
|
|
|
47
47
|
// src/components/primitives/Text.tsx
|
|
48
48
|
var import_react_native2 = require("react-native");
|
|
@@ -309,6 +309,109 @@ async function ensureAnonymousSession() {
|
|
|
309
309
|
return { user: data.user, isNew: true };
|
|
310
310
|
}
|
|
311
311
|
|
|
312
|
+
// src/studio/analytics/client.ts
|
|
313
|
+
var import_react_native3 = require("react-native");
|
|
314
|
+
var import_mixpanel_react_native = require("mixpanel-react-native");
|
|
315
|
+
|
|
316
|
+
// src/core/logger.ts
|
|
317
|
+
var import_react_native_logs = require("react-native-logs");
|
|
318
|
+
var log = import_react_native_logs.logger.createLogger(
|
|
319
|
+
{
|
|
320
|
+
levels: {
|
|
321
|
+
debug: 0,
|
|
322
|
+
info: 1,
|
|
323
|
+
warn: 2,
|
|
324
|
+
error: 3
|
|
325
|
+
},
|
|
326
|
+
severity: "debug",
|
|
327
|
+
transport: import_react_native_logs.consoleTransport,
|
|
328
|
+
transportOptions: {
|
|
329
|
+
colors: {
|
|
330
|
+
info: "blueBright",
|
|
331
|
+
warn: "yellowBright",
|
|
332
|
+
error: "redBright"
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
async: true,
|
|
336
|
+
dateFormat: "time",
|
|
337
|
+
printLevel: true,
|
|
338
|
+
printDate: true,
|
|
339
|
+
fixedExtLvlLength: false,
|
|
340
|
+
enabled: true
|
|
341
|
+
}
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
// src/studio/analytics/client.ts
|
|
345
|
+
var studioMixpanel = null;
|
|
346
|
+
var studioAnalyticsEnabled = false;
|
|
347
|
+
var initPromise = null;
|
|
348
|
+
async function initStudioAnalytics(options) {
|
|
349
|
+
if (initPromise) return initPromise;
|
|
350
|
+
initPromise = (async () => {
|
|
351
|
+
if (!options.enabled) {
|
|
352
|
+
studioAnalyticsEnabled = false;
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
const token = (options.token ?? "").trim();
|
|
356
|
+
if (!token) {
|
|
357
|
+
studioAnalyticsEnabled = false;
|
|
358
|
+
log.warn("[studio-analytics] disabled: missing Mixpanel token");
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
try {
|
|
362
|
+
const trackAutomaticEvents = false;
|
|
363
|
+
const useNative = false;
|
|
364
|
+
const serverUrl = (options.serverUrl ?? "").trim() || "https://api.mixpanel.com";
|
|
365
|
+
const superProperties = {
|
|
366
|
+
runtime: "comerge-studio",
|
|
367
|
+
platform: import_react_native3.Platform.OS
|
|
368
|
+
};
|
|
369
|
+
studioMixpanel = new import_mixpanel_react_native.Mixpanel(token, trackAutomaticEvents, useNative);
|
|
370
|
+
await studioMixpanel.init(false, superProperties, serverUrl);
|
|
371
|
+
studioMixpanel.setLoggingEnabled(Boolean(options.debug));
|
|
372
|
+
studioMixpanel.setFlushBatchSize(50);
|
|
373
|
+
studioAnalyticsEnabled = true;
|
|
374
|
+
} catch (error) {
|
|
375
|
+
studioMixpanel = null;
|
|
376
|
+
studioAnalyticsEnabled = false;
|
|
377
|
+
log.warn("[studio-analytics] init failed", error);
|
|
378
|
+
}
|
|
379
|
+
})();
|
|
380
|
+
return initPromise;
|
|
381
|
+
}
|
|
382
|
+
async function trackStudioEvent(eventName, properties) {
|
|
383
|
+
if (!studioAnalyticsEnabled || !studioMixpanel) return;
|
|
384
|
+
try {
|
|
385
|
+
await studioMixpanel.track(eventName, properties);
|
|
386
|
+
} catch (error) {
|
|
387
|
+
log.warn("[studio-analytics] track failed", { eventName, error });
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
async function flushStudioAnalytics() {
|
|
391
|
+
if (!studioAnalyticsEnabled || !studioMixpanel) return;
|
|
392
|
+
try {
|
|
393
|
+
await studioMixpanel.flush();
|
|
394
|
+
} catch (error) {
|
|
395
|
+
log.warn("[studio-analytics] flush failed", error);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
async function identifyStudioUser(userId) {
|
|
399
|
+
if (!studioAnalyticsEnabled || !studioMixpanel || !userId) return;
|
|
400
|
+
try {
|
|
401
|
+
await studioMixpanel.identify(userId);
|
|
402
|
+
} catch (error) {
|
|
403
|
+
log.warn("[studio-analytics] identify failed", error);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
async function resetStudioAnalytics() {
|
|
407
|
+
if (!studioAnalyticsEnabled || !studioMixpanel) return;
|
|
408
|
+
try {
|
|
409
|
+
await studioMixpanel.reset();
|
|
410
|
+
} catch (error) {
|
|
411
|
+
log.warn("[studio-analytics] reset failed", error);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
312
415
|
// src/studio/bootstrap/useStudioBootstrap.ts
|
|
313
416
|
var SUPABASE_URL = "https://xtfxwbckjpfmqubnsusu.supabase.co";
|
|
314
417
|
var SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inh0Znh3YmNranBmbXF1Ym5zdXN1Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjA2MDEyMzAsImV4cCI6MjA3NjE3NzIzMH0.dzWGAWrK4CvrmHVHzf8w7JlUZohdap0ZPnLZnABMV8s";
|
|
@@ -323,11 +426,23 @@ function useStudioBootstrap(options) {
|
|
|
323
426
|
(async () => {
|
|
324
427
|
try {
|
|
325
428
|
setClientKey(options.clientKey);
|
|
326
|
-
const
|
|
429
|
+
const hasInjectedSupabase = isSupabaseClientInjected();
|
|
430
|
+
const requireAuth = hasInjectedSupabase;
|
|
431
|
+
const analyticsEnabled = options.analyticsEnabled ?? hasInjectedSupabase;
|
|
432
|
+
await initStudioAnalytics({
|
|
433
|
+
enabled: analyticsEnabled,
|
|
434
|
+
token: process.env.EXPO_PUBLIC_MIXPANEL_TOKEN,
|
|
435
|
+
serverUrl: process.env.EXPO_PUBLIC_MIXPANEL_SERVER_URL,
|
|
436
|
+
debug: __DEV__
|
|
437
|
+
});
|
|
327
438
|
if (!requireAuth) {
|
|
328
439
|
setSupabaseConfig({ url: SUPABASE_URL, anonKey: SUPABASE_ANON_KEY });
|
|
440
|
+
await resetStudioAnalytics();
|
|
329
441
|
}
|
|
330
442
|
const { user } = requireAuth ? await ensureAuthenticatedSession() : await ensureAnonymousSession();
|
|
443
|
+
if (requireAuth) {
|
|
444
|
+
await identifyStudioUser(user.id);
|
|
445
|
+
}
|
|
331
446
|
if (cancelled) return;
|
|
332
447
|
setState({ ready: true, userId: user.id, error: null });
|
|
333
448
|
} catch (e) {
|
|
@@ -339,19 +454,25 @@ function useStudioBootstrap(options) {
|
|
|
339
454
|
return () => {
|
|
340
455
|
cancelled = true;
|
|
341
456
|
};
|
|
342
|
-
}, [options.clientKey]);
|
|
457
|
+
}, [options.analyticsEnabled, options.clientKey]);
|
|
343
458
|
return state;
|
|
344
459
|
}
|
|
345
460
|
|
|
346
461
|
// src/studio/bootstrap/StudioBootstrap.tsx
|
|
347
462
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
348
|
-
function StudioBootstrap({
|
|
349
|
-
|
|
463
|
+
function StudioBootstrap({
|
|
464
|
+
children,
|
|
465
|
+
fallback,
|
|
466
|
+
renderError,
|
|
467
|
+
clientKey: clientKey2,
|
|
468
|
+
analyticsEnabled
|
|
469
|
+
}) {
|
|
470
|
+
const { ready, error, userId } = useStudioBootstrap({ clientKey: clientKey2, analyticsEnabled });
|
|
350
471
|
if (error) {
|
|
351
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
472
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.View, { style: { flex: 1, justifyContent: "center", alignItems: "center", padding: 24 }, children: renderError ? renderError(error) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { variant: "bodyMuted", children: error.message }) });
|
|
352
473
|
}
|
|
353
474
|
if (!ready) {
|
|
354
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
475
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.View, { style: { flex: 1, justifyContent: "center", alignItems: "center", padding: 24 }, children: fallback ?? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { variant: "bodyMuted", children: "Loading\u2026" }) });
|
|
355
476
|
}
|
|
356
477
|
if (typeof children === "function") {
|
|
357
478
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: children({ userId: userId ?? "" }) });
|
|
@@ -364,36 +485,6 @@ var React3 = __toESM(require("react"));
|
|
|
364
485
|
|
|
365
486
|
// src/core/services/http/index.ts
|
|
366
487
|
var import_axios2 = __toESM(require("axios"));
|
|
367
|
-
|
|
368
|
-
// src/core/logger.ts
|
|
369
|
-
var import_react_native_logs = require("react-native-logs");
|
|
370
|
-
var log = import_react_native_logs.logger.createLogger(
|
|
371
|
-
{
|
|
372
|
-
levels: {
|
|
373
|
-
debug: 0,
|
|
374
|
-
info: 1,
|
|
375
|
-
warn: 2,
|
|
376
|
-
error: 3
|
|
377
|
-
},
|
|
378
|
-
severity: "debug",
|
|
379
|
-
transport: import_react_native_logs.consoleTransport,
|
|
380
|
-
transportOptions: {
|
|
381
|
-
colors: {
|
|
382
|
-
info: "blueBright",
|
|
383
|
-
warn: "yellowBright",
|
|
384
|
-
error: "redBright"
|
|
385
|
-
}
|
|
386
|
-
},
|
|
387
|
-
async: true,
|
|
388
|
-
dateFormat: "time",
|
|
389
|
-
printLevel: true,
|
|
390
|
-
printDate: true,
|
|
391
|
-
fixedExtLvlLength: false,
|
|
392
|
-
enabled: true
|
|
393
|
-
}
|
|
394
|
-
);
|
|
395
|
-
|
|
396
|
-
// src/core/services/http/index.ts
|
|
397
488
|
var RETRYABLE_MAX_ATTEMPTS = 3;
|
|
398
489
|
var RETRYABLE_BASE_DELAY_MS = 500;
|
|
399
490
|
var RETRYABLE_MAX_DELAY_MS = 4e3;
|
|
@@ -842,13 +933,13 @@ var appsRepository = new AppsRepositoryImpl(appsRemoteDataSource);
|
|
|
842
933
|
|
|
843
934
|
// src/studio/hooks/useForegroundSignal.ts
|
|
844
935
|
var React2 = __toESM(require("react"));
|
|
845
|
-
var
|
|
936
|
+
var import_react_native5 = require("react-native");
|
|
846
937
|
function useForegroundSignal(enabled = true) {
|
|
847
938
|
const [signal, setSignal] = React2.useState(0);
|
|
848
|
-
const lastStateRef = React2.useRef(
|
|
939
|
+
const lastStateRef = React2.useRef(import_react_native5.AppState.currentState);
|
|
849
940
|
React2.useEffect(() => {
|
|
850
941
|
if (!enabled) return;
|
|
851
|
-
const sub =
|
|
942
|
+
const sub = import_react_native5.AppState.addEventListener("change", (nextState) => {
|
|
852
943
|
const prevState = lastStateRef.current;
|
|
853
944
|
lastStateRef.current = nextState;
|
|
854
945
|
const didResume = (prevState === "background" || prevState === "inactive") && nextState === "active";
|
|
@@ -1208,6 +1299,154 @@ var BundlesRepositoryImpl = class extends BaseRepository {
|
|
|
1208
1299
|
};
|
|
1209
1300
|
var bundlesRepository = new BundlesRepositoryImpl(bundlesRemoteDataSource);
|
|
1210
1301
|
|
|
1302
|
+
// src/studio/analytics/events.ts
|
|
1303
|
+
var STUDIO_ANALYTICS_EVENT_VERSION = 1;
|
|
1304
|
+
|
|
1305
|
+
// src/studio/analytics/track.ts
|
|
1306
|
+
function baseProps() {
|
|
1307
|
+
return { event_version: STUDIO_ANALYTICS_EVENT_VERSION };
|
|
1308
|
+
}
|
|
1309
|
+
function normalizeError(error) {
|
|
1310
|
+
if (!error) return {};
|
|
1311
|
+
if (typeof error === "string") {
|
|
1312
|
+
return { error_code: error.slice(0, 120), error_domain: "string" };
|
|
1313
|
+
}
|
|
1314
|
+
if (error instanceof Error) {
|
|
1315
|
+
return {
|
|
1316
|
+
error_code: error.message.slice(0, 120),
|
|
1317
|
+
error_domain: error.name || "Error"
|
|
1318
|
+
};
|
|
1319
|
+
}
|
|
1320
|
+
if (typeof error === "object") {
|
|
1321
|
+
const candidate = error;
|
|
1322
|
+
return {
|
|
1323
|
+
error_code: String(candidate.code ?? candidate.message ?? "unknown_error").slice(0, 120),
|
|
1324
|
+
error_domain: candidate.name ?? "object"
|
|
1325
|
+
};
|
|
1326
|
+
}
|
|
1327
|
+
return { error_code: "unknown_error", error_domain: typeof error };
|
|
1328
|
+
}
|
|
1329
|
+
async function trackMutationEvent(name, payload) {
|
|
1330
|
+
await trackStudioEvent(name, payload);
|
|
1331
|
+
await flushStudioAnalytics();
|
|
1332
|
+
}
|
|
1333
|
+
var lastOpenCommentsKey = null;
|
|
1334
|
+
var lastOpenCommentsAt = 0;
|
|
1335
|
+
async function trackRemixApp(params) {
|
|
1336
|
+
const errorProps = params.success ? {} : normalizeError(params.error);
|
|
1337
|
+
await trackMutationEvent("remix_app", {
|
|
1338
|
+
app_id: params.appId,
|
|
1339
|
+
source_app_id: params.sourceAppId,
|
|
1340
|
+
thread_id: params.threadId,
|
|
1341
|
+
success: params.success,
|
|
1342
|
+
...errorProps,
|
|
1343
|
+
...baseProps()
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
async function trackEditApp(params) {
|
|
1347
|
+
const errorProps = params.success ? {} : normalizeError(params.error);
|
|
1348
|
+
await trackMutationEvent("edit_app", {
|
|
1349
|
+
app_id: params.appId,
|
|
1350
|
+
thread_id: params.threadId,
|
|
1351
|
+
prompt_length: params.promptLength,
|
|
1352
|
+
success: params.success,
|
|
1353
|
+
...errorProps,
|
|
1354
|
+
...baseProps()
|
|
1355
|
+
});
|
|
1356
|
+
}
|
|
1357
|
+
async function trackShareApp(params) {
|
|
1358
|
+
const errorProps = params.success ? {} : normalizeError(params.error);
|
|
1359
|
+
await trackMutationEvent("share_app", {
|
|
1360
|
+
app_id: params.appId,
|
|
1361
|
+
success: params.success,
|
|
1362
|
+
...errorProps,
|
|
1363
|
+
...baseProps()
|
|
1364
|
+
});
|
|
1365
|
+
}
|
|
1366
|
+
async function trackOpenMergeRequest(params) {
|
|
1367
|
+
const errorProps = params.success ? {} : normalizeError(params.error);
|
|
1368
|
+
await trackMutationEvent("open_merge_request", {
|
|
1369
|
+
app_id: params.appId,
|
|
1370
|
+
merge_request_id: params.mergeRequestId,
|
|
1371
|
+
success: params.success,
|
|
1372
|
+
...errorProps,
|
|
1373
|
+
...baseProps()
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
async function trackApproveMergeRequest(params) {
|
|
1377
|
+
const errorProps = params.success ? {} : normalizeError(params.error);
|
|
1378
|
+
await trackMutationEvent("approve_merge_request", {
|
|
1379
|
+
app_id: params.appId,
|
|
1380
|
+
merge_request_id: params.mergeRequestId,
|
|
1381
|
+
success: params.success,
|
|
1382
|
+
...errorProps,
|
|
1383
|
+
...baseProps()
|
|
1384
|
+
});
|
|
1385
|
+
}
|
|
1386
|
+
async function trackRejectMergeRequest(params) {
|
|
1387
|
+
const errorProps = params.success ? {} : normalizeError(params.error);
|
|
1388
|
+
await trackMutationEvent("reject_merge_request", {
|
|
1389
|
+
app_id: params.appId,
|
|
1390
|
+
merge_request_id: params.mergeRequestId,
|
|
1391
|
+
success: params.success,
|
|
1392
|
+
...errorProps,
|
|
1393
|
+
...baseProps()
|
|
1394
|
+
});
|
|
1395
|
+
}
|
|
1396
|
+
async function trackTestBundle(params) {
|
|
1397
|
+
const errorProps = params.success ? {} : normalizeError(params.error);
|
|
1398
|
+
await trackMutationEvent("test_bundle", {
|
|
1399
|
+
app_id: params.appId,
|
|
1400
|
+
commit_id: params.commitId,
|
|
1401
|
+
success: params.success,
|
|
1402
|
+
...errorProps,
|
|
1403
|
+
...baseProps()
|
|
1404
|
+
});
|
|
1405
|
+
}
|
|
1406
|
+
async function trackLikeApp(params) {
|
|
1407
|
+
const errorProps = params.success ? {} : normalizeError(params.error);
|
|
1408
|
+
await trackMutationEvent("like_app", {
|
|
1409
|
+
app_id: params.appId,
|
|
1410
|
+
source: params.source ?? "unknown",
|
|
1411
|
+
success: params.success,
|
|
1412
|
+
...errorProps,
|
|
1413
|
+
...baseProps()
|
|
1414
|
+
});
|
|
1415
|
+
}
|
|
1416
|
+
async function trackUnlikeApp(params) {
|
|
1417
|
+
const errorProps = params.success ? {} : normalizeError(params.error);
|
|
1418
|
+
await trackMutationEvent("unlike_app", {
|
|
1419
|
+
app_id: params.appId,
|
|
1420
|
+
source: params.source ?? "unknown",
|
|
1421
|
+
success: params.success,
|
|
1422
|
+
...errorProps,
|
|
1423
|
+
...baseProps()
|
|
1424
|
+
});
|
|
1425
|
+
}
|
|
1426
|
+
async function trackOpenComments(params) {
|
|
1427
|
+
const key = `${params.appId}:${params.source ?? "unknown"}`;
|
|
1428
|
+
const now = Date.now();
|
|
1429
|
+
if (lastOpenCommentsKey === key && now - lastOpenCommentsAt < 1e3) return;
|
|
1430
|
+
lastOpenCommentsKey = key;
|
|
1431
|
+
lastOpenCommentsAt = now;
|
|
1432
|
+
await trackStudioEvent("open_comments", {
|
|
1433
|
+
app_id: params.appId,
|
|
1434
|
+
source: params.source ?? "unknown",
|
|
1435
|
+
...baseProps()
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1438
|
+
async function trackSubmitComment(params) {
|
|
1439
|
+
const errorProps = params.success ? {} : normalizeError(params.error);
|
|
1440
|
+
await trackMutationEvent("submit_comment", {
|
|
1441
|
+
app_id: params.appId,
|
|
1442
|
+
comment_type: "general",
|
|
1443
|
+
comment_length: params.commentLength,
|
|
1444
|
+
success: params.success,
|
|
1445
|
+
...errorProps,
|
|
1446
|
+
...baseProps()
|
|
1447
|
+
});
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1211
1450
|
// src/studio/hooks/useBundleManager.ts
|
|
1212
1451
|
function sleep2(ms) {
|
|
1213
1452
|
return new Promise((r) => setTimeout(r, ms));
|
|
@@ -1524,7 +1763,7 @@ async function pollBundle(appId, bundleId, opts) {
|
|
|
1524
1763
|
await sleep2(opts.intervalMs);
|
|
1525
1764
|
}
|
|
1526
1765
|
}
|
|
1527
|
-
async function resolveBundlePath(src, platform, mode) {
|
|
1766
|
+
async function resolveBundlePath(src, platform, mode, onStatus) {
|
|
1528
1767
|
const { appId, commitId } = src;
|
|
1529
1768
|
const dir = bundlesCacheDir();
|
|
1530
1769
|
await ensureDir(dir);
|
|
@@ -1538,7 +1777,9 @@ async function resolveBundlePath(src, platform, mode) {
|
|
|
1538
1777
|
},
|
|
1539
1778
|
{ attempts: 3, baseDelayMs: 500, maxDelayMs: 4e3 }
|
|
1540
1779
|
);
|
|
1780
|
+
onStatus == null ? void 0 : onStatus(initiate.status);
|
|
1541
1781
|
const finalBundle = initiate.status === "succeeded" || initiate.status === "failed" ? initiate : await pollBundle(appId, initiate.id, { timeoutMs: 3 * 60 * 1e3, intervalMs: 1200 });
|
|
1782
|
+
onStatus == null ? void 0 : onStatus(finalBundle.status);
|
|
1542
1783
|
if (finalBundle.status === "failed") {
|
|
1543
1784
|
throw new Error("Bundle build failed.");
|
|
1544
1785
|
}
|
|
@@ -1580,6 +1821,7 @@ function useBundleManager({
|
|
|
1580
1821
|
const [renderToken, setRenderToken] = React5.useState(0);
|
|
1581
1822
|
const [loading, setLoading] = React5.useState(false);
|
|
1582
1823
|
const [loadingMode, setLoadingMode] = React5.useState(null);
|
|
1824
|
+
const [bundleStatus, setBundleStatus] = React5.useState(null);
|
|
1583
1825
|
const [statusLabel, setStatusLabel] = React5.useState(null);
|
|
1584
1826
|
const [error, setError] = React5.useState(null);
|
|
1585
1827
|
const [isTesting, setIsTesting] = React5.useState(false);
|
|
@@ -1691,16 +1933,20 @@ function useBundleManager({
|
|
|
1691
1933
|
activeLoadModeRef.current = mode;
|
|
1692
1934
|
setLoading(true);
|
|
1693
1935
|
setLoadingMode(mode);
|
|
1936
|
+
setBundleStatus(null);
|
|
1694
1937
|
setError(null);
|
|
1695
1938
|
setStatusLabel(mode === "test" ? "Loading test bundle\u2026" : "Loading latest build\u2026");
|
|
1696
1939
|
if (mode === "base" && desiredModeRef.current === "base") {
|
|
1697
1940
|
void activateCachedBase(src.appId);
|
|
1698
1941
|
}
|
|
1699
1942
|
try {
|
|
1700
|
-
const { bundlePath: path, bundle } = await resolveBundlePath(src, platform, mode)
|
|
1943
|
+
const { bundlePath: path, bundle } = await resolveBundlePath(src, platform, mode, (status) => {
|
|
1944
|
+
setBundleStatus(status);
|
|
1945
|
+
});
|
|
1701
1946
|
if (mode === "base" && opId !== baseOpIdRef.current) return;
|
|
1702
1947
|
if (mode === "test" && opId !== testOpIdRef.current) return;
|
|
1703
1948
|
if (desiredModeRef.current !== mode) return;
|
|
1949
|
+
setBundleStatus(bundle.status);
|
|
1704
1950
|
setBundlePath(path);
|
|
1705
1951
|
const fingerprint = bundle.checksumSha256 ?? `id:${bundle.id}`;
|
|
1706
1952
|
const shouldSkipInitialBaseRemount = mode === "base" && initialHydratedBaseFromDiskRef.current && !hasCompletedFirstNetworkBaseLoadRef.current && Boolean(lastBaseFingerprintRef.current) && lastBaseFingerprintRef.current === fingerprint;
|
|
@@ -1736,6 +1982,7 @@ function useBundleManager({
|
|
|
1736
1982
|
} catch (e) {
|
|
1737
1983
|
if (mode === "base" && opId !== baseOpIdRef.current) return;
|
|
1738
1984
|
if (mode === "test" && opId !== testOpIdRef.current) return;
|
|
1985
|
+
setBundleStatus("failed");
|
|
1739
1986
|
const msg = e instanceof Error ? e.message : String(e);
|
|
1740
1987
|
setError(msg);
|
|
1741
1988
|
setStatusLabel(null);
|
|
@@ -1751,7 +1998,22 @@ function useBundleManager({
|
|
|
1751
1998
|
await load(baseRef.current, "base");
|
|
1752
1999
|
}, [load]);
|
|
1753
2000
|
const loadTest = React5.useCallback(async (src) => {
|
|
1754
|
-
|
|
2001
|
+
try {
|
|
2002
|
+
await load(src, "test");
|
|
2003
|
+
await trackTestBundle({
|
|
2004
|
+
appId: src.appId,
|
|
2005
|
+
commitId: src.commitId ?? void 0,
|
|
2006
|
+
success: true
|
|
2007
|
+
});
|
|
2008
|
+
} catch (error2) {
|
|
2009
|
+
await trackTestBundle({
|
|
2010
|
+
appId: src.appId,
|
|
2011
|
+
commitId: src.commitId ?? void 0,
|
|
2012
|
+
success: false,
|
|
2013
|
+
error: error2
|
|
2014
|
+
});
|
|
2015
|
+
throw error2;
|
|
2016
|
+
}
|
|
1755
2017
|
}, [load]);
|
|
1756
2018
|
const restoreBase = React5.useCallback(async () => {
|
|
1757
2019
|
const src = baseRef.current;
|
|
@@ -1767,7 +2029,19 @@ function useBundleManager({
|
|
|
1767
2029
|
if (!canRequestLatest) return;
|
|
1768
2030
|
void loadBase();
|
|
1769
2031
|
}, [base.appId, base.commitId, platform, canRequestLatest, loadBase]);
|
|
1770
|
-
return {
|
|
2032
|
+
return {
|
|
2033
|
+
bundlePath,
|
|
2034
|
+
renderToken,
|
|
2035
|
+
loading,
|
|
2036
|
+
loadingMode,
|
|
2037
|
+
bundleStatus,
|
|
2038
|
+
statusLabel,
|
|
2039
|
+
error,
|
|
2040
|
+
isTesting,
|
|
2041
|
+
loadBase,
|
|
2042
|
+
loadTest,
|
|
2043
|
+
restoreBase
|
|
2044
|
+
};
|
|
1771
2045
|
}
|
|
1772
2046
|
|
|
1773
2047
|
// src/studio/hooks/useMergeRequests.ts
|
|
@@ -1977,24 +2251,68 @@ function useMergeRequests(params) {
|
|
|
1977
2251
|
}, [appId]);
|
|
1978
2252
|
React6.useEffect(() => {
|
|
1979
2253
|
void refresh();
|
|
1980
|
-
}, [refresh]);
|
|
2254
|
+
}, [appId, refresh]);
|
|
1981
2255
|
const openMergeRequest = React6.useCallback(async (sourceAppId) => {
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
2256
|
+
try {
|
|
2257
|
+
const mr = await mergeRequestsRepository.open({ sourceAppId });
|
|
2258
|
+
await refresh();
|
|
2259
|
+
await trackOpenMergeRequest({
|
|
2260
|
+
appId,
|
|
2261
|
+
mergeRequestId: mr.id,
|
|
2262
|
+
success: true
|
|
2263
|
+
});
|
|
2264
|
+
return mr;
|
|
2265
|
+
} catch (error2) {
|
|
2266
|
+
await trackOpenMergeRequest({
|
|
2267
|
+
appId,
|
|
2268
|
+
success: false,
|
|
2269
|
+
error: error2
|
|
2270
|
+
});
|
|
2271
|
+
throw error2;
|
|
2272
|
+
}
|
|
1985
2273
|
}, [refresh]);
|
|
1986
2274
|
const approve = React6.useCallback(async (mrId) => {
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
2275
|
+
try {
|
|
2276
|
+
const mr = await mergeRequestsRepository.update(mrId, { status: "approved" });
|
|
2277
|
+
await refresh();
|
|
2278
|
+
const merged = await pollUntilMerged(mrId);
|
|
2279
|
+
await refresh();
|
|
2280
|
+
await trackApproveMergeRequest({
|
|
2281
|
+
appId,
|
|
2282
|
+
mergeRequestId: mrId,
|
|
2283
|
+
success: true
|
|
2284
|
+
});
|
|
2285
|
+
return merged ?? mr;
|
|
2286
|
+
} catch (error2) {
|
|
2287
|
+
await trackApproveMergeRequest({
|
|
2288
|
+
appId,
|
|
2289
|
+
mergeRequestId: mrId,
|
|
2290
|
+
success: false,
|
|
2291
|
+
error: error2
|
|
2292
|
+
});
|
|
2293
|
+
throw error2;
|
|
2294
|
+
}
|
|
2295
|
+
}, [appId, pollUntilMerged, refresh]);
|
|
1993
2296
|
const reject = React6.useCallback(async (mrId) => {
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
2297
|
+
try {
|
|
2298
|
+
const mr = await mergeRequestsRepository.update(mrId, { status: "rejected" });
|
|
2299
|
+
await refresh();
|
|
2300
|
+
await trackRejectMergeRequest({
|
|
2301
|
+
appId,
|
|
2302
|
+
mergeRequestId: mrId,
|
|
2303
|
+
success: true
|
|
2304
|
+
});
|
|
2305
|
+
return mr;
|
|
2306
|
+
} catch (error2) {
|
|
2307
|
+
await trackRejectMergeRequest({
|
|
2308
|
+
appId,
|
|
2309
|
+
mergeRequestId: mrId,
|
|
2310
|
+
success: false,
|
|
2311
|
+
error: error2
|
|
2312
|
+
});
|
|
2313
|
+
throw error2;
|
|
2314
|
+
}
|
|
2315
|
+
}, [appId, refresh]);
|
|
1998
2316
|
const toSummary = React6.useCallback((mr) => {
|
|
1999
2317
|
const stats = creatorStatsById[mr.createdBy];
|
|
2000
2318
|
return {
|
|
@@ -2030,7 +2348,7 @@ function useMergeRequests(params) {
|
|
|
2030
2348
|
|
|
2031
2349
|
// src/studio/hooks/useAttachmentUpload.ts
|
|
2032
2350
|
var React7 = __toESM(require("react"));
|
|
2033
|
-
var
|
|
2351
|
+
var import_react_native6 = require("react-native");
|
|
2034
2352
|
var FileSystem2 = __toESM(require("expo-file-system/legacy"));
|
|
2035
2353
|
|
|
2036
2354
|
// src/data/attachment/remote.ts
|
|
@@ -2117,7 +2435,7 @@ function useAttachmentUpload() {
|
|
|
2117
2435
|
const blobs = await Promise.all(
|
|
2118
2436
|
dataUrls.map(async (dataUrl, idx) => {
|
|
2119
2437
|
const normalized = dataUrl.startsWith("data:") ? dataUrl : `data:image/png;base64,${dataUrl}`;
|
|
2120
|
-
const blob =
|
|
2438
|
+
const blob = import_react_native6.Platform.OS === "android" ? await dataUrlToBlobAndroid(normalized) : await (await fetch(normalized)).blob();
|
|
2121
2439
|
const mimeType = getMimeTypeFromDataUrl(normalized);
|
|
2122
2440
|
return { blob, idx, mimeType };
|
|
2123
2441
|
})
|
|
@@ -2235,13 +2553,21 @@ function useStudioActions({
|
|
|
2235
2553
|
if (sending) return;
|
|
2236
2554
|
setSending(true);
|
|
2237
2555
|
setError(null);
|
|
2556
|
+
let forkSucceeded = false;
|
|
2238
2557
|
try {
|
|
2239
2558
|
let targetApp = app;
|
|
2559
|
+
const sourceAppId = app.id;
|
|
2240
2560
|
if (shouldForkOnEdit) {
|
|
2241
2561
|
setForking(true);
|
|
2242
|
-
const sourceAppId = app.id;
|
|
2243
2562
|
const forked = await appsRepository.fork(app.id, {});
|
|
2244
2563
|
targetApp = forked;
|
|
2564
|
+
await trackRemixApp({
|
|
2565
|
+
appId: forked.id,
|
|
2566
|
+
sourceAppId,
|
|
2567
|
+
threadId: forked.threadId ?? void 0,
|
|
2568
|
+
success: true
|
|
2569
|
+
});
|
|
2570
|
+
forkSucceeded = true;
|
|
2245
2571
|
onForkedApp == null ? void 0 : onForkedApp(forked.id, { keepRenderingAppId: sourceAppId });
|
|
2246
2572
|
}
|
|
2247
2573
|
setForking(false);
|
|
@@ -2269,9 +2595,33 @@ function useStudioActions({
|
|
|
2269
2595
|
queueItemId: editResult.queueItemId ?? null,
|
|
2270
2596
|
queuePosition: editResult.queuePosition ?? null
|
|
2271
2597
|
});
|
|
2598
|
+
await trackEditApp({
|
|
2599
|
+
appId: targetApp.id,
|
|
2600
|
+
threadId,
|
|
2601
|
+
promptLength: prompt.trim().length,
|
|
2602
|
+
success: true
|
|
2603
|
+
});
|
|
2272
2604
|
} catch (e) {
|
|
2273
2605
|
const err = e instanceof Error ? e : new Error(String(e));
|
|
2274
2606
|
setError(err);
|
|
2607
|
+
if (shouldForkOnEdit && !forkSucceeded && (app == null ? void 0 : app.id)) {
|
|
2608
|
+
await trackRemixApp({
|
|
2609
|
+
appId: app.id,
|
|
2610
|
+
sourceAppId: app.id,
|
|
2611
|
+
threadId: app.threadId ?? void 0,
|
|
2612
|
+
success: false,
|
|
2613
|
+
error: err
|
|
2614
|
+
});
|
|
2615
|
+
}
|
|
2616
|
+
if ((app == null ? void 0 : app.id) && app.threadId) {
|
|
2617
|
+
await trackEditApp({
|
|
2618
|
+
appId: app.id,
|
|
2619
|
+
threadId: app.threadId,
|
|
2620
|
+
promptLength: prompt.trim().length,
|
|
2621
|
+
success: false,
|
|
2622
|
+
error: err
|
|
2623
|
+
});
|
|
2624
|
+
}
|
|
2275
2625
|
throw err;
|
|
2276
2626
|
} finally {
|
|
2277
2627
|
setForking(false);
|
|
@@ -2286,12 +2636,13 @@ function useStudioActions({
|
|
|
2286
2636
|
|
|
2287
2637
|
// src/studio/ui/RuntimeRenderer.tsx
|
|
2288
2638
|
var React9 = __toESM(require("react"));
|
|
2289
|
-
var
|
|
2639
|
+
var import_react_native7 = require("react-native");
|
|
2290
2640
|
var import_runtime = require("@comergehq/runtime");
|
|
2291
2641
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
2292
2642
|
function RuntimeRenderer({
|
|
2293
2643
|
appKey,
|
|
2294
2644
|
bundlePath,
|
|
2645
|
+
preparingText,
|
|
2295
2646
|
forcePreparing,
|
|
2296
2647
|
renderToken,
|
|
2297
2648
|
style,
|
|
@@ -2305,11 +2656,11 @@ function RuntimeRenderer({
|
|
|
2305
2656
|
}, [bundlePath]);
|
|
2306
2657
|
if (!bundlePath || forcePreparing) {
|
|
2307
2658
|
if (!hasRenderedOnce && !forcePreparing && !allowInitialPreparing) {
|
|
2308
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2659
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native7.View, { style: [{ flex: 1 }, style] });
|
|
2309
2660
|
}
|
|
2310
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2661
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native7.View, { style: [{ flex: 1, justifyContent: "center", alignItems: "center", padding: 24 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { variant: "bodyMuted", children: preparingText ?? "Preparing app\u2026" }) });
|
|
2311
2662
|
}
|
|
2312
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2663
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native7.View, { style: [{ flex: 1 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2313
2664
|
import_runtime.ComergeRuntimeRenderer,
|
|
2314
2665
|
{
|
|
2315
2666
|
appKey,
|
|
@@ -2321,17 +2672,17 @@ function RuntimeRenderer({
|
|
|
2321
2672
|
}
|
|
2322
2673
|
|
|
2323
2674
|
// src/studio/ui/StudioOverlay.tsx
|
|
2324
|
-
var
|
|
2325
|
-
var
|
|
2675
|
+
var React45 = __toESM(require("react"));
|
|
2676
|
+
var import_react_native59 = require("react-native");
|
|
2326
2677
|
|
|
2327
2678
|
// src/components/studio-sheet/StudioBottomSheet.tsx
|
|
2328
2679
|
var React12 = __toESM(require("react"));
|
|
2329
|
-
var
|
|
2680
|
+
var import_react_native10 = require("react-native");
|
|
2330
2681
|
var import_bottom_sheet = require("@gorhom/bottom-sheet");
|
|
2331
2682
|
var import_react_native_safe_area_context = require("react-native-safe-area-context");
|
|
2332
2683
|
|
|
2333
2684
|
// src/components/studio-sheet/StudioSheetBackground.tsx
|
|
2334
|
-
var
|
|
2685
|
+
var import_react_native9 = require("react-native");
|
|
2335
2686
|
var import_liquid_glass2 = require("@callstack/liquid-glass");
|
|
2336
2687
|
|
|
2337
2688
|
// src/components/utils/ResettableLiquidGlassView.tsx
|
|
@@ -2340,7 +2691,7 @@ var import_liquid_glass = require("@callstack/liquid-glass");
|
|
|
2340
2691
|
|
|
2341
2692
|
// src/components/utils/liquidGlassReset.tsx
|
|
2342
2693
|
var React10 = __toESM(require("react"));
|
|
2343
|
-
var
|
|
2694
|
+
var import_react_native8 = require("react-native");
|
|
2344
2695
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
2345
2696
|
var LiquidGlassResetContext = React10.createContext(0);
|
|
2346
2697
|
function LiquidGlassResetProvider({
|
|
@@ -2349,11 +2700,11 @@ function LiquidGlassResetProvider({
|
|
|
2349
2700
|
}) {
|
|
2350
2701
|
const [token, setToken] = React10.useState(0);
|
|
2351
2702
|
React10.useEffect(() => {
|
|
2352
|
-
if (
|
|
2703
|
+
if (import_react_native8.Platform.OS !== "ios") return;
|
|
2353
2704
|
const onChange = (state) => {
|
|
2354
2705
|
if (state === "active") setToken((t) => t + 1);
|
|
2355
2706
|
};
|
|
2356
|
-
const sub =
|
|
2707
|
+
const sub = import_react_native8.AppState.addEventListener("change", onChange);
|
|
2357
2708
|
return () => sub.remove();
|
|
2358
2709
|
}, []);
|
|
2359
2710
|
React10.useEffect(() => {
|
|
@@ -2390,7 +2741,7 @@ function StudioSheetBackground({
|
|
|
2390
2741
|
renderBackground
|
|
2391
2742
|
}) {
|
|
2392
2743
|
const theme = useTheme();
|
|
2393
|
-
const radius =
|
|
2744
|
+
const radius = import_react_native9.Platform.OS === "ios" ? 39 : 16;
|
|
2394
2745
|
const fallbackBgColor = theme.scheme === "dark" ? "rgba(11, 8, 15, 0.85)" : "rgba(255, 255, 255, 0.85)";
|
|
2395
2746
|
const secondaryBgBaseColor = theme.scheme === "dark" ? "rgb(24, 24, 27)" : "rgb(173, 173, 173)";
|
|
2396
2747
|
const containerStyle = {
|
|
@@ -2411,7 +2762,7 @@ function StudioSheetBackground({
|
|
|
2411
2762
|
}
|
|
2412
2763
|
),
|
|
2413
2764
|
import_liquid_glass2.isLiquidGlassSupported && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2414
|
-
|
|
2765
|
+
import_react_native9.View,
|
|
2415
2766
|
{
|
|
2416
2767
|
style: [
|
|
2417
2768
|
containerStyle,
|
|
@@ -2448,12 +2799,12 @@ function StudioBottomSheet({
|
|
|
2448
2799
|
const resolvedSheetRef = sheetRef ?? internalSheetRef;
|
|
2449
2800
|
const resolvedSnapPoints = React12.useMemo(() => [...snapPoints], [snapPoints]);
|
|
2450
2801
|
const currentIndexRef = React12.useRef(open ? resolvedSnapPoints.length - 1 : -1);
|
|
2451
|
-
const lastAppStateRef = React12.useRef(
|
|
2802
|
+
const lastAppStateRef = React12.useRef(import_react_native10.AppState.currentState);
|
|
2452
2803
|
React12.useEffect(() => {
|
|
2453
|
-
const sub =
|
|
2804
|
+
const sub = import_react_native10.AppState.addEventListener("change", (state) => {
|
|
2454
2805
|
lastAppStateRef.current = state;
|
|
2455
2806
|
if (state === "background" || state === "inactive") {
|
|
2456
|
-
|
|
2807
|
+
import_react_native10.Keyboard.dismiss();
|
|
2457
2808
|
return;
|
|
2458
2809
|
}
|
|
2459
2810
|
});
|
|
@@ -2494,19 +2845,19 @@ function StudioBottomSheet({
|
|
|
2494
2845
|
...bottomSheetProps,
|
|
2495
2846
|
onChange: handleChange,
|
|
2496
2847
|
onDismiss: () => onOpenChange == null ? void 0 : onOpenChange(false),
|
|
2497
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2848
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native10.View, { style: { flex: 1, overflow: "hidden" }, children })
|
|
2498
2849
|
}
|
|
2499
2850
|
);
|
|
2500
2851
|
}
|
|
2501
2852
|
|
|
2502
2853
|
// src/components/studio-sheet/StudioSheetPager.tsx
|
|
2503
2854
|
var React13 = __toESM(require("react"));
|
|
2504
|
-
var
|
|
2855
|
+
var import_react_native11 = require("react-native");
|
|
2505
2856
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
2506
2857
|
function StudioSheetPager({ activePage, width, preview, chat, style }) {
|
|
2507
|
-
const anim = React13.useRef(new
|
|
2858
|
+
const anim = React13.useRef(new import_react_native11.Animated.Value(activePage === "chat" ? 1 : 0)).current;
|
|
2508
2859
|
React13.useEffect(() => {
|
|
2509
|
-
|
|
2860
|
+
import_react_native11.Animated.spring(anim, {
|
|
2510
2861
|
toValue: activePage === "chat" ? 1 : 0,
|
|
2511
2862
|
useNativeDriver: true,
|
|
2512
2863
|
tension: 65,
|
|
@@ -2515,9 +2866,9 @@ function StudioSheetPager({ activePage, width, preview, chat, style }) {
|
|
|
2515
2866
|
}, [activePage, anim]);
|
|
2516
2867
|
const previewTranslateX = anim.interpolate({ inputRange: [0, 1], outputRange: [0, -width] });
|
|
2517
2868
|
const chatTranslateX = anim.interpolate({ inputRange: [0, 1], outputRange: [width, 0] });
|
|
2518
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2869
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native11.Animated.View, { style: [{ flex: 1 }, style], children: [
|
|
2519
2870
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2520
|
-
|
|
2871
|
+
import_react_native11.Animated.View,
|
|
2521
2872
|
{
|
|
2522
2873
|
style: [
|
|
2523
2874
|
{
|
|
@@ -2534,7 +2885,7 @@ function StudioSheetPager({ activePage, width, preview, chat, style }) {
|
|
|
2534
2885
|
}
|
|
2535
2886
|
),
|
|
2536
2887
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2537
|
-
|
|
2888
|
+
import_react_native11.Animated.View,
|
|
2538
2889
|
{
|
|
2539
2890
|
style: [
|
|
2540
2891
|
{
|
|
@@ -2555,7 +2906,7 @@ function StudioSheetPager({ activePage, width, preview, chat, style }) {
|
|
|
2555
2906
|
|
|
2556
2907
|
// src/components/bubble/Bubble.tsx
|
|
2557
2908
|
var import_react = require("react");
|
|
2558
|
-
var
|
|
2909
|
+
var import_react_native12 = require("react-native");
|
|
2559
2910
|
var Haptics = __toESM(require("expo-haptics"));
|
|
2560
2911
|
var import_react_native_reanimated = __toESM(require("react-native-reanimated"));
|
|
2561
2912
|
var import_liquid_glass3 = require("@callstack/liquid-glass");
|
|
@@ -2627,7 +2978,7 @@ function Bubble({
|
|
|
2627
2978
|
backgroundColor
|
|
2628
2979
|
}) {
|
|
2629
2980
|
const theme = useTheme();
|
|
2630
|
-
const { width, height } = (0,
|
|
2981
|
+
const { width, height } = (0, import_react_native12.useWindowDimensions)();
|
|
2631
2982
|
const isDanger = variant === "danger";
|
|
2632
2983
|
const onPressRef = (0, import_react.useRef)(onPress);
|
|
2633
2984
|
(0, import_react.useEffect)(() => {
|
|
@@ -2720,7 +3071,7 @@ function Bubble({
|
|
|
2720
3071
|
}
|
|
2721
3072
|
}, [forceShowTrigger, visible, animateIn]);
|
|
2722
3073
|
const panResponder = (0, import_react.useRef)(
|
|
2723
|
-
|
|
3074
|
+
import_react_native12.PanResponder.create({
|
|
2724
3075
|
onStartShouldSetPanResponder: () => true,
|
|
2725
3076
|
onMoveShouldSetPanResponder: () => true,
|
|
2726
3077
|
onPanResponderGrant: () => {
|
|
@@ -2783,24 +3134,24 @@ function Bubble({
|
|
|
2783
3134
|
interactive: true,
|
|
2784
3135
|
effect: "clear",
|
|
2785
3136
|
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2786
|
-
|
|
3137
|
+
import_react_native12.Pressable,
|
|
2787
3138
|
{
|
|
2788
3139
|
onPress: () => {
|
|
2789
3140
|
if (!disabled) animateOut();
|
|
2790
3141
|
},
|
|
2791
3142
|
style: styles.buttonInner,
|
|
2792
3143
|
android_ripple: { color: "rgba(255, 255, 255, 0.3)", borderless: true },
|
|
2793
|
-
children: children ?? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3144
|
+
children: children ?? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native12.View, {})
|
|
2794
3145
|
}
|
|
2795
3146
|
)
|
|
2796
3147
|
}
|
|
2797
3148
|
) }),
|
|
2798
|
-
badgeCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3149
|
+
badgeCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native12.View, { style: [styles.badge, { backgroundColor: theme.colors.danger }], children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native12.Text, { style: [styles.badgeText, { color: theme.colors.onDanger }], children: badgeCount > 99 ? "99+" : badgeCount }) })
|
|
2799
3150
|
]
|
|
2800
3151
|
}
|
|
2801
3152
|
);
|
|
2802
3153
|
}
|
|
2803
|
-
var styles =
|
|
3154
|
+
var styles = import_react_native12.StyleSheet.create({
|
|
2804
3155
|
floatingButton: {
|
|
2805
3156
|
position: "absolute",
|
|
2806
3157
|
justifyContent: "center",
|
|
@@ -2837,7 +3188,7 @@ var styles = import_react_native11.StyleSheet.create({
|
|
|
2837
3188
|
|
|
2838
3189
|
// src/components/overlays/EdgeGlowFrame.tsx
|
|
2839
3190
|
var React14 = __toESM(require("react"));
|
|
2840
|
-
var
|
|
3191
|
+
var import_react_native13 = require("react-native");
|
|
2841
3192
|
var import_expo_linear_gradient = require("expo-linear-gradient");
|
|
2842
3193
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
2843
3194
|
function baseColor(role, theme) {
|
|
@@ -2862,9 +3213,9 @@ function EdgeGlowFrame({
|
|
|
2862
3213
|
}) {
|
|
2863
3214
|
const theme = useTheme();
|
|
2864
3215
|
const alpha = Math.max(0, Math.min(1, intensity));
|
|
2865
|
-
const anim = React14.useRef(new
|
|
3216
|
+
const anim = React14.useRef(new import_react_native13.Animated.Value(visible ? 1 : 0)).current;
|
|
2866
3217
|
React14.useEffect(() => {
|
|
2867
|
-
|
|
3218
|
+
import_react_native13.Animated.timing(anim, {
|
|
2868
3219
|
toValue: visible ? 1 : 0,
|
|
2869
3220
|
duration: 300,
|
|
2870
3221
|
useNativeDriver: true
|
|
@@ -2873,8 +3224,8 @@ function EdgeGlowFrame({
|
|
|
2873
3224
|
const c = baseColor(role, theme);
|
|
2874
3225
|
const strong = withAlpha(c, 0.6 * alpha);
|
|
2875
3226
|
const soft = withAlpha(c, 0.22 * alpha);
|
|
2876
|
-
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2877
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
3227
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native13.Animated.View, { pointerEvents: "none", style: [{ position: "absolute", inset: 0, opacity: anim }, style], children: [
|
|
3228
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native13.View, { style: { position: "absolute", top: 0, left: 0, right: 0, height: thickness }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2878
3229
|
import_expo_linear_gradient.LinearGradient,
|
|
2879
3230
|
{
|
|
2880
3231
|
colors: [strong, soft, "transparent"],
|
|
@@ -2883,7 +3234,7 @@ function EdgeGlowFrame({
|
|
|
2883
3234
|
style: { width: "100%", height: "100%" }
|
|
2884
3235
|
}
|
|
2885
3236
|
) }),
|
|
2886
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
3237
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native13.View, { style: { position: "absolute", bottom: 0, left: 0, right: 0, height: thickness }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2887
3238
|
import_expo_linear_gradient.LinearGradient,
|
|
2888
3239
|
{
|
|
2889
3240
|
colors: ["transparent", soft, strong],
|
|
@@ -2892,7 +3243,7 @@ function EdgeGlowFrame({
|
|
|
2892
3243
|
style: { width: "100%", height: "100%" }
|
|
2893
3244
|
}
|
|
2894
3245
|
) }),
|
|
2895
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
3246
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native13.View, { style: { position: "absolute", top: 0, bottom: 0, left: 0, width: thickness }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2896
3247
|
import_expo_linear_gradient.LinearGradient,
|
|
2897
3248
|
{
|
|
2898
3249
|
colors: [strong, soft, "transparent"],
|
|
@@ -2901,7 +3252,7 @@ function EdgeGlowFrame({
|
|
|
2901
3252
|
style: { width: "100%", height: "100%" }
|
|
2902
3253
|
}
|
|
2903
3254
|
) }),
|
|
2904
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
3255
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native13.View, { style: { position: "absolute", top: 0, bottom: 0, right: 0, width: thickness }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2905
3256
|
import_expo_linear_gradient.LinearGradient,
|
|
2906
3257
|
{
|
|
2907
3258
|
colors: ["transparent", soft, strong],
|
|
@@ -2915,12 +3266,12 @@ function EdgeGlowFrame({
|
|
|
2915
3266
|
|
|
2916
3267
|
// src/components/draw/DrawModeOverlay.tsx
|
|
2917
3268
|
var React17 = __toESM(require("react"));
|
|
2918
|
-
var
|
|
3269
|
+
var import_react_native17 = require("react-native");
|
|
2919
3270
|
var import_react_native_view_shot = require("react-native-view-shot");
|
|
2920
3271
|
|
|
2921
3272
|
// src/components/draw/DrawSurface.tsx
|
|
2922
3273
|
var React15 = __toESM(require("react"));
|
|
2923
|
-
var
|
|
3274
|
+
var import_react_native14 = require("react-native");
|
|
2924
3275
|
var import_react_native_svg = __toESM(require("react-native-svg"));
|
|
2925
3276
|
|
|
2926
3277
|
// src/components/draw/strokes.ts
|
|
@@ -2991,7 +3342,7 @@ function DrawSurface({
|
|
|
2991
3342
|
triggerRender();
|
|
2992
3343
|
}, [color, onAddStroke, strokeWidth, triggerRender]);
|
|
2993
3344
|
const panResponder = React15.useMemo(
|
|
2994
|
-
() =>
|
|
3345
|
+
() => import_react_native14.PanResponder.create({
|
|
2995
3346
|
onStartShouldSetPanResponder: () => true,
|
|
2996
3347
|
onMoveShouldSetPanResponder: () => true,
|
|
2997
3348
|
onPanResponderGrant: onStart,
|
|
@@ -3003,7 +3354,7 @@ function DrawSurface({
|
|
|
3003
3354
|
);
|
|
3004
3355
|
const currentPath = pointsToSmoothPath(currentPointsRef.current);
|
|
3005
3356
|
void renderTick;
|
|
3006
|
-
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
3357
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native14.View, { style: [import_react_native14.StyleSheet.absoluteFill, styles2.container, style], ...panResponder.panHandlers, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native_svg.default, { style: import_react_native14.StyleSheet.absoluteFill, width: "100%", height: "100%", children: [
|
|
3007
3358
|
strokes.map((s, idx) => {
|
|
3008
3359
|
const d = pointsToSmoothPath(s.points);
|
|
3009
3360
|
if (!d) return null;
|
|
@@ -3033,7 +3384,7 @@ function DrawSurface({
|
|
|
3033
3384
|
) : null
|
|
3034
3385
|
] }) });
|
|
3035
3386
|
}
|
|
3036
|
-
var styles2 =
|
|
3387
|
+
var styles2 = import_react_native14.StyleSheet.create({
|
|
3037
3388
|
container: {
|
|
3038
3389
|
zIndex: 5
|
|
3039
3390
|
}
|
|
@@ -3041,7 +3392,7 @@ var styles2 = import_react_native13.StyleSheet.create({
|
|
|
3041
3392
|
|
|
3042
3393
|
// src/components/draw/DrawToolbar.tsx
|
|
3043
3394
|
var React16 = __toESM(require("react"));
|
|
3044
|
-
var
|
|
3395
|
+
var import_react_native16 = require("react-native");
|
|
3045
3396
|
var import_react_native_safe_area_context2 = require("react-native-safe-area-context");
|
|
3046
3397
|
var import_lucide_react_native = require("lucide-react-native");
|
|
3047
3398
|
|
|
@@ -3060,7 +3411,7 @@ async function impact(style) {
|
|
|
3060
3411
|
}
|
|
3061
3412
|
|
|
3062
3413
|
// src/components/draw/DrawColorPicker.tsx
|
|
3063
|
-
var
|
|
3414
|
+
var import_react_native15 = require("react-native");
|
|
3064
3415
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
3065
3416
|
function DrawColorPicker({
|
|
3066
3417
|
colors,
|
|
@@ -3095,10 +3446,10 @@ function DrawColorPicker({
|
|
|
3095
3446
|
return { ...base, ...selectedStyle, ...whiteStyle };
|
|
3096
3447
|
};
|
|
3097
3448
|
if (!expanded) {
|
|
3098
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3449
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native15.Pressable, { onPress: onToggle, style: [swatchStyle(selected, true), style] });
|
|
3099
3450
|
}
|
|
3100
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3101
|
-
|
|
3451
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native15.View, { style: [{ flexDirection: "row", alignItems: "center", gap: 8 }, style], children: colors.map((c, idx) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3452
|
+
import_react_native15.Pressable,
|
|
3102
3453
|
{
|
|
3103
3454
|
onPress: () => {
|
|
3104
3455
|
onSelect(c);
|
|
@@ -3129,14 +3480,14 @@ function DrawToolbar({
|
|
|
3129
3480
|
style
|
|
3130
3481
|
}) {
|
|
3131
3482
|
const insets = (0, import_react_native_safe_area_context2.useSafeAreaInsets)();
|
|
3132
|
-
const { width: screenWidth, height: screenHeight } = (0,
|
|
3483
|
+
const { width: screenWidth, height: screenHeight } = (0, import_react_native16.useWindowDimensions)();
|
|
3133
3484
|
const [expanded, setExpanded] = React16.useState(false);
|
|
3134
|
-
const pos = React16.useRef(new
|
|
3485
|
+
const pos = React16.useRef(new import_react_native16.Animated.ValueXY({ x: screenWidth / 2 - 110, y: -140 })).current;
|
|
3135
3486
|
const start = React16.useRef({ x: 0, y: 0 });
|
|
3136
3487
|
const currentPos = React16.useRef({ x: 0, y: 0 });
|
|
3137
3488
|
React16.useEffect(() => {
|
|
3138
3489
|
if (hidden) return;
|
|
3139
|
-
|
|
3490
|
+
import_react_native16.Animated.spring(pos.y, {
|
|
3140
3491
|
toValue: insets.top + 60,
|
|
3141
3492
|
useNativeDriver: true,
|
|
3142
3493
|
damping: 12,
|
|
@@ -3163,7 +3514,7 @@ function DrawToolbar({
|
|
|
3163
3514
|
[insets.top, screenHeight, screenWidth]
|
|
3164
3515
|
);
|
|
3165
3516
|
const panResponder = React16.useMemo(
|
|
3166
|
-
() =>
|
|
3517
|
+
() => import_react_native16.PanResponder.create({
|
|
3167
3518
|
onStartShouldSetPanResponder: () => false,
|
|
3168
3519
|
onMoveShouldSetPanResponder: (_e, g) => Math.abs(g.dx) > 5 || Math.abs(g.dy) > 5,
|
|
3169
3520
|
onPanResponderGrant: () => {
|
|
@@ -3175,7 +3526,7 @@ function DrawToolbar({
|
|
|
3175
3526
|
},
|
|
3176
3527
|
onPanResponderRelease: () => {
|
|
3177
3528
|
const next = clamp2(currentPos.current.x, currentPos.current.y);
|
|
3178
|
-
|
|
3529
|
+
import_react_native16.Animated.spring(pos, { toValue: next, useNativeDriver: true }).start();
|
|
3179
3530
|
}
|
|
3180
3531
|
}),
|
|
3181
3532
|
[clamp2, pos]
|
|
@@ -3192,7 +3543,7 @@ function DrawToolbar({
|
|
|
3192
3543
|
const isDisabled = Boolean(disabled) || Boolean(capturingDisabled);
|
|
3193
3544
|
const [pressed, setPressed] = React16.useState(false);
|
|
3194
3545
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3195
|
-
|
|
3546
|
+
import_react_native16.View,
|
|
3196
3547
|
{
|
|
3197
3548
|
style: {
|
|
3198
3549
|
width: 28,
|
|
@@ -3204,7 +3555,7 @@ function DrawToolbar({
|
|
|
3204
3555
|
opacity: isDisabled ? 0.5 : pressed ? 0.85 : 1
|
|
3205
3556
|
},
|
|
3206
3557
|
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3207
|
-
|
|
3558
|
+
import_react_native16.Pressable,
|
|
3208
3559
|
{
|
|
3209
3560
|
accessibilityRole: "button",
|
|
3210
3561
|
accessibilityLabel,
|
|
@@ -3221,7 +3572,7 @@ function DrawToolbar({
|
|
|
3221
3572
|
);
|
|
3222
3573
|
}
|
|
3223
3574
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3224
|
-
|
|
3575
|
+
import_react_native16.Animated.View,
|
|
3225
3576
|
{
|
|
3226
3577
|
style: [
|
|
3227
3578
|
{
|
|
@@ -3238,7 +3589,7 @@ function DrawToolbar({
|
|
|
3238
3589
|
],
|
|
3239
3590
|
...panResponder.panHandlers,
|
|
3240
3591
|
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3241
|
-
|
|
3592
|
+
import_react_native16.View,
|
|
3242
3593
|
{
|
|
3243
3594
|
style: {
|
|
3244
3595
|
backgroundColor: "#F43F5E",
|
|
@@ -3246,7 +3597,7 @@ function DrawToolbar({
|
|
|
3246
3597
|
padding: 12,
|
|
3247
3598
|
minWidth: 220
|
|
3248
3599
|
},
|
|
3249
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
3600
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native16.View, { style: { flexDirection: "row", alignItems: "center", gap: 8 }, children: [
|
|
3250
3601
|
renderDragHandle ? renderDragHandle() : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react_native.GripVertical, { size: 20, color: "rgba(255, 255, 255, 0.6)" }),
|
|
3251
3602
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3252
3603
|
DrawColorPicker,
|
|
@@ -3264,7 +3615,7 @@ function DrawToolbar({
|
|
|
3264
3615
|
}
|
|
3265
3616
|
}
|
|
3266
3617
|
),
|
|
3267
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3618
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native16.View, { style: { width: 1, height: 20, backgroundColor: "rgba(255, 255, 255, 0.3)", marginHorizontal: 4 } }),
|
|
3268
3619
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3269
3620
|
CircleActionButton,
|
|
3270
3621
|
{
|
|
@@ -3302,7 +3653,7 @@ function DrawToolbar({
|
|
|
3302
3653
|
void impact("medium");
|
|
3303
3654
|
onDone();
|
|
3304
3655
|
},
|
|
3305
|
-
children: capturing ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3656
|
+
children: capturing ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native16.ActivityIndicator, { color: "#FFFFFF", size: "small" }) : renderDoneIcon ? renderDoneIcon() : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react_native.Check, { size: 16, color: "#FFFFFF" })
|
|
3306
3657
|
}
|
|
3307
3658
|
)
|
|
3308
3659
|
] })
|
|
@@ -3387,7 +3738,7 @@ function DrawModeOverlay({
|
|
|
3387
3738
|
}
|
|
3388
3739
|
}, [captureTargetRef, capturing, onCapture]);
|
|
3389
3740
|
if (!visible) return null;
|
|
3390
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
3741
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native17.View, { style: [import_react_native17.StyleSheet.absoluteFill, styles3.root, style], pointerEvents: "box-none", children: [
|
|
3391
3742
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(EdgeGlowFrame, { visible: !hideUi, role: "danger", thickness: 50, intensity: 1 }),
|
|
3392
3743
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3393
3744
|
DrawSurface,
|
|
@@ -3418,7 +3769,7 @@ function DrawModeOverlay({
|
|
|
3418
3769
|
)
|
|
3419
3770
|
] });
|
|
3420
3771
|
}
|
|
3421
|
-
var styles3 =
|
|
3772
|
+
var styles3 = import_react_native17.StyleSheet.create({
|
|
3422
3773
|
root: {
|
|
3423
3774
|
zIndex: 9999
|
|
3424
3775
|
}
|
|
@@ -3426,7 +3777,7 @@ var styles3 = import_react_native16.StyleSheet.create({
|
|
|
3426
3777
|
|
|
3427
3778
|
// src/components/comments/AppCommentsSheet.tsx
|
|
3428
3779
|
var React24 = __toESM(require("react"));
|
|
3429
|
-
var
|
|
3780
|
+
var import_react_native23 = require("react-native");
|
|
3430
3781
|
var import_bottom_sheet3 = require("@gorhom/bottom-sheet");
|
|
3431
3782
|
var import_react_native_safe_area_context3 = require("react-native-safe-area-context");
|
|
3432
3783
|
var import_liquid_glass5 = require("@callstack/liquid-glass");
|
|
@@ -3434,13 +3785,13 @@ var import_lucide_react_native4 = require("lucide-react-native");
|
|
|
3434
3785
|
|
|
3435
3786
|
// src/components/chat/ChatComposer.tsx
|
|
3436
3787
|
var React19 = __toESM(require("react"));
|
|
3437
|
-
var
|
|
3788
|
+
var import_react_native19 = require("react-native");
|
|
3438
3789
|
var import_liquid_glass4 = require("@callstack/liquid-glass");
|
|
3439
3790
|
var import_lucide_react_native3 = require("lucide-react-native");
|
|
3440
3791
|
|
|
3441
3792
|
// src/components/chat/MultilineTextInput.tsx
|
|
3442
3793
|
var React18 = __toESM(require("react"));
|
|
3443
|
-
var
|
|
3794
|
+
var import_react_native18 = require("react-native");
|
|
3444
3795
|
var import_bottom_sheet2 = require("@gorhom/bottom-sheet");
|
|
3445
3796
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
3446
3797
|
var MultilineTextInput = React18.forwardRef(function MultilineTextInput2({ useBottomSheetTextInput = false, placeholder, placeholderTextColor, style, ...props }, ref) {
|
|
@@ -3463,7 +3814,7 @@ var MultilineTextInput = React18.forwardRef(function MultilineTextInput2({ useBo
|
|
|
3463
3814
|
style: [baseStyle, style],
|
|
3464
3815
|
textAlignVertical: "top"
|
|
3465
3816
|
};
|
|
3466
|
-
return useBottomSheetTextInput ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_bottom_sheet2.BottomSheetTextInput, { ref, ...commonProps }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3817
|
+
return useBottomSheetTextInput ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_bottom_sheet2.BottomSheetTextInput, { ref, ...commonProps }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native18.TextInput, { ref, ...commonProps });
|
|
3467
3818
|
});
|
|
3468
3819
|
|
|
3469
3820
|
// src/components/icons/StudioIcons.tsx
|
|
@@ -3517,9 +3868,9 @@ function AspectRatioThumbnail({
|
|
|
3517
3868
|
renderRemoveIcon
|
|
3518
3869
|
}) {
|
|
3519
3870
|
const [aspectRatio, setAspectRatio] = React19.useState(1);
|
|
3520
|
-
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
3521
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3522
|
-
|
|
3871
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_react_native19.View, { style: { height: THUMBNAIL_HEIGHT, aspectRatio, position: "relative" }, children: [
|
|
3872
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native19.View, { style: { flex: 1, borderRadius: 8, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3873
|
+
import_react_native19.Image,
|
|
3523
3874
|
{
|
|
3524
3875
|
source: { uri },
|
|
3525
3876
|
style: { width: "100%", height: "100%" },
|
|
@@ -3532,7 +3883,7 @@ function AspectRatioThumbnail({
|
|
|
3532
3883
|
}
|
|
3533
3884
|
) }),
|
|
3534
3885
|
onRemove ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3535
|
-
|
|
3886
|
+
import_react_native19.Pressable,
|
|
3536
3887
|
{
|
|
3537
3888
|
style: {
|
|
3538
3889
|
position: "absolute",
|
|
@@ -3579,17 +3930,17 @@ function ChatComposer({
|
|
|
3579
3930
|
const hasText = text.trim().length > 0;
|
|
3580
3931
|
const composerMinHeight = hasAttachments ? THUMBNAIL_HEIGHT + 44 + 24 : 44;
|
|
3581
3932
|
const isButtonDisabled = sending || disabled || sendDisabled;
|
|
3582
|
-
const maxInputHeight = React19.useMemo(() =>
|
|
3583
|
-
const shakeAnim = React19.useRef(new
|
|
3933
|
+
const maxInputHeight = React19.useMemo(() => import_react_native19.Dimensions.get("window").height * 0.5, []);
|
|
3934
|
+
const shakeAnim = React19.useRef(new import_react_native19.Animated.Value(0)).current;
|
|
3584
3935
|
const [sendPressed, setSendPressed] = React19.useState(false);
|
|
3585
3936
|
const triggerShake = React19.useCallback(() => {
|
|
3586
3937
|
shakeAnim.setValue(0);
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3938
|
+
import_react_native19.Animated.sequence([
|
|
3939
|
+
import_react_native19.Animated.timing(shakeAnim, { toValue: 10, duration: 50, useNativeDriver: true }),
|
|
3940
|
+
import_react_native19.Animated.timing(shakeAnim, { toValue: -10, duration: 50, useNativeDriver: true }),
|
|
3941
|
+
import_react_native19.Animated.timing(shakeAnim, { toValue: 10, duration: 50, useNativeDriver: true }),
|
|
3942
|
+
import_react_native19.Animated.timing(shakeAnim, { toValue: -10, duration: 50, useNativeDriver: true }),
|
|
3943
|
+
import_react_native19.Animated.timing(shakeAnim, { toValue: 0, duration: 50, useNativeDriver: true })
|
|
3593
3944
|
]).start();
|
|
3594
3945
|
}, [shakeAnim]);
|
|
3595
3946
|
const handleSend = React19.useCallback(async () => {
|
|
@@ -3606,12 +3957,12 @@ function ChatComposer({
|
|
|
3606
3957
|
const placeholderTextColor = theme.scheme === "dark" ? "#A1A1AA" : "#71717A";
|
|
3607
3958
|
const sendBg = withAlpha(theme.colors.primary, isButtonDisabled ? 0.6 : sendPressed ? 0.9 : 1);
|
|
3608
3959
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3609
|
-
|
|
3960
|
+
import_react_native19.View,
|
|
3610
3961
|
{
|
|
3611
3962
|
style: [{ paddingHorizontal: 16, paddingBottom: 12, paddingTop: 8 }, style],
|
|
3612
3963
|
onLayout: (e) => onLayout == null ? void 0 : onLayout({ height: e.nativeEvent.layout.height }),
|
|
3613
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
3614
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3964
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_react_native19.View, { style: { flexDirection: "row", alignItems: "flex-end", gap: 8 }, children: [
|
|
3965
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native19.Animated.View, { style: { flex: 1, transform: [{ translateX: shakeAnim }] }, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
3615
3966
|
import_liquid_glass4.LiquidGlassView,
|
|
3616
3967
|
{
|
|
3617
3968
|
style: [
|
|
@@ -3624,7 +3975,7 @@ function ChatComposer({
|
|
|
3624
3975
|
effect: "clear",
|
|
3625
3976
|
children: [
|
|
3626
3977
|
hasAttachments ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
3627
|
-
|
|
3978
|
+
import_react_native19.ScrollView,
|
|
3628
3979
|
{
|
|
3629
3980
|
horizontal: true,
|
|
3630
3981
|
showsHorizontalScrollIndicator: false,
|
|
@@ -3641,7 +3992,7 @@ function ChatComposer({
|
|
|
3641
3992
|
`attachment-${index}`
|
|
3642
3993
|
)),
|
|
3643
3994
|
onAddAttachment ? renderAddAttachment ? renderAddAttachment() : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3644
|
-
|
|
3995
|
+
import_react_native19.Pressable,
|
|
3645
3996
|
{
|
|
3646
3997
|
style: {
|
|
3647
3998
|
height: THUMBNAIL_HEIGHT,
|
|
@@ -3692,7 +4043,7 @@ function ChatComposer({
|
|
|
3692
4043
|
interactive: true,
|
|
3693
4044
|
effect: "clear",
|
|
3694
4045
|
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3695
|
-
|
|
4046
|
+
import_react_native19.View,
|
|
3696
4047
|
{
|
|
3697
4048
|
style: {
|
|
3698
4049
|
width: 44,
|
|
@@ -3702,7 +4053,7 @@ function ChatComposer({
|
|
|
3702
4053
|
backgroundColor: sendBg
|
|
3703
4054
|
},
|
|
3704
4055
|
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3705
|
-
|
|
4056
|
+
import_react_native19.Pressable,
|
|
3706
4057
|
{
|
|
3707
4058
|
accessibilityRole: "button",
|
|
3708
4059
|
accessibilityLabel: "Send",
|
|
@@ -3711,7 +4062,7 @@ function ChatComposer({
|
|
|
3711
4062
|
onPressIn: () => setSendPressed(true),
|
|
3712
4063
|
onPressOut: () => setSendPressed(false),
|
|
3713
4064
|
style: { flex: 1, alignItems: "center", justifyContent: "center" },
|
|
3714
|
-
children: sending ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
4065
|
+
children: sending ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native19.ActivityIndicator, {}) : renderSendIcon ? renderSendIcon() : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconChevronRight, { size: 20, colorToken: "onPrimary" })
|
|
3715
4066
|
}
|
|
3716
4067
|
)
|
|
3717
4068
|
}
|
|
@@ -3725,10 +4076,10 @@ function ChatComposer({
|
|
|
3725
4076
|
|
|
3726
4077
|
// src/components/comments/CommentRow.tsx
|
|
3727
4078
|
var React20 = __toESM(require("react"));
|
|
3728
|
-
var
|
|
4079
|
+
var import_react_native21 = require("react-native");
|
|
3729
4080
|
|
|
3730
4081
|
// src/components/primitives/Avatar.tsx
|
|
3731
|
-
var
|
|
4082
|
+
var import_react_native20 = require("react-native");
|
|
3732
4083
|
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
3733
4084
|
function initialsFrom(name) {
|
|
3734
4085
|
var _a, _b;
|
|
@@ -3748,7 +4099,7 @@ function Avatar({
|
|
|
3748
4099
|
const radius = size / 2;
|
|
3749
4100
|
const fallbackBg = fallbackBackgroundColor ?? theme.colors.neutral;
|
|
3750
4101
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3751
|
-
|
|
4102
|
+
import_react_native20.View,
|
|
3752
4103
|
{
|
|
3753
4104
|
style: [
|
|
3754
4105
|
{
|
|
@@ -3763,7 +4114,7 @@ function Avatar({
|
|
|
3763
4114
|
style
|
|
3764
4115
|
],
|
|
3765
4116
|
children: uri ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3766
|
-
|
|
4117
|
+
import_react_native20.Image,
|
|
3767
4118
|
{
|
|
3768
4119
|
source: { uri },
|
|
3769
4120
|
style: [{ width: size, height: size }, imageStyle],
|
|
@@ -3814,7 +4165,7 @@ function CommentRow({ comment, showDivider }) {
|
|
|
3814
4165
|
};
|
|
3815
4166
|
}, [comment.authorId]);
|
|
3816
4167
|
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
3817
|
-
|
|
4168
|
+
import_react_native21.View,
|
|
3818
4169
|
{
|
|
3819
4170
|
style: {
|
|
3820
4171
|
flexDirection: "row",
|
|
@@ -3825,8 +4176,8 @@ function CommentRow({ comment, showDivider }) {
|
|
|
3825
4176
|
},
|
|
3826
4177
|
children: [
|
|
3827
4178
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Avatar, { size: 32, uri: authorAvatar, name: authorName ?? comment.authorId, style: { marginTop: 6 } }),
|
|
3828
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
3829
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
4179
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_react_native21.View, { style: { flex: 1, minWidth: 0, gap: 4 }, children: [
|
|
4180
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_react_native21.View, { style: { flexDirection: "row", alignItems: "center", gap: theme.spacing.sm }, children: [
|
|
3830
4181
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Text, { style: { fontSize: 14, lineHeight: 18, fontWeight: theme.typography.fontWeight.bold, color: theme.colors.text }, children: authorName ?? "Unknown User" }),
|
|
3831
4182
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Text, { style: { fontSize: 12, lineHeight: 16, color: theme.colors.textMuted }, children: formatTimeAgo(comment.createdAt) })
|
|
3832
4183
|
] }),
|
|
@@ -3951,7 +4302,18 @@ function useAppComments(appId) {
|
|
|
3951
4302
|
try {
|
|
3952
4303
|
const newComment = await appCommentsRepository.create(appId, { body: trimmed, commentType: "general" });
|
|
3953
4304
|
setComments((prev) => sortByCreatedAtAsc([...prev, newComment]));
|
|
4305
|
+
await trackSubmitComment({
|
|
4306
|
+
appId,
|
|
4307
|
+
commentLength: trimmed.length,
|
|
4308
|
+
success: true
|
|
4309
|
+
});
|
|
3954
4310
|
} catch (e) {
|
|
4311
|
+
await trackSubmitComment({
|
|
4312
|
+
appId,
|
|
4313
|
+
commentLength: trimmed.length,
|
|
4314
|
+
success: false,
|
|
4315
|
+
error: e
|
|
4316
|
+
});
|
|
3955
4317
|
setError(e instanceof Error ? e : new Error(String(e)));
|
|
3956
4318
|
throw e;
|
|
3957
4319
|
} finally {
|
|
@@ -3994,13 +4356,13 @@ function useAppDetails(appId) {
|
|
|
3994
4356
|
|
|
3995
4357
|
// src/components/comments/useIosKeyboardSnapFix.ts
|
|
3996
4358
|
var React23 = __toESM(require("react"));
|
|
3997
|
-
var
|
|
4359
|
+
var import_react_native22 = require("react-native");
|
|
3998
4360
|
function useIosKeyboardSnapFix(sheetRef, options) {
|
|
3999
4361
|
const [keyboardVisible, setKeyboardVisible] = React23.useState(false);
|
|
4000
4362
|
React23.useEffect(() => {
|
|
4001
|
-
if (
|
|
4002
|
-
const show =
|
|
4003
|
-
const hide =
|
|
4363
|
+
if (import_react_native22.Platform.OS !== "ios") return;
|
|
4364
|
+
const show = import_react_native22.Keyboard.addListener("keyboardWillShow", () => setKeyboardVisible(true));
|
|
4365
|
+
const hide = import_react_native22.Keyboard.addListener("keyboardWillHide", () => {
|
|
4004
4366
|
var _a;
|
|
4005
4367
|
setKeyboardVisible(false);
|
|
4006
4368
|
const target = (options == null ? void 0 : options.targetIndex) ?? 1;
|
|
@@ -4076,17 +4438,17 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
4076
4438
|
onChange: handleChange,
|
|
4077
4439
|
backgroundStyle: {
|
|
4078
4440
|
backgroundColor: theme.scheme === "dark" ? "#0B080F" : "#FFFFFF",
|
|
4079
|
-
borderTopLeftRadius:
|
|
4080
|
-
borderTopRightRadius:
|
|
4441
|
+
borderTopLeftRadius: import_react_native23.Platform.OS === "ios" ? 39 : 16,
|
|
4442
|
+
borderTopRightRadius: import_react_native23.Platform.OS === "ios" ? 39 : 16
|
|
4081
4443
|
},
|
|
4082
4444
|
handleIndicatorStyle: { backgroundColor: theme.colors.handleIndicator },
|
|
4083
4445
|
keyboardBehavior: "interactive",
|
|
4084
4446
|
keyboardBlurBehavior: "restore",
|
|
4085
4447
|
android_keyboardInputMode: "adjustResize",
|
|
4086
4448
|
topInset: insets.top,
|
|
4087
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
4449
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_native23.View, { style: { flex: 1 }, children: [
|
|
4088
4450
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
4089
|
-
|
|
4451
|
+
import_react_native23.View,
|
|
4090
4452
|
{
|
|
4091
4453
|
style: {
|
|
4092
4454
|
flexDirection: "row",
|
|
@@ -4122,7 +4484,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
4122
4484
|
interactive: true,
|
|
4123
4485
|
effect: "clear",
|
|
4124
4486
|
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
4125
|
-
|
|
4487
|
+
import_react_native23.View,
|
|
4126
4488
|
{
|
|
4127
4489
|
style: {
|
|
4128
4490
|
width: 32,
|
|
@@ -4133,7 +4495,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
4133
4495
|
justifyContent: "center"
|
|
4134
4496
|
},
|
|
4135
4497
|
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
4136
|
-
|
|
4498
|
+
import_react_native23.Pressable,
|
|
4137
4499
|
{
|
|
4138
4500
|
disabled: !appId,
|
|
4139
4501
|
onPress: () => void handlePlay(),
|
|
@@ -4168,13 +4530,13 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
4168
4530
|
},
|
|
4169
4531
|
keyboardShouldPersistTaps: "handled",
|
|
4170
4532
|
children: [
|
|
4171
|
-
loading && comments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
4533
|
+
loading && comments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native23.View, { style: { flex: 1, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native23.ActivityIndicator, {}) }) : comments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native23.View, { style: { flex: 1, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Text, { variant: "bodyMuted", style: { textAlign: "center" }, children: "No comments yet" }) }) : comments.map((c, idx) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CommentRow, { comment: c, showDivider: idx < comments.length - 1 }, c.id)),
|
|
4172
4534
|
error ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Text, { variant: "captionMuted", style: { marginTop: theme.spacing.lg }, children: "Failed to load comments." }) : null
|
|
4173
4535
|
]
|
|
4174
4536
|
}
|
|
4175
4537
|
),
|
|
4176
4538
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
4177
|
-
|
|
4539
|
+
import_react_native23.View,
|
|
4178
4540
|
{
|
|
4179
4541
|
style: {
|
|
4180
4542
|
position: "absolute",
|
|
@@ -4183,7 +4545,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
4183
4545
|
bottom: 0,
|
|
4184
4546
|
paddingHorizontal: theme.spacing.lg,
|
|
4185
4547
|
paddingTop: theme.spacing.sm,
|
|
4186
|
-
paddingBottom:
|
|
4548
|
+
paddingBottom: import_react_native23.Platform.OS === "ios" ? keyboardVisible ? theme.spacing.lg : insets.bottom : insets.bottom + 10,
|
|
4187
4549
|
borderTopWidth: 1,
|
|
4188
4550
|
borderTopColor: withAlpha(theme.colors.border, 0.1),
|
|
4189
4551
|
backgroundColor: withAlpha(theme.colors.background, 0.8)
|
|
@@ -4197,7 +4559,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
4197
4559
|
useBottomSheetTextInput: true,
|
|
4198
4560
|
onSend: async (text) => {
|
|
4199
4561
|
await create(text);
|
|
4200
|
-
|
|
4562
|
+
import_react_native23.Keyboard.dismiss();
|
|
4201
4563
|
}
|
|
4202
4564
|
}
|
|
4203
4565
|
)
|
|
@@ -4210,16 +4572,16 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
4210
4572
|
|
|
4211
4573
|
// src/studio/ui/PreviewPanel.tsx
|
|
4212
4574
|
var React35 = __toESM(require("react"));
|
|
4213
|
-
var
|
|
4575
|
+
var import_react_native44 = require("react-native");
|
|
4214
4576
|
|
|
4215
4577
|
// src/components/preview/PreviewPage.tsx
|
|
4216
|
-
var
|
|
4578
|
+
var import_react_native24 = require("react-native");
|
|
4217
4579
|
var import_bottom_sheet4 = require("@gorhom/bottom-sheet");
|
|
4218
4580
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
4219
4581
|
function PreviewPage({ header, children, contentStyle }) {
|
|
4220
4582
|
const theme = useTheme();
|
|
4221
|
-
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
4222
|
-
header ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4583
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_native24.View, { style: { flex: 1 }, children: [
|
|
4584
|
+
header ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native24.View, { children: header }) : null,
|
|
4223
4585
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4224
4586
|
import_bottom_sheet4.BottomSheetScrollView,
|
|
4225
4587
|
{
|
|
@@ -4239,15 +4601,15 @@ function PreviewPage({ header, children, contentStyle }) {
|
|
|
4239
4601
|
}
|
|
4240
4602
|
|
|
4241
4603
|
// src/studio/ui/preview-panel/PreviewPanelHeader.tsx
|
|
4242
|
-
var
|
|
4604
|
+
var import_react_native27 = require("react-native");
|
|
4243
4605
|
|
|
4244
4606
|
// src/components/studio-sheet/StudioSheetHeader.tsx
|
|
4245
|
-
var
|
|
4607
|
+
var import_react_native25 = require("react-native");
|
|
4246
4608
|
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
4247
4609
|
function StudioSheetHeader({ left, center, right, style }) {
|
|
4248
4610
|
const theme = useTheme();
|
|
4249
4611
|
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
4250
|
-
|
|
4612
|
+
import_react_native25.View,
|
|
4251
4613
|
{
|
|
4252
4614
|
style: [
|
|
4253
4615
|
{
|
|
@@ -4260,9 +4622,9 @@ function StudioSheetHeader({ left, center, right, style }) {
|
|
|
4260
4622
|
style
|
|
4261
4623
|
],
|
|
4262
4624
|
children: [
|
|
4263
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4264
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4265
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4625
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.View, { style: { flexDirection: "row", alignItems: "center" }, children: left }),
|
|
4626
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.View, { style: { flex: 1, alignItems: "center" }, children: center }),
|
|
4627
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.View, { style: { flexDirection: "row", alignItems: "center" }, children: right })
|
|
4266
4628
|
]
|
|
4267
4629
|
}
|
|
4268
4630
|
);
|
|
@@ -4270,7 +4632,7 @@ function StudioSheetHeader({ left, center, right, style }) {
|
|
|
4270
4632
|
|
|
4271
4633
|
// src/components/studio-sheet/StudioSheetHeaderIconButton.tsx
|
|
4272
4634
|
var React25 = __toESM(require("react"));
|
|
4273
|
-
var
|
|
4635
|
+
var import_react_native26 = require("react-native");
|
|
4274
4636
|
var import_liquid_glass6 = require("@callstack/liquid-glass");
|
|
4275
4637
|
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
4276
4638
|
function StudioSheetHeaderIconButton({
|
|
@@ -4290,14 +4652,14 @@ function StudioSheetHeaderIconButton({
|
|
|
4290
4652
|
const glassInnerBg = intent === "danger" ? theme.colors.danger : theme.colors.primary;
|
|
4291
4653
|
const resolvedOpacity = disabled ? 0.6 : pressed ? 0.9 : 1;
|
|
4292
4654
|
const glassBg = withAlpha(glassInnerBg, resolvedOpacity);
|
|
4293
|
-
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4655
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_native26.View, { style, children: appearance === "glass" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4294
4656
|
ResettableLiquidGlassView,
|
|
4295
4657
|
{
|
|
4296
4658
|
style: [{ borderRadius: 100 }, !import_liquid_glass6.isLiquidGlassSupported && { backgroundColor: glassFallbackBg }],
|
|
4297
4659
|
interactive: true,
|
|
4298
4660
|
effect: "clear",
|
|
4299
4661
|
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4300
|
-
|
|
4662
|
+
import_react_native26.View,
|
|
4301
4663
|
{
|
|
4302
4664
|
style: {
|
|
4303
4665
|
width: size,
|
|
@@ -4308,7 +4670,7 @@ function StudioSheetHeaderIconButton({
|
|
|
4308
4670
|
backgroundColor: glassBg
|
|
4309
4671
|
},
|
|
4310
4672
|
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4311
|
-
|
|
4673
|
+
import_react_native26.Pressable,
|
|
4312
4674
|
{
|
|
4313
4675
|
accessibilityRole: "button",
|
|
4314
4676
|
accessibilityLabel,
|
|
@@ -4327,7 +4689,7 @@ function StudioSheetHeaderIconButton({
|
|
|
4327
4689
|
)
|
|
4328
4690
|
}
|
|
4329
4691
|
) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4330
|
-
|
|
4692
|
+
import_react_native26.View,
|
|
4331
4693
|
{
|
|
4332
4694
|
style: {
|
|
4333
4695
|
width: size,
|
|
@@ -4339,7 +4701,7 @@ function StudioSheetHeaderIconButton({
|
|
|
4339
4701
|
opacity: resolvedOpacity
|
|
4340
4702
|
},
|
|
4341
4703
|
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4342
|
-
|
|
4704
|
+
import_react_native26.Pressable,
|
|
4343
4705
|
{
|
|
4344
4706
|
accessibilityRole: "button",
|
|
4345
4707
|
accessibilityLabel,
|
|
@@ -4373,7 +4735,7 @@ function PreviewPanelHeader({
|
|
|
4373
4735
|
{
|
|
4374
4736
|
left: onNavigateHome ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(StudioSheetHeaderIconButton, { onPress: onNavigateHome, accessibilityLabel: "Home", appearance: "glass", intent: "primary", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(IconHome, { size: 20, colorToken: "onPrimary" }) }) : null,
|
|
4375
4737
|
center: null,
|
|
4376
|
-
right: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
4738
|
+
right: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
4377
4739
|
isOwner ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4378
4740
|
StudioSheetHeaderIconButton,
|
|
4379
4741
|
{
|
|
@@ -4403,10 +4765,10 @@ function PreviewPanelHeader({
|
|
|
4403
4765
|
}
|
|
4404
4766
|
|
|
4405
4767
|
// src/components/preview/PreviewHeroCard.tsx
|
|
4406
|
-
var
|
|
4768
|
+
var import_react_native29 = require("react-native");
|
|
4407
4769
|
|
|
4408
4770
|
// src/components/primitives/Surface.tsx
|
|
4409
|
-
var
|
|
4771
|
+
var import_react_native28 = require("react-native");
|
|
4410
4772
|
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
4411
4773
|
function backgroundFor(variant, theme) {
|
|
4412
4774
|
const { colors } = theme;
|
|
@@ -4425,7 +4787,7 @@ function backgroundFor(variant, theme) {
|
|
|
4425
4787
|
function Surface({ variant = "surface", border = false, style, ...props }) {
|
|
4426
4788
|
const theme = useTheme();
|
|
4427
4789
|
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4428
|
-
|
|
4790
|
+
import_react_native28.View,
|
|
4429
4791
|
{
|
|
4430
4792
|
...props,
|
|
4431
4793
|
style: [
|
|
@@ -4481,11 +4843,11 @@ function PreviewHeroCard({
|
|
|
4481
4843
|
},
|
|
4482
4844
|
style
|
|
4483
4845
|
],
|
|
4484
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
4485
|
-
background ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
4486
|
-
image ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
4487
|
-
overlayTopLeft ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
4488
|
-
overlayBottom ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
4846
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react_native29.View, { style: { flex: 1 }, children: [
|
|
4847
|
+
background ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_native29.View, { style: { position: "absolute", inset: 0 }, children: background }) : null,
|
|
4848
|
+
image ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_native29.View, { style: { position: "absolute", inset: 0 }, children: image }) : null,
|
|
4849
|
+
overlayTopLeft ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_native29.View, { style: { position: "absolute", top: theme.spacing.sm, left: theme.spacing.sm, zIndex: 2 }, children: overlayTopLeft }) : null,
|
|
4850
|
+
overlayBottom ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_native29.View, { style: { flex: 1, justifyContent: "flex-end" }, children: overlayBottom }) : null
|
|
4489
4851
|
] })
|
|
4490
4852
|
}
|
|
4491
4853
|
);
|
|
@@ -4493,20 +4855,20 @@ function PreviewHeroCard({
|
|
|
4493
4855
|
|
|
4494
4856
|
// src/components/preview/PreviewPlaceholder.tsx
|
|
4495
4857
|
var React26 = __toESM(require("react"));
|
|
4496
|
-
var
|
|
4858
|
+
var import_react_native30 = require("react-native");
|
|
4497
4859
|
var import_expo_linear_gradient2 = require("expo-linear-gradient");
|
|
4498
4860
|
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
4499
4861
|
function PreviewPlaceholder({ visible, style }) {
|
|
4500
4862
|
if (!visible) return null;
|
|
4501
|
-
const opacityAnim = React26.useRef(new
|
|
4863
|
+
const opacityAnim = React26.useRef(new import_react_native30.Animated.Value(0)).current;
|
|
4502
4864
|
React26.useEffect(() => {
|
|
4503
4865
|
if (!visible) return;
|
|
4504
|
-
const animation =
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4866
|
+
const animation = import_react_native30.Animated.loop(
|
|
4867
|
+
import_react_native30.Animated.sequence([
|
|
4868
|
+
import_react_native30.Animated.timing(opacityAnim, { toValue: 1, duration: 1500, useNativeDriver: true }),
|
|
4869
|
+
import_react_native30.Animated.timing(opacityAnim, { toValue: 2, duration: 1500, useNativeDriver: true }),
|
|
4870
|
+
import_react_native30.Animated.timing(opacityAnim, { toValue: 3, duration: 1500, useNativeDriver: true }),
|
|
4871
|
+
import_react_native30.Animated.timing(opacityAnim, { toValue: 0, duration: 1500, useNativeDriver: true })
|
|
4510
4872
|
])
|
|
4511
4873
|
);
|
|
4512
4874
|
animation.start();
|
|
@@ -4517,7 +4879,7 @@ function PreviewPlaceholder({ visible, style }) {
|
|
|
4517
4879
|
const opacity3 = opacityAnim.interpolate({ inputRange: [0, 1, 2, 3], outputRange: [0, 0, 1, 0] });
|
|
4518
4880
|
const opacity4 = opacityAnim.interpolate({ inputRange: [0, 1, 2, 3], outputRange: [0, 0, 0, 1] });
|
|
4519
4881
|
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
4520
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4882
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_native30.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity1 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4521
4883
|
import_expo_linear_gradient2.LinearGradient,
|
|
4522
4884
|
{
|
|
4523
4885
|
colors: ["rgba(98, 0, 238, 0.45)", "rgba(168, 85, 247, 0.35)"],
|
|
@@ -4526,7 +4888,7 @@ function PreviewPlaceholder({ visible, style }) {
|
|
|
4526
4888
|
style: { width: "100%", height: "100%" }
|
|
4527
4889
|
}
|
|
4528
4890
|
) }),
|
|
4529
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4891
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_native30.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity2 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4530
4892
|
import_expo_linear_gradient2.LinearGradient,
|
|
4531
4893
|
{
|
|
4532
4894
|
colors: ["rgba(168, 85, 247, 0.45)", "rgba(139, 92, 246, 0.35)"],
|
|
@@ -4535,7 +4897,7 @@ function PreviewPlaceholder({ visible, style }) {
|
|
|
4535
4897
|
style: { width: "100%", height: "100%" }
|
|
4536
4898
|
}
|
|
4537
4899
|
) }),
|
|
4538
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4900
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_native30.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity3 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4539
4901
|
import_expo_linear_gradient2.LinearGradient,
|
|
4540
4902
|
{
|
|
4541
4903
|
colors: ["rgba(139, 92, 246, 0.45)", "rgba(126, 34, 206, 0.35)"],
|
|
@@ -4544,7 +4906,7 @@ function PreviewPlaceholder({ visible, style }) {
|
|
|
4544
4906
|
style: { width: "100%", height: "100%" }
|
|
4545
4907
|
}
|
|
4546
4908
|
) }),
|
|
4547
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4909
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_native30.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity4 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4548
4910
|
import_expo_linear_gradient2.LinearGradient,
|
|
4549
4911
|
{
|
|
4550
4912
|
colors: ["rgba(126, 34, 206, 0.45)", "rgba(98, 0, 238, 0.35)"],
|
|
@@ -4557,12 +4919,12 @@ function PreviewPlaceholder({ visible, style }) {
|
|
|
4557
4919
|
}
|
|
4558
4920
|
|
|
4559
4921
|
// src/components/preview/PreviewImage.tsx
|
|
4560
|
-
var
|
|
4922
|
+
var import_react_native31 = require("react-native");
|
|
4561
4923
|
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
4562
4924
|
function PreviewImage({ uri, onLoad, style }) {
|
|
4563
4925
|
if (!uri) return null;
|
|
4564
4926
|
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
4565
|
-
|
|
4927
|
+
import_react_native31.Image,
|
|
4566
4928
|
{
|
|
4567
4929
|
source: { uri },
|
|
4568
4930
|
resizeMode: "cover",
|
|
@@ -4573,7 +4935,7 @@ function PreviewImage({ uri, onLoad, style }) {
|
|
|
4573
4935
|
}
|
|
4574
4936
|
|
|
4575
4937
|
// src/components/preview/StatsBar.tsx
|
|
4576
|
-
var
|
|
4938
|
+
var import_react_native32 = require("react-native");
|
|
4577
4939
|
var import_liquid_glass7 = require("@callstack/liquid-glass");
|
|
4578
4940
|
var import_lucide_react_native5 = require("lucide-react-native");
|
|
4579
4941
|
|
|
@@ -4606,7 +4968,7 @@ function StatsBar({
|
|
|
4606
4968
|
const theme = useTheme();
|
|
4607
4969
|
const statsBgColor = theme.scheme === "dark" ? "rgba(24, 24, 27, 0.5)" : "rgba(255, 255, 255, 0.5)";
|
|
4608
4970
|
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
4609
|
-
|
|
4971
|
+
import_react_native32.View,
|
|
4610
4972
|
{
|
|
4611
4973
|
style: [
|
|
4612
4974
|
{ position: "absolute", bottom: 12, width: "100%", paddingHorizontal: 12 },
|
|
@@ -4622,15 +4984,15 @@ function StatsBar({
|
|
|
4622
4984
|
!import_liquid_glass7.isLiquidGlassSupported && { backgroundColor: statsBgColor }
|
|
4623
4985
|
],
|
|
4624
4986
|
effect: "clear",
|
|
4625
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
4987
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_react_native32.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: 16 }, children: [
|
|
4626
4988
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
4627
|
-
|
|
4989
|
+
import_react_native32.Pressable,
|
|
4628
4990
|
{
|
|
4629
4991
|
disabled: !onPressLike,
|
|
4630
4992
|
onPress: onPressLike,
|
|
4631
4993
|
hitSlop: 8,
|
|
4632
4994
|
style: { paddingVertical: 8 },
|
|
4633
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
4995
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_react_native32.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
4634
4996
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
4635
4997
|
import_lucide_react_native5.Heart,
|
|
4636
4998
|
{
|
|
@@ -4640,7 +5002,7 @@ function StatsBar({
|
|
|
4640
5002
|
fill: isLiked ? theme.colors.danger : "transparent"
|
|
4641
5003
|
}
|
|
4642
5004
|
),
|
|
4643
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
5005
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react_native32.View, { style: { width: 4 } }),
|
|
4644
5006
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
4645
5007
|
Text,
|
|
4646
5008
|
{
|
|
@@ -4656,22 +5018,22 @@ function StatsBar({
|
|
|
4656
5018
|
}
|
|
4657
5019
|
),
|
|
4658
5020
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
4659
|
-
|
|
5021
|
+
import_react_native32.Pressable,
|
|
4660
5022
|
{
|
|
4661
5023
|
disabled: !onPressComments,
|
|
4662
5024
|
onPress: onPressComments,
|
|
4663
5025
|
hitSlop: 8,
|
|
4664
5026
|
style: { paddingVertical: 8 },
|
|
4665
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
5027
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_react_native32.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
4666
5028
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react_native5.MessageCircle, { size: 16, strokeWidth: 2.5, color: "#FFFFFF" }),
|
|
4667
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
5029
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react_native32.View, { style: { width: 4 } }),
|
|
4668
5030
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Text, { variant: "caption", style: { color: "#FFFFFF", fontWeight: theme.typography.fontWeight.bold }, children: commentCount })
|
|
4669
5031
|
] })
|
|
4670
5032
|
}
|
|
4671
5033
|
),
|
|
4672
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
4673
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
4674
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
5034
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_react_native32.View, { style: { flexDirection: "row", alignItems: "center", paddingVertical: 8 }, children: [
|
|
5035
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react_native32.View, { style: { transform: [{ scaleY: -1 }] }, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(MergeIcon, { width: 14, height: 14, color: "#FFFFFF" }) }),
|
|
5036
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react_native32.View, { style: { width: 4 } }),
|
|
4675
5037
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Text, { variant: "caption", style: { color: "#FFFFFF", fontWeight: theme.typography.fontWeight.bold }, children: forkCount })
|
|
4676
5038
|
] })
|
|
4677
5039
|
] })
|
|
@@ -4682,7 +5044,7 @@ function StatsBar({
|
|
|
4682
5044
|
}
|
|
4683
5045
|
|
|
4684
5046
|
// src/components/preview/PreviewStatusBadge.tsx
|
|
4685
|
-
var
|
|
5047
|
+
var import_react_native33 = require("react-native");
|
|
4686
5048
|
var import_lucide_react_native6 = require("lucide-react-native");
|
|
4687
5049
|
|
|
4688
5050
|
// src/data/apps/types.ts
|
|
@@ -4727,7 +5089,7 @@ function PreviewStatusBadge({ status }) {
|
|
|
4727
5089
|
const IconComp = STATUS_ICON[status];
|
|
4728
5090
|
const label = APP_STATUS_LABEL[status] ?? status;
|
|
4729
5091
|
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
4730
|
-
|
|
5092
|
+
import_react_native33.View,
|
|
4731
5093
|
{
|
|
4732
5094
|
style: {
|
|
4733
5095
|
flexDirection: "row",
|
|
@@ -4780,10 +5142,10 @@ function PreviewHeroSection({
|
|
|
4780
5142
|
}
|
|
4781
5143
|
|
|
4782
5144
|
// src/studio/ui/preview-panel/PreviewMetaSection.tsx
|
|
4783
|
-
var
|
|
5145
|
+
var import_react_native35 = require("react-native");
|
|
4784
5146
|
|
|
4785
5147
|
// src/components/preview/PreviewMetaRow.tsx
|
|
4786
|
-
var
|
|
5148
|
+
var import_react_native34 = require("react-native");
|
|
4787
5149
|
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
4788
5150
|
function PreviewMetaRow({
|
|
4789
5151
|
avatarUri,
|
|
@@ -4795,10 +5157,10 @@ function PreviewMetaRow({
|
|
|
4795
5157
|
style
|
|
4796
5158
|
}) {
|
|
4797
5159
|
const theme = useTheme();
|
|
4798
|
-
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
4799
|
-
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
5160
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react_native34.View, { style: [{ alignSelf: "stretch" }, style], children: [
|
|
5161
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react_native34.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
4800
5162
|
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Avatar, { uri: avatarUri, name: creatorName, size: 24, style: { marginRight: theme.spacing.sm } }),
|
|
4801
|
-
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
5163
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react_native34.View, { style: { flexDirection: "row", alignItems: "center", flex: 1, minWidth: 0, marginRight: theme.spacing.sm }, children: [
|
|
4802
5164
|
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
4803
5165
|
Text,
|
|
4804
5166
|
{
|
|
@@ -4813,9 +5175,9 @@ function PreviewMetaRow({
|
|
|
4813
5175
|
children: title
|
|
4814
5176
|
}
|
|
4815
5177
|
),
|
|
4816
|
-
tag ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
5178
|
+
tag ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react_native34.View, { style: { marginLeft: theme.spacing.sm }, children: tag }) : null
|
|
4817
5179
|
] }),
|
|
4818
|
-
rightMetric ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
5180
|
+
rightMetric ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react_native34.View, { children: rightMetric }) : null
|
|
4819
5181
|
] }),
|
|
4820
5182
|
subtitle ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
4821
5183
|
Text,
|
|
@@ -4871,9 +5233,9 @@ function PreviewMetaSection({ app, isOwner, creator, downloadsCount }) {
|
|
|
4871
5233
|
subtitle: app.description,
|
|
4872
5234
|
avatarUri: (creator == null ? void 0 : creator.avatar) ?? null,
|
|
4873
5235
|
creatorName: (creator == null ? void 0 : creator.name) ?? null,
|
|
4874
|
-
tag: isOwner || app.forkedFromAppId ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
5236
|
+
tag: isOwner || app.forkedFromAppId ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react_native35.View, { style: { paddingHorizontal: 8, paddingVertical: 2, borderRadius: 999, backgroundColor: "#007A75" }, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Text, { variant: "caption", style: { color: "#fff", fontWeight: theme.typography.fontWeight.semibold }, children: app.forkedFromAppId ? "Remix" : "Owner" }) }) : null,
|
|
4875
5237
|
rightMetric: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
|
|
4876
|
-
|
|
5238
|
+
import_react_native35.View,
|
|
4877
5239
|
{
|
|
4878
5240
|
style: {
|
|
4879
5241
|
flexDirection: "row",
|
|
@@ -4907,10 +5269,10 @@ function PreviewMetaSection({ app, isOwner, creator, downloadsCount }) {
|
|
|
4907
5269
|
}
|
|
4908
5270
|
|
|
4909
5271
|
// src/studio/ui/preview-panel/PreviewCustomizeSection.tsx
|
|
4910
|
-
var
|
|
5272
|
+
var import_react_native37 = require("react-native");
|
|
4911
5273
|
|
|
4912
5274
|
// src/studio/ui/preview-panel/PressableCardRow.tsx
|
|
4913
|
-
var
|
|
5275
|
+
var import_react_native36 = require("react-native");
|
|
4914
5276
|
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
4915
5277
|
function PressableCardRow({
|
|
4916
5278
|
accessibilityLabel,
|
|
@@ -4923,20 +5285,20 @@ function PressableCardRow({
|
|
|
4923
5285
|
style
|
|
4924
5286
|
}) {
|
|
4925
5287
|
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
4926
|
-
|
|
5288
|
+
import_react_native36.Pressable,
|
|
4927
5289
|
{
|
|
4928
5290
|
accessibilityRole: "button",
|
|
4929
5291
|
accessibilityLabel,
|
|
4930
5292
|
disabled,
|
|
4931
5293
|
onPress,
|
|
4932
5294
|
style: ({ pressed }) => ({ opacity: disabled ? 0.6 : pressed ? 0.85 : 1 }),
|
|
4933
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Card, { padded: false, border: false, style, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
5295
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Card, { padded: false, border: false, style, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_react_native36.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
4934
5296
|
left,
|
|
4935
|
-
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
5297
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_react_native36.View, { style: { flex: 1, minWidth: 0 }, children: [
|
|
4936
5298
|
title,
|
|
4937
5299
|
subtitle ? subtitle : null
|
|
4938
5300
|
] }),
|
|
4939
|
-
right ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
5301
|
+
right ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react_native36.View, { style: { marginLeft: 16 }, children: right }) : null
|
|
4940
5302
|
] }) })
|
|
4941
5303
|
}
|
|
4942
5304
|
);
|
|
@@ -4978,7 +5340,7 @@ function PreviewCustomizeSection({
|
|
|
4978
5340
|
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_jsx_runtime38.Fragment, { children: [
|
|
4979
5341
|
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(SectionTitle, { children: "Customize" }),
|
|
4980
5342
|
showProcessing ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
4981
|
-
|
|
5343
|
+
import_react_native37.View,
|
|
4982
5344
|
{
|
|
4983
5345
|
style: {
|
|
4984
5346
|
flexDirection: "row",
|
|
@@ -4992,7 +5354,7 @@ function PreviewCustomizeSection({
|
|
|
4992
5354
|
},
|
|
4993
5355
|
children: [
|
|
4994
5356
|
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
4995
|
-
|
|
5357
|
+
import_react_native37.View,
|
|
4996
5358
|
{
|
|
4997
5359
|
style: {
|
|
4998
5360
|
width: 40,
|
|
@@ -5003,10 +5365,10 @@ function PreviewCustomizeSection({
|
|
|
5003
5365
|
backgroundColor: withAlpha(theme.colors.warning, 0.1),
|
|
5004
5366
|
marginRight: theme.spacing.lg
|
|
5005
5367
|
},
|
|
5006
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
5368
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_react_native37.ActivityIndicator, { color: theme.colors.warning, size: "small" })
|
|
5007
5369
|
}
|
|
5008
5370
|
),
|
|
5009
|
-
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
5371
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_react_native37.View, { style: { flex: 1, minWidth: 0 }, children: [
|
|
5010
5372
|
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Text, { style: { color: theme.colors.text, fontSize: 16, lineHeight: 20, fontWeight: theme.typography.fontWeight.semibold }, children: app.status === "error" ? "Error" : "Processing" }),
|
|
5011
5373
|
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Text, { style: { color: theme.colors.textMuted, fontSize: 12, lineHeight: 16, marginTop: 2 }, children: statusDescription(app.status, app.statusError) })
|
|
5012
5374
|
] })
|
|
@@ -5027,7 +5389,7 @@ function PreviewCustomizeSection({
|
|
|
5027
5389
|
marginBottom: theme.spacing.sm
|
|
5028
5390
|
},
|
|
5029
5391
|
left: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
5030
|
-
|
|
5392
|
+
import_react_native37.View,
|
|
5031
5393
|
{
|
|
5032
5394
|
style: {
|
|
5033
5395
|
width: 40,
|
|
@@ -5060,7 +5422,7 @@ function PreviewCustomizeSection({
|
|
|
5060
5422
|
marginBottom: theme.spacing.sm
|
|
5061
5423
|
},
|
|
5062
5424
|
left: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
5063
|
-
|
|
5425
|
+
import_react_native37.View,
|
|
5064
5426
|
{
|
|
5065
5427
|
style: {
|
|
5066
5428
|
width: 40,
|
|
@@ -5084,16 +5446,16 @@ function PreviewCustomizeSection({
|
|
|
5084
5446
|
|
|
5085
5447
|
// src/studio/ui/preview-panel/PreviewCollaborateSection.tsx
|
|
5086
5448
|
var React32 = __toESM(require("react"));
|
|
5087
|
-
var
|
|
5449
|
+
var import_react_native43 = require("react-native");
|
|
5088
5450
|
var import_lucide_react_native9 = require("lucide-react-native");
|
|
5089
5451
|
|
|
5090
5452
|
// src/components/merge-requests/MergeRequestStatusCard.tsx
|
|
5091
5453
|
var React28 = __toESM(require("react"));
|
|
5092
|
-
var
|
|
5454
|
+
var import_react_native39 = require("react-native");
|
|
5093
5455
|
var import_lucide_react_native7 = require("lucide-react-native");
|
|
5094
5456
|
|
|
5095
5457
|
// src/components/primitives/MarkdownText.tsx
|
|
5096
|
-
var
|
|
5458
|
+
var import_react_native38 = require("react-native");
|
|
5097
5459
|
var import_react_native_markdown_display = __toESM(require("react-native-markdown-display"));
|
|
5098
5460
|
var import_react2 = require("react");
|
|
5099
5461
|
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
@@ -5137,7 +5499,7 @@ function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
|
|
|
5137
5499
|
const codeTextColor = isDark ? "#FFFFFF" : theme.colors.text;
|
|
5138
5500
|
const paragraphBottom = variant === "mergeRequest" ? 8 : 6;
|
|
5139
5501
|
const baseLineHeight = variant === "mergeRequest" ? 22 : 20;
|
|
5140
|
-
const screen =
|
|
5502
|
+
const screen = import_react_native38.Dimensions.get("window");
|
|
5141
5503
|
const tooltipPadding = theme.spacing.sm;
|
|
5142
5504
|
const tooltipYOffset = theme.spacing.lg + 32;
|
|
5143
5505
|
const minTooltipY = theme.spacing.xl;
|
|
@@ -5167,7 +5529,7 @@ function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
|
|
|
5167
5529
|
setShowCopied(false);
|
|
5168
5530
|
}, 1200);
|
|
5169
5531
|
};
|
|
5170
|
-
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
5532
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_react_native38.Pressable, { style, onPress: import_react_native38.Keyboard.dismiss, onLongPress: handleLongPress, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_react_native38.View, { style: { position: "relative" }, children: [
|
|
5171
5533
|
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
5172
5534
|
import_react_native_markdown_display.default,
|
|
5173
5535
|
{
|
|
@@ -5181,7 +5543,7 @@ function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
|
|
|
5181
5543
|
paddingHorizontal: variant === "mergeRequest" ? 6 : 4,
|
|
5182
5544
|
paddingVertical: variant === "mergeRequest" ? 2 : 0,
|
|
5183
5545
|
borderRadius: variant === "mergeRequest" ? 6 : 4,
|
|
5184
|
-
fontFamily:
|
|
5546
|
+
fontFamily: import_react_native38.Platform.OS === "ios" ? "Menlo" : "monospace",
|
|
5185
5547
|
fontSize: 13
|
|
5186
5548
|
},
|
|
5187
5549
|
code_block: {
|
|
@@ -5202,8 +5564,8 @@ function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
|
|
|
5202
5564
|
children: markdown
|
|
5203
5565
|
}
|
|
5204
5566
|
),
|
|
5205
|
-
showCopied && tooltipAnchor ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
5206
|
-
|
|
5567
|
+
showCopied && tooltipAnchor ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_react_native38.Modal, { transparent: true, visible: true, statusBarTranslucent: true, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_react_native38.View, { pointerEvents: "none", style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
5568
|
+
import_react_native38.View,
|
|
5207
5569
|
{
|
|
5208
5570
|
pointerEvents: "none",
|
|
5209
5571
|
style: {
|
|
@@ -5217,7 +5579,7 @@ function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
|
|
|
5217
5579
|
},
|
|
5218
5580
|
onLayout: (event) => setTooltipWidth(event.nativeEvent.layout.width),
|
|
5219
5581
|
children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
5220
|
-
|
|
5582
|
+
import_react_native38.Text,
|
|
5221
5583
|
{
|
|
5222
5584
|
style: {
|
|
5223
5585
|
color: theme.colors.onSuccess,
|
|
@@ -5321,15 +5683,15 @@ function MergeRequestStatusCard({
|
|
|
5321
5683
|
const createdIso = toIsoString(mergeRequest.createdAt ?? null);
|
|
5322
5684
|
const headerTimeAgo = updatedIso ? formatTimeAgo(updatedIso) : "";
|
|
5323
5685
|
const createdTimeAgo = createdIso ? formatTimeAgo(createdIso) : "";
|
|
5324
|
-
const rotate = React28.useRef(new
|
|
5686
|
+
const rotate = React28.useRef(new import_react_native39.Animated.Value(expanded ? 1 : 0)).current;
|
|
5325
5687
|
React28.useEffect(() => {
|
|
5326
|
-
|
|
5688
|
+
import_react_native39.Animated.timing(rotate, {
|
|
5327
5689
|
toValue: expanded ? 1 : 0,
|
|
5328
5690
|
duration: 200,
|
|
5329
5691
|
useNativeDriver: true
|
|
5330
5692
|
}).start();
|
|
5331
5693
|
}, [expanded, rotate]);
|
|
5332
|
-
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
5694
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_native39.Pressable, { onPress: () => setExpanded(!expanded), style: ({ pressed }) => [{ opacity: pressed ? 0.95 : 1 }], children: /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
5333
5695
|
Card,
|
|
5334
5696
|
{
|
|
5335
5697
|
padded: false,
|
|
@@ -5342,10 +5704,10 @@ function MergeRequestStatusCard({
|
|
|
5342
5704
|
style
|
|
5343
5705
|
],
|
|
5344
5706
|
children: [
|
|
5345
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
5346
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
5347
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
5348
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
5707
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native39.View, { style: { flexDirection: "row", alignItems: "center", gap: theme.spacing.lg }, children: [
|
|
5708
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_native39.View, { style: { width: 40, height: 40, borderRadius: 999, alignItems: "center", justifyContent: "center", backgroundColor: bgColor }, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(StatusIcon, { size: 20, color: iconColor }) }),
|
|
5709
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native39.View, { style: { flex: 1, minWidth: 0 }, children: [
|
|
5710
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native39.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
5349
5711
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
5350
5712
|
Text,
|
|
5351
5713
|
{
|
|
@@ -5364,8 +5726,8 @@ function MergeRequestStatusCard({
|
|
|
5364
5726
|
] }),
|
|
5365
5727
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Text, { style: { fontSize: 12, lineHeight: 16, color: theme.colors.textMuted }, numberOfLines: 1, children: mergeRequest.title ?? "Untitled merge request" })
|
|
5366
5728
|
] }),
|
|
5367
|
-
headerRight ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
5368
|
-
|
|
5729
|
+
headerRight ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_native39.View, { children: headerRight }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
5730
|
+
import_react_native39.Animated.View,
|
|
5369
5731
|
{
|
|
5370
5732
|
style: {
|
|
5371
5733
|
transform: [
|
|
@@ -5378,7 +5740,7 @@ function MergeRequestStatusCard({
|
|
|
5378
5740
|
}
|
|
5379
5741
|
)
|
|
5380
5742
|
] }),
|
|
5381
|
-
expanded ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
5743
|
+
expanded ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native39.View, { style: { marginTop: 16, marginLeft: 56 }, children: [
|
|
5382
5744
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
5383
5745
|
Text,
|
|
5384
5746
|
{
|
|
@@ -5414,16 +5776,16 @@ function MergeRequestStatusCard({
|
|
|
5414
5776
|
|
|
5415
5777
|
// src/components/merge-requests/ReviewMergeRequestCarousel.tsx
|
|
5416
5778
|
var React31 = __toESM(require("react"));
|
|
5417
|
-
var
|
|
5779
|
+
var import_react_native42 = require("react-native");
|
|
5418
5780
|
|
|
5419
5781
|
// src/components/merge-requests/ReviewMergeRequestCard.tsx
|
|
5420
5782
|
var React30 = __toESM(require("react"));
|
|
5421
|
-
var
|
|
5783
|
+
var import_react_native41 = require("react-native");
|
|
5422
5784
|
var import_lucide_react_native8 = require("lucide-react-native");
|
|
5423
5785
|
|
|
5424
5786
|
// src/components/merge-requests/ReviewMergeRequestActionButton.tsx
|
|
5425
5787
|
var React29 = __toESM(require("react"));
|
|
5426
|
-
var
|
|
5788
|
+
var import_react_native40 = require("react-native");
|
|
5427
5789
|
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
5428
5790
|
function ReviewMergeRequestActionButton({
|
|
5429
5791
|
accessibilityLabel,
|
|
@@ -5440,7 +5802,7 @@ function ReviewMergeRequestActionButton({
|
|
|
5440
5802
|
const paddingVertical = iconOnly ? 0 : 8;
|
|
5441
5803
|
const opacity = disabled ? 0.5 : pressed ? 0.9 : 1;
|
|
5442
5804
|
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
5443
|
-
|
|
5805
|
+
import_react_native40.View,
|
|
5444
5806
|
{
|
|
5445
5807
|
style: {
|
|
5446
5808
|
width,
|
|
@@ -5455,7 +5817,7 @@ function ReviewMergeRequestActionButton({
|
|
|
5455
5817
|
justifyContent: "center"
|
|
5456
5818
|
},
|
|
5457
5819
|
children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
5458
|
-
|
|
5820
|
+
import_react_native40.Pressable,
|
|
5459
5821
|
{
|
|
5460
5822
|
accessibilityRole: "button",
|
|
5461
5823
|
accessibilityLabel,
|
|
@@ -5497,12 +5859,12 @@ function ReviewMergeRequestCard({
|
|
|
5497
5859
|
const theme = useTheme();
|
|
5498
5860
|
const status = React30.useMemo(() => getMergeRequestStatusDisplay(mr.status), [mr.status]);
|
|
5499
5861
|
const canAct = mr.status === "open";
|
|
5500
|
-
const rotate = React30.useRef(new
|
|
5862
|
+
const rotate = React30.useRef(new import_react_native41.Animated.Value(isExpanded ? 1 : 0)).current;
|
|
5501
5863
|
React30.useEffect(() => {
|
|
5502
|
-
|
|
5864
|
+
import_react_native41.Animated.timing(rotate, { toValue: isExpanded ? 1 : 0, duration: 200, useNativeDriver: true }).start();
|
|
5503
5865
|
}, [isExpanded, rotate]);
|
|
5504
5866
|
const position = total > 1 ? `${index + 1}/${total}` : "Merge request";
|
|
5505
|
-
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
5867
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_react_native41.Pressable, { onPress: onToggle, style: ({ pressed }) => ({ opacity: pressed ? 0.95 : 1 }), children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
5506
5868
|
Card,
|
|
5507
5869
|
{
|
|
5508
5870
|
padded: false,
|
|
@@ -5515,9 +5877,9 @@ function ReviewMergeRequestCard({
|
|
|
5515
5877
|
}
|
|
5516
5878
|
],
|
|
5517
5879
|
children: [
|
|
5518
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
5880
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native41.View, { style: { flexDirection: "row", alignItems: "center", gap: 12 }, children: [
|
|
5519
5881
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Avatar, { size: 40, uri: (creator == null ? void 0 : creator.avatar) ?? null, name: (creator == null ? void 0 : creator.name) ?? void 0 }),
|
|
5520
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
5882
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native41.View, { style: { flex: 1, minWidth: 0 }, children: [
|
|
5521
5883
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
5522
5884
|
Text,
|
|
5523
5885
|
{
|
|
@@ -5533,7 +5895,7 @@ function ReviewMergeRequestCard({
|
|
|
5533
5895
|
] })
|
|
5534
5896
|
] }),
|
|
5535
5897
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
5536
|
-
|
|
5898
|
+
import_react_native41.Animated.View,
|
|
5537
5899
|
{
|
|
5538
5900
|
style: {
|
|
5539
5901
|
transform: [{ rotate: rotate.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "180deg"] }) }]
|
|
@@ -5542,7 +5904,7 @@ function ReviewMergeRequestCard({
|
|
|
5542
5904
|
}
|
|
5543
5905
|
)
|
|
5544
5906
|
] }),
|
|
5545
|
-
isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
5907
|
+
isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native41.View, { style: { marginTop: 16 }, children: [
|
|
5546
5908
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
5547
5909
|
Text,
|
|
5548
5910
|
{
|
|
@@ -5560,9 +5922,9 @@ function ReviewMergeRequestCard({
|
|
|
5560
5922
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Text, { style: { color: theme.colors.textMuted, fontSize: 12, lineHeight: 16, marginBottom: 12 }, children: creator ? `${creator.approvedOrMergedMergeRequests} approved merge${creator.approvedOrMergedMergeRequests !== 1 ? "s" : ""}` : "Loading stats..." }),
|
|
5561
5923
|
mr.description ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(MarkdownText, { markdown: mr.description, variant: "mergeRequest" }) : null
|
|
5562
5924
|
] }) : null,
|
|
5563
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
5564
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
5565
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
5925
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_react_native41.View, { style: { height: 1, backgroundColor: withAlpha(theme.colors.borderStrong, 0.5), marginTop: 12, marginBottom: 12 } }),
|
|
5926
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native41.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
5927
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native41.View, { style: { flexDirection: "row", gap: 8 }, children: [
|
|
5566
5928
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
5567
5929
|
ReviewMergeRequestActionButton,
|
|
5568
5930
|
{
|
|
@@ -5571,7 +5933,7 @@ function ReviewMergeRequestCard({
|
|
|
5571
5933
|
disabled: !canAct || isAnyProcessing,
|
|
5572
5934
|
onPress: onReject,
|
|
5573
5935
|
iconOnly: !isExpanded,
|
|
5574
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
5936
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native41.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
|
|
5575
5937
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_lucide_react_native8.X, { size: 18, color: "#FFFFFF" }),
|
|
5576
5938
|
isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Text, { style: { fontSize: 13, color: "#FFFFFF", fontWeight: theme.typography.fontWeight.semibold }, children: "Reject" }) : null
|
|
5577
5939
|
] })
|
|
@@ -5585,10 +5947,10 @@ function ReviewMergeRequestCard({
|
|
|
5585
5947
|
disabled: !canAct || isAnyProcessing,
|
|
5586
5948
|
onPress: onApprove,
|
|
5587
5949
|
iconOnly: !isExpanded,
|
|
5588
|
-
children: isProcessing ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
5589
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
5950
|
+
children: isProcessing ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native41.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
|
|
5951
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_react_native41.ActivityIndicator, { size: "small", color: "#FFFFFF" }),
|
|
5590
5952
|
isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Text, { style: { fontSize: 13, color: "#FFFFFF", fontWeight: theme.typography.fontWeight.semibold }, children: "Processing" }) : null
|
|
5591
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
5953
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native41.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
|
|
5592
5954
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_lucide_react_native8.Check, { size: 18, color: "#FFFFFF" }),
|
|
5593
5955
|
isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Text, { style: { fontSize: 13, color: "#FFFFFF", fontWeight: theme.typography.fontWeight.semibold }, children: "Approve" }) : null
|
|
5594
5956
|
] })
|
|
@@ -5603,7 +5965,7 @@ function ReviewMergeRequestCard({
|
|
|
5603
5965
|
disabled: isBuilding || isTestingThis,
|
|
5604
5966
|
onPress: onTest,
|
|
5605
5967
|
iconOnly: !isExpanded,
|
|
5606
|
-
children: isTestingThis ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
5968
|
+
children: isTestingThis ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_react_native41.ActivityIndicator, { size: "small", color: "#888" }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native41.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
|
|
5607
5969
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_lucide_react_native8.Play, { size: 14, color: theme.colors.text }),
|
|
5608
5970
|
isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Text, { style: { fontSize: 13, color: theme.colors.text, fontWeight: theme.typography.fontWeight.semibold }, children: "Test" }) : null
|
|
5609
5971
|
] })
|
|
@@ -5629,32 +5991,32 @@ function ReviewMergeRequestCarousel({
|
|
|
5629
5991
|
style
|
|
5630
5992
|
}) {
|
|
5631
5993
|
const theme = useTheme();
|
|
5632
|
-
const { width } = (0,
|
|
5994
|
+
const { width } = (0, import_react_native42.useWindowDimensions)();
|
|
5633
5995
|
const [expanded, setExpanded] = React31.useState({});
|
|
5634
|
-
const carouselScrollX = React31.useRef(new
|
|
5996
|
+
const carouselScrollX = React31.useRef(new import_react_native42.Animated.Value(0)).current;
|
|
5635
5997
|
const peekAmount = 24;
|
|
5636
5998
|
const gap = 16;
|
|
5637
5999
|
const cardWidth = React31.useMemo(() => Math.max(1, width - theme.spacing.lg * 2 - peekAmount), [peekAmount, theme.spacing.lg, width]);
|
|
5638
6000
|
const snapInterval = cardWidth + gap;
|
|
5639
6001
|
const dotColor = theme.scheme === "dark" ? "#FFFFFF" : "#000000";
|
|
5640
6002
|
if (mergeRequests.length === 0) return null;
|
|
5641
|
-
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
6003
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_react_native42.View, { style: [{ marginHorizontal: -theme.spacing.lg }, style], children: [
|
|
5642
6004
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
5643
|
-
|
|
6005
|
+
import_react_native42.FlatList,
|
|
5644
6006
|
{
|
|
5645
6007
|
horizontal: true,
|
|
5646
6008
|
data: mergeRequests,
|
|
5647
6009
|
keyExtractor: (mr) => mr.id,
|
|
5648
6010
|
showsHorizontalScrollIndicator: false,
|
|
5649
6011
|
contentContainerStyle: { paddingHorizontal: theme.spacing.lg, paddingVertical: theme.spacing.sm },
|
|
5650
|
-
ItemSeparatorComponent: () => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
6012
|
+
ItemSeparatorComponent: () => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native42.View, { style: { width: gap } }),
|
|
5651
6013
|
snapToAlignment: "start",
|
|
5652
6014
|
decelerationRate: "fast",
|
|
5653
6015
|
snapToInterval: snapInterval,
|
|
5654
6016
|
disableIntervalMomentum: true,
|
|
5655
6017
|
style: { paddingRight: peekAmount },
|
|
5656
|
-
ListFooterComponent: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
5657
|
-
onScroll:
|
|
6018
|
+
ListFooterComponent: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native42.View, { style: { width: peekAmount } }),
|
|
6019
|
+
onScroll: import_react_native42.Animated.event([{ nativeEvent: { contentOffset: { x: carouselScrollX } } }], {
|
|
5658
6020
|
useNativeDriver: false
|
|
5659
6021
|
}),
|
|
5660
6022
|
scrollEventThrottle: 16,
|
|
@@ -5665,7 +6027,7 @@ function ReviewMergeRequestCarousel({
|
|
|
5665
6027
|
const isProcessing = Boolean(processingMrId && processingMrId === item.id);
|
|
5666
6028
|
const isAnyProcessing = Boolean(processingMrId);
|
|
5667
6029
|
const isTestingThis = Boolean(testingMrId && testingMrId === item.id);
|
|
5668
|
-
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
6030
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native42.View, { style: { width: cardWidth }, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
5669
6031
|
ReviewMergeRequestCard,
|
|
5670
6032
|
{
|
|
5671
6033
|
mr: item,
|
|
@@ -5686,7 +6048,7 @@ function ReviewMergeRequestCarousel({
|
|
|
5686
6048
|
}
|
|
5687
6049
|
}
|
|
5688
6050
|
),
|
|
5689
|
-
mergeRequests.length >= 1 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
6051
|
+
mergeRequests.length >= 1 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native42.View, { style: { flexDirection: "row", justifyContent: "center", columnGap: 8, marginTop: theme.spacing.md }, children: mergeRequests.map((mr, index) => {
|
|
5690
6052
|
const inputRange = [(index - 1) * snapInterval, index * snapInterval, (index + 1) * snapInterval];
|
|
5691
6053
|
const scale = carouselScrollX.interpolate({
|
|
5692
6054
|
inputRange,
|
|
@@ -5699,7 +6061,7 @@ function ReviewMergeRequestCarousel({
|
|
|
5699
6061
|
extrapolate: "clamp"
|
|
5700
6062
|
});
|
|
5701
6063
|
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
5702
|
-
|
|
6064
|
+
import_react_native42.Animated.View,
|
|
5703
6065
|
{
|
|
5704
6066
|
style: {
|
|
5705
6067
|
width: 8,
|
|
@@ -5766,7 +6128,7 @@ function PreviewCollaborateSection({
|
|
|
5766
6128
|
accessibilityLabel: "Submit merge request",
|
|
5767
6129
|
disabled: submittingMr,
|
|
5768
6130
|
onPress: () => {
|
|
5769
|
-
|
|
6131
|
+
import_react_native43.Alert.alert(
|
|
5770
6132
|
"Submit Merge Request",
|
|
5771
6133
|
"Are you sure you want to submit your changes to the original app?",
|
|
5772
6134
|
[
|
|
@@ -5792,7 +6154,7 @@ function PreviewCollaborateSection({
|
|
|
5792
6154
|
marginBottom: theme.spacing.sm
|
|
5793
6155
|
},
|
|
5794
6156
|
left: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
5795
|
-
|
|
6157
|
+
import_react_native43.View,
|
|
5796
6158
|
{
|
|
5797
6159
|
style: {
|
|
5798
6160
|
width: 40,
|
|
@@ -5803,7 +6165,7 @@ function PreviewCollaborateSection({
|
|
|
5803
6165
|
backgroundColor: withAlpha("#03DAC6", 0.1),
|
|
5804
6166
|
marginRight: theme.spacing.lg
|
|
5805
6167
|
},
|
|
5806
|
-
children: submittingMr ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
6168
|
+
children: submittingMr ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native43.ActivityIndicator, { color: "#03DAC6", size: "small" }) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(MergeIcon, { width: 20, height: 20, color: "#03DAC6" })
|
|
5807
6169
|
}
|
|
5808
6170
|
),
|
|
5809
6171
|
title: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Text, { style: { color: theme.colors.text, fontSize: 16, lineHeight: 20, fontWeight: theme.typography.fontWeight.semibold }, children: "Submit your new changes" }),
|
|
@@ -5817,7 +6179,7 @@ function PreviewCollaborateSection({
|
|
|
5817
6179
|
accessibilityLabel: "Sync from original",
|
|
5818
6180
|
disabled: isSyncing,
|
|
5819
6181
|
onPress: () => {
|
|
5820
|
-
|
|
6182
|
+
import_react_native43.Alert.alert(
|
|
5821
6183
|
"Sync from Original",
|
|
5822
6184
|
"This will pull the latest upstream changes into your remix.",
|
|
5823
6185
|
[
|
|
@@ -5829,12 +6191,12 @@ function PreviewCollaborateSection({
|
|
|
5829
6191
|
setSyncingLocal(true);
|
|
5830
6192
|
Promise.resolve(onSyncUpstream()).then((result) => {
|
|
5831
6193
|
if ((result == null ? void 0 : result.status) === "up-to-date") {
|
|
5832
|
-
|
|
6194
|
+
import_react_native43.Alert.alert("Up to date", "Your remix already includes the latest upstream changes.");
|
|
5833
6195
|
} else {
|
|
5834
|
-
|
|
6196
|
+
import_react_native43.Alert.alert("Sync started", "Upstream changes are being merged into your remix.");
|
|
5835
6197
|
}
|
|
5836
6198
|
}).catch(() => {
|
|
5837
|
-
|
|
6199
|
+
import_react_native43.Alert.alert("Sync failed", "We could not start the sync. Please try again.");
|
|
5838
6200
|
}).finally(() => setSyncingLocal(false));
|
|
5839
6201
|
}
|
|
5840
6202
|
}
|
|
@@ -5850,7 +6212,7 @@ function PreviewCollaborateSection({
|
|
|
5850
6212
|
marginBottom: theme.spacing.sm
|
|
5851
6213
|
},
|
|
5852
6214
|
left: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
5853
|
-
|
|
6215
|
+
import_react_native43.View,
|
|
5854
6216
|
{
|
|
5855
6217
|
style: {
|
|
5856
6218
|
width: 40,
|
|
@@ -5861,7 +6223,7 @@ function PreviewCollaborateSection({
|
|
|
5861
6223
|
backgroundColor: withAlpha(theme.colors.primary, 0.12),
|
|
5862
6224
|
marginRight: theme.spacing.lg
|
|
5863
6225
|
},
|
|
5864
|
-
children: isSyncing ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
6226
|
+
children: isSyncing ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native43.ActivityIndicator, { color: theme.colors.primary, size: "small" }) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react_native9.RefreshCw, { size: 18, color: theme.colors.primary })
|
|
5865
6227
|
}
|
|
5866
6228
|
),
|
|
5867
6229
|
title: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Text, { style: { color: theme.colors.text, fontSize: 16, lineHeight: 20, fontWeight: theme.typography.fontWeight.semibold }, children: "Sync from Original" }),
|
|
@@ -5899,7 +6261,7 @@ function PreviewCollaborateSection({
|
|
|
5899
6261
|
children: "History"
|
|
5900
6262
|
}
|
|
5901
6263
|
),
|
|
5902
|
-
outgoingMergeRequests.map((mr) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
6264
|
+
outgoingMergeRequests.map((mr) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native43.View, { style: { marginBottom: theme.spacing.sm }, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(MergeRequestStatusCard, { mergeRequest: toMergeRequestSummary(mr) }) }, mr.id))
|
|
5903
6265
|
] }) : null
|
|
5904
6266
|
] });
|
|
5905
6267
|
}
|
|
@@ -6023,7 +6385,8 @@ function useAppStats({
|
|
|
6023
6385
|
initialComments = 0,
|
|
6024
6386
|
initialForks = 0,
|
|
6025
6387
|
initialIsLiked = false,
|
|
6026
|
-
onOpenComments
|
|
6388
|
+
onOpenComments,
|
|
6389
|
+
interactionSource = "unknown"
|
|
6027
6390
|
}) {
|
|
6028
6391
|
const [likeCount, setLikeCount] = React33.useState(initialLikes);
|
|
6029
6392
|
const [commentCount, setCommentCount] = React33.useState(initialComments);
|
|
@@ -6067,23 +6430,31 @@ function useAppStats({
|
|
|
6067
6430
|
if (newIsLiked) {
|
|
6068
6431
|
const res = await appLikesRepository.create(appId, {});
|
|
6069
6432
|
if (typeof ((_a = res.stats) == null ? void 0 : _a.total) === "number") setLikeCount(Math.max(0, res.stats.total));
|
|
6433
|
+
await trackLikeApp({ appId, source: interactionSource, success: true });
|
|
6070
6434
|
} else {
|
|
6071
6435
|
const res = await appLikesRepository.removeMine(appId);
|
|
6072
6436
|
if (typeof ((_b = res.stats) == null ? void 0 : _b.total) === "number") setLikeCount(Math.max(0, res.stats.total));
|
|
6437
|
+
await trackUnlikeApp({ appId, source: interactionSource, success: true });
|
|
6073
6438
|
}
|
|
6074
6439
|
} catch (e) {
|
|
6075
6440
|
setIsLiked(!newIsLiked);
|
|
6076
6441
|
setLikeCount((prev) => Math.max(0, prev + (newIsLiked ? -1 : 1)));
|
|
6442
|
+
if (newIsLiked) {
|
|
6443
|
+
await trackLikeApp({ appId, source: interactionSource, success: false, error: e });
|
|
6444
|
+
} else {
|
|
6445
|
+
await trackUnlikeApp({ appId, source: interactionSource, success: false, error: e });
|
|
6446
|
+
}
|
|
6077
6447
|
}
|
|
6078
|
-
}, [appId, isLiked, likeCount]);
|
|
6448
|
+
}, [appId, interactionSource, isLiked, likeCount]);
|
|
6079
6449
|
const handleOpenComments = React33.useCallback(() => {
|
|
6080
6450
|
if (!appId) return;
|
|
6081
6451
|
try {
|
|
6082
6452
|
void Haptics2.impactAsync(Haptics2.ImpactFeedbackStyle.Light);
|
|
6083
6453
|
} catch {
|
|
6084
6454
|
}
|
|
6455
|
+
void trackOpenComments({ appId, source: interactionSource });
|
|
6085
6456
|
onOpenComments == null ? void 0 : onOpenComments();
|
|
6086
|
-
}, [appId, onOpenComments]);
|
|
6457
|
+
}, [appId, interactionSource, onOpenComments]);
|
|
6087
6458
|
return { likeCount, commentCount, forkCount, isLiked, setCommentCount, handleLike, handleOpenComments };
|
|
6088
6459
|
}
|
|
6089
6460
|
|
|
@@ -6166,7 +6537,8 @@ function usePreviewPanelData(params) {
|
|
|
6166
6537
|
initialForks: insights.forks,
|
|
6167
6538
|
initialComments: commentCountOverride ?? insights.comments,
|
|
6168
6539
|
initialIsLiked: Boolean(app == null ? void 0 : app.isLiked),
|
|
6169
|
-
onOpenComments
|
|
6540
|
+
onOpenComments,
|
|
6541
|
+
interactionSource: "preview_panel"
|
|
6170
6542
|
});
|
|
6171
6543
|
const canSubmitMergeRequest = React34.useMemo(() => {
|
|
6172
6544
|
if (!isOwner) return false;
|
|
@@ -6232,7 +6604,7 @@ ${shareUrl}` : `Check out this app on Remix
|
|
|
6232
6604
|
${shareUrl}`;
|
|
6233
6605
|
try {
|
|
6234
6606
|
const title = app.name ?? "Remix app";
|
|
6235
|
-
const payload =
|
|
6607
|
+
const payload = import_react_native44.Platform.OS === "ios" ? {
|
|
6236
6608
|
title,
|
|
6237
6609
|
message
|
|
6238
6610
|
} : {
|
|
@@ -6240,9 +6612,18 @@ ${shareUrl}`;
|
|
|
6240
6612
|
message,
|
|
6241
6613
|
url: shareUrl
|
|
6242
6614
|
};
|
|
6243
|
-
await
|
|
6615
|
+
await import_react_native44.Share.share(payload);
|
|
6616
|
+
await trackShareApp({
|
|
6617
|
+
appId: app.id,
|
|
6618
|
+
success: true
|
|
6619
|
+
});
|
|
6244
6620
|
} catch (error) {
|
|
6245
6621
|
log.warn("PreviewPanel share failed", error);
|
|
6622
|
+
await trackShareApp({
|
|
6623
|
+
appId: app.id,
|
|
6624
|
+
success: false,
|
|
6625
|
+
error
|
|
6626
|
+
});
|
|
6246
6627
|
}
|
|
6247
6628
|
}, [app]);
|
|
6248
6629
|
const {
|
|
@@ -6274,9 +6655,9 @@ ${shareUrl}`;
|
|
|
6274
6655
|
}
|
|
6275
6656
|
);
|
|
6276
6657
|
if (loading || !app) {
|
|
6277
|
-
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(PreviewPage, { header, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
|
|
6278
|
-
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
6279
|
-
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
6658
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(PreviewPage, { header, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_react_native44.View, { style: { flex: 1, justifyContent: "center", alignItems: "center", padding: 24 }, children: [
|
|
6659
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_react_native44.ActivityIndicator, {}),
|
|
6660
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_react_native44.View, { style: { height: 12 } }),
|
|
6280
6661
|
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Text, { variant: "bodyMuted", children: "Loading app\u2026" })
|
|
6281
6662
|
] }) });
|
|
6282
6663
|
}
|
|
@@ -6336,25 +6717,26 @@ ${shareUrl}`;
|
|
|
6336
6717
|
}
|
|
6337
6718
|
|
|
6338
6719
|
// src/studio/ui/ChatPanel.tsx
|
|
6339
|
-
var
|
|
6340
|
-
var
|
|
6720
|
+
var React42 = __toESM(require("react"));
|
|
6721
|
+
var import_react_native56 = require("react-native");
|
|
6341
6722
|
|
|
6342
6723
|
// src/components/chat/ChatPage.tsx
|
|
6343
|
-
var
|
|
6344
|
-
var
|
|
6724
|
+
var React39 = __toESM(require("react"));
|
|
6725
|
+
var import_react_native49 = require("react-native");
|
|
6345
6726
|
var import_react_native_safe_area_context4 = require("react-native-safe-area-context");
|
|
6346
6727
|
|
|
6347
6728
|
// src/components/chat/ChatMessageList.tsx
|
|
6348
|
-
var
|
|
6349
|
-
var
|
|
6729
|
+
var React38 = __toESM(require("react"));
|
|
6730
|
+
var import_react_native48 = require("react-native");
|
|
6350
6731
|
var import_bottom_sheet5 = require("@gorhom/bottom-sheet");
|
|
6351
6732
|
|
|
6352
6733
|
// src/components/chat/ChatMessageBubble.tsx
|
|
6353
|
-
var
|
|
6734
|
+
var React36 = __toESM(require("react"));
|
|
6735
|
+
var import_react_native46 = require("react-native");
|
|
6354
6736
|
var import_lucide_react_native10 = require("lucide-react-native");
|
|
6355
6737
|
|
|
6356
6738
|
// src/components/primitives/Button.tsx
|
|
6357
|
-
var
|
|
6739
|
+
var import_react_native45 = require("react-native");
|
|
6358
6740
|
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
6359
6741
|
function backgroundFor2(variant, theme, pressed, disabled) {
|
|
6360
6742
|
const { colors } = theme;
|
|
@@ -6392,7 +6774,7 @@ function Button({
|
|
|
6392
6774
|
const theme = useTheme();
|
|
6393
6775
|
const isDisabled = disabled ?? void 0;
|
|
6394
6776
|
return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
6395
|
-
|
|
6777
|
+
import_react_native45.Pressable,
|
|
6396
6778
|
{
|
|
6397
6779
|
...props,
|
|
6398
6780
|
disabled: isDisabled,
|
|
@@ -6418,7 +6800,19 @@ function Button({
|
|
|
6418
6800
|
|
|
6419
6801
|
// src/components/chat/ChatMessageBubble.tsx
|
|
6420
6802
|
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
6421
|
-
function
|
|
6803
|
+
function areMessageMetaEqual(a, b) {
|
|
6804
|
+
if (a === b) return true;
|
|
6805
|
+
if (!a || !b) return a === b;
|
|
6806
|
+
return a.kind === b.kind && a.event === b.event && a.status === b.status && a.mergeRequestId === b.mergeRequestId && a.sourceAppId === b.sourceAppId && a.targetAppId === b.targetAppId && a.appId === b.appId && a.threadId === b.threadId;
|
|
6807
|
+
}
|
|
6808
|
+
function ChatMessageBubbleInner({
|
|
6809
|
+
message,
|
|
6810
|
+
renderContent,
|
|
6811
|
+
isLast,
|
|
6812
|
+
retrying,
|
|
6813
|
+
onRetryMessage,
|
|
6814
|
+
style
|
|
6815
|
+
}) {
|
|
6422
6816
|
var _a, _b;
|
|
6423
6817
|
const theme = useTheme();
|
|
6424
6818
|
const metaEvent = ((_a = message.meta) == null ? void 0 : _a.event) ?? null;
|
|
@@ -6433,9 +6827,12 @@ function ChatMessageBubble({ message, renderContent, isLast, retrying, onRetry,
|
|
|
6433
6827
|
const bubbleVariant = isHuman ? "surface" : "surfaceRaised";
|
|
6434
6828
|
const cornerStyle = isHuman ? { borderTopRightRadius: 0 } : { borderTopLeftRadius: 0 };
|
|
6435
6829
|
const bodyColor = metaStatus === "success" ? theme.colors.success : metaStatus === "error" ? theme.colors.danger : void 0;
|
|
6436
|
-
const showRetry = Boolean(
|
|
6830
|
+
const showRetry = Boolean(onRetryMessage) && isLast && metaStatus === "error" && message.author === "human";
|
|
6437
6831
|
const retryLabel = retrying ? "Retrying..." : "Retry";
|
|
6438
|
-
|
|
6832
|
+
const handleRetryPress = React36.useCallback(() => {
|
|
6833
|
+
onRetryMessage == null ? void 0 : onRetryMessage(message.id);
|
|
6834
|
+
}, [message.id, onRetryMessage]);
|
|
6835
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native46.View, { style: [align, style], children: [
|
|
6439
6836
|
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
6440
6837
|
Surface,
|
|
6441
6838
|
{
|
|
@@ -6451,23 +6848,23 @@ function ChatMessageBubble({ message, renderContent, isLast, retrying, onRetry,
|
|
|
6451
6848
|
},
|
|
6452
6849
|
cornerStyle
|
|
6453
6850
|
],
|
|
6454
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
|
|
6851
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native46.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
6455
6852
|
isMergeCompleted || isSyncCompleted ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react_native10.CheckCheck, { size: 16, color: theme.colors.success, style: { marginRight: theme.spacing.sm } }) : null,
|
|
6456
6853
|
isMergeApproved || isSyncStarted ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react_native10.GitMerge, { size: 16, color: theme.colors.text, style: { marginRight: theme.spacing.sm } }) : null,
|
|
6457
|
-
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
6854
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native46.View, { style: { flexShrink: 1, minWidth: 0 }, children: renderContent ? renderContent(message) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(MarkdownText, { markdown: message.content, variant: "chat", bodyColor }) })
|
|
6458
6855
|
] })
|
|
6459
6856
|
}
|
|
6460
6857
|
),
|
|
6461
|
-
showRetry ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
6858
|
+
showRetry ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native46.View, { style: { marginTop: theme.spacing.xs, alignSelf: align.alignSelf }, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
6462
6859
|
Button,
|
|
6463
6860
|
{
|
|
6464
6861
|
variant: "ghost",
|
|
6465
6862
|
size: "sm",
|
|
6466
|
-
onPress:
|
|
6863
|
+
onPress: handleRetryPress,
|
|
6467
6864
|
disabled: retrying,
|
|
6468
6865
|
style: { borderColor: theme.colors.danger },
|
|
6469
6866
|
accessibilityLabel: "Retry send",
|
|
6470
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
|
|
6867
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native46.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
6471
6868
|
!retrying ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react_native10.RotateCcw, { size: 14, color: theme.colors.danger }) : null,
|
|
6472
6869
|
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
6473
6870
|
Text,
|
|
@@ -6484,26 +6881,31 @@ function ChatMessageBubble({ message, renderContent, isLast, retrying, onRetry,
|
|
|
6484
6881
|
) }) : null
|
|
6485
6882
|
] });
|
|
6486
6883
|
}
|
|
6884
|
+
function areEqual(prev, next) {
|
|
6885
|
+
return prev.message.id === next.message.id && prev.message.author === next.message.author && prev.message.content === next.message.content && prev.message.kind === next.message.kind && String(prev.message.createdAt) === String(next.message.createdAt) && areMessageMetaEqual(prev.message.meta, next.message.meta) && prev.renderContent === next.renderContent && prev.isLast === next.isLast && prev.retrying === next.retrying && prev.onRetryMessage === next.onRetryMessage && prev.style === next.style;
|
|
6886
|
+
}
|
|
6887
|
+
var ChatMessageBubble = React36.memo(ChatMessageBubbleInner, areEqual);
|
|
6888
|
+
ChatMessageBubble.displayName = "ChatMessageBubble";
|
|
6487
6889
|
|
|
6488
6890
|
// src/components/chat/TypingIndicator.tsx
|
|
6489
|
-
var
|
|
6490
|
-
var
|
|
6891
|
+
var React37 = __toESM(require("react"));
|
|
6892
|
+
var import_react_native47 = require("react-native");
|
|
6491
6893
|
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
6492
6894
|
function TypingIndicator({ style }) {
|
|
6493
6895
|
const theme = useTheme();
|
|
6494
6896
|
const dotColor = theme.colors.textSubtle;
|
|
6495
|
-
const anims =
|
|
6496
|
-
() => [new
|
|
6897
|
+
const anims = React37.useMemo(
|
|
6898
|
+
() => [new import_react_native47.Animated.Value(0.3), new import_react_native47.Animated.Value(0.3), new import_react_native47.Animated.Value(0.3)],
|
|
6497
6899
|
[]
|
|
6498
6900
|
);
|
|
6499
|
-
|
|
6901
|
+
React37.useEffect(() => {
|
|
6500
6902
|
const loops = [];
|
|
6501
6903
|
anims.forEach((a, idx) => {
|
|
6502
|
-
const seq =
|
|
6503
|
-
|
|
6504
|
-
|
|
6904
|
+
const seq = import_react_native47.Animated.sequence([
|
|
6905
|
+
import_react_native47.Animated.timing(a, { toValue: 1, duration: 420, useNativeDriver: true, delay: idx * 140 }),
|
|
6906
|
+
import_react_native47.Animated.timing(a, { toValue: 0.3, duration: 420, useNativeDriver: true })
|
|
6505
6907
|
]);
|
|
6506
|
-
const loop =
|
|
6908
|
+
const loop = import_react_native47.Animated.loop(seq);
|
|
6507
6909
|
loops.push(loop);
|
|
6508
6910
|
loop.start();
|
|
6509
6911
|
});
|
|
@@ -6511,8 +6913,8 @@ function TypingIndicator({ style }) {
|
|
|
6511
6913
|
loops.forEach((l) => l.stop());
|
|
6512
6914
|
};
|
|
6513
6915
|
}, [anims]);
|
|
6514
|
-
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
6515
|
-
|
|
6916
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_react_native47.View, { style: [{ flexDirection: "row", alignItems: "center" }, style], children: anims.map((a, i) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
6917
|
+
import_react_native47.Animated.View,
|
|
6516
6918
|
{
|
|
6517
6919
|
style: {
|
|
6518
6920
|
width: 8,
|
|
@@ -6521,7 +6923,7 @@ function TypingIndicator({ style }) {
|
|
|
6521
6923
|
marginHorizontal: 3,
|
|
6522
6924
|
backgroundColor: dotColor,
|
|
6523
6925
|
opacity: a,
|
|
6524
|
-
transform: [{ translateY:
|
|
6926
|
+
transform: [{ translateY: import_react_native47.Animated.multiply(import_react_native47.Animated.subtract(a, 0.3), 2) }]
|
|
6525
6927
|
}
|
|
6526
6928
|
},
|
|
6527
6929
|
i
|
|
@@ -6530,7 +6932,7 @@ function TypingIndicator({ style }) {
|
|
|
6530
6932
|
|
|
6531
6933
|
// src/components/chat/ChatMessageList.tsx
|
|
6532
6934
|
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
6533
|
-
var ChatMessageList =
|
|
6935
|
+
var ChatMessageList = React38.forwardRef(
|
|
6534
6936
|
({
|
|
6535
6937
|
messages,
|
|
6536
6938
|
showTypingIndicator = false,
|
|
@@ -6543,21 +6945,22 @@ var ChatMessageList = React37.forwardRef(
|
|
|
6543
6945
|
nearBottomThreshold = 200
|
|
6544
6946
|
}, ref) => {
|
|
6545
6947
|
const theme = useTheme();
|
|
6546
|
-
const listRef =
|
|
6547
|
-
const nearBottomRef =
|
|
6548
|
-
const initialScrollDoneRef =
|
|
6549
|
-
const lastMessageIdRef =
|
|
6550
|
-
const data =
|
|
6948
|
+
const listRef = React38.useRef(null);
|
|
6949
|
+
const nearBottomRef = React38.useRef(true);
|
|
6950
|
+
const initialScrollDoneRef = React38.useRef(false);
|
|
6951
|
+
const lastMessageIdRef = React38.useRef(null);
|
|
6952
|
+
const data = React38.useMemo(() => {
|
|
6551
6953
|
return [...messages].reverse();
|
|
6552
6954
|
}, [messages]);
|
|
6553
6955
|
const lastMessageId = messages.length > 0 ? messages[messages.length - 1].id : null;
|
|
6554
|
-
const
|
|
6956
|
+
const keyExtractor = React38.useCallback((m) => m.id, []);
|
|
6957
|
+
const scrollToBottom = React38.useCallback((options) => {
|
|
6555
6958
|
var _a;
|
|
6556
6959
|
const animated = (options == null ? void 0 : options.animated) ?? true;
|
|
6557
6960
|
(_a = listRef.current) == null ? void 0 : _a.scrollToOffset({ offset: 0, animated });
|
|
6558
6961
|
}, []);
|
|
6559
|
-
|
|
6560
|
-
const handleScroll =
|
|
6962
|
+
React38.useImperativeHandle(ref, () => ({ scrollToBottom }), [scrollToBottom]);
|
|
6963
|
+
const handleScroll = React38.useCallback(
|
|
6561
6964
|
(e) => {
|
|
6562
6965
|
const { contentOffset, contentSize, layoutMeasurement } = e.nativeEvent;
|
|
6563
6966
|
const distanceFromBottom = Math.max(contentOffset.y - Math.max(bottomInset, 0), 0);
|
|
@@ -6569,7 +6972,7 @@ var ChatMessageList = React37.forwardRef(
|
|
|
6569
6972
|
},
|
|
6570
6973
|
[bottomInset, nearBottomThreshold, onNearBottomChange]
|
|
6571
6974
|
);
|
|
6572
|
-
|
|
6975
|
+
React38.useEffect(() => {
|
|
6573
6976
|
if (!initialScrollDoneRef.current) return;
|
|
6574
6977
|
const lastId = messages.length > 0 ? messages[messages.length - 1].id : null;
|
|
6575
6978
|
const prevLastId = lastMessageIdRef.current;
|
|
@@ -6579,54 +6982,68 @@ var ChatMessageList = React37.forwardRef(
|
|
|
6579
6982
|
const id = requestAnimationFrame(() => scrollToBottom({ animated: true }));
|
|
6580
6983
|
return () => cancelAnimationFrame(id);
|
|
6581
6984
|
}, [messages, scrollToBottom]);
|
|
6582
|
-
|
|
6985
|
+
React38.useEffect(() => {
|
|
6583
6986
|
if (showTypingIndicator && nearBottomRef.current) {
|
|
6584
6987
|
const id = requestAnimationFrame(() => scrollToBottom({ animated: true }));
|
|
6585
6988
|
return () => cancelAnimationFrame(id);
|
|
6586
6989
|
}
|
|
6587
6990
|
return void 0;
|
|
6588
6991
|
}, [showTypingIndicator, scrollToBottom]);
|
|
6992
|
+
const handleContentSizeChange = React38.useCallback(() => {
|
|
6993
|
+
if (initialScrollDoneRef.current) return;
|
|
6994
|
+
initialScrollDoneRef.current = true;
|
|
6995
|
+
lastMessageIdRef.current = messages.length > 0 ? messages[messages.length - 1].id : null;
|
|
6996
|
+
nearBottomRef.current = true;
|
|
6997
|
+
onNearBottomChange == null ? void 0 : onNearBottomChange(true);
|
|
6998
|
+
requestAnimationFrame(() => scrollToBottom({ animated: false }));
|
|
6999
|
+
}, [messages, onNearBottomChange, scrollToBottom]);
|
|
7000
|
+
const contentContainerStyle = React38.useMemo(
|
|
7001
|
+
() => [
|
|
7002
|
+
{
|
|
7003
|
+
paddingHorizontal: theme.spacing.lg,
|
|
7004
|
+
paddingVertical: theme.spacing.sm
|
|
7005
|
+
},
|
|
7006
|
+
contentStyle
|
|
7007
|
+
],
|
|
7008
|
+
[contentStyle, theme.spacing.lg, theme.spacing.sm]
|
|
7009
|
+
);
|
|
7010
|
+
const renderSeparator = React38.useCallback(() => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_react_native48.View, { style: { height: theme.spacing.sm } }), [theme.spacing.sm]);
|
|
7011
|
+
const listHeader = React38.useMemo(
|
|
7012
|
+
() => /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_react_native48.View, { children: [
|
|
7013
|
+
showTypingIndicator ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_react_native48.View, { style: { marginTop: theme.spacing.sm, alignSelf: "flex-start", paddingHorizontal: theme.spacing.lg }, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(TypingIndicator, {}) }) : null,
|
|
7014
|
+
bottomInset > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_react_native48.View, { style: { height: bottomInset } }) : null
|
|
7015
|
+
] }),
|
|
7016
|
+
[bottomInset, showTypingIndicator, theme.spacing.lg, theme.spacing.sm]
|
|
7017
|
+
);
|
|
7018
|
+
const renderItem = React38.useCallback(
|
|
7019
|
+
({ item }) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
7020
|
+
ChatMessageBubble,
|
|
7021
|
+
{
|
|
7022
|
+
message: item,
|
|
7023
|
+
renderContent: renderMessageContent,
|
|
7024
|
+
isLast: Boolean(lastMessageId && item.id === lastMessageId),
|
|
7025
|
+
retrying: (isRetryingMessage == null ? void 0 : isRetryingMessage(item.id)) ?? false,
|
|
7026
|
+
onRetryMessage
|
|
7027
|
+
}
|
|
7028
|
+
),
|
|
7029
|
+
[isRetryingMessage, lastMessageId, onRetryMessage, renderMessageContent]
|
|
7030
|
+
);
|
|
6589
7031
|
return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
6590
7032
|
import_bottom_sheet5.BottomSheetFlatList,
|
|
6591
7033
|
{
|
|
6592
7034
|
ref: listRef,
|
|
6593
7035
|
inverted: true,
|
|
6594
7036
|
data,
|
|
6595
|
-
keyExtractor
|
|
7037
|
+
keyExtractor,
|
|
6596
7038
|
keyboardShouldPersistTaps: "handled",
|
|
6597
7039
|
onScroll: handleScroll,
|
|
6598
7040
|
scrollEventThrottle: 16,
|
|
6599
7041
|
showsVerticalScrollIndicator: false,
|
|
6600
|
-
onContentSizeChange:
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
|
|
6605
|
-
onNearBottomChange == null ? void 0 : onNearBottomChange(true);
|
|
6606
|
-
requestAnimationFrame(() => scrollToBottom({ animated: false }));
|
|
6607
|
-
},
|
|
6608
|
-
contentContainerStyle: [
|
|
6609
|
-
{
|
|
6610
|
-
paddingHorizontal: theme.spacing.lg,
|
|
6611
|
-
paddingVertical: theme.spacing.sm
|
|
6612
|
-
},
|
|
6613
|
-
contentStyle
|
|
6614
|
-
],
|
|
6615
|
-
ItemSeparatorComponent: () => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_react_native47.View, { style: { height: theme.spacing.sm } }),
|
|
6616
|
-
renderItem: ({ item }) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
6617
|
-
ChatMessageBubble,
|
|
6618
|
-
{
|
|
6619
|
-
message: item,
|
|
6620
|
-
renderContent: renderMessageContent,
|
|
6621
|
-
isLast: Boolean(lastMessageId && item.id === lastMessageId),
|
|
6622
|
-
retrying: (isRetryingMessage == null ? void 0 : isRetryingMessage(item.id)) ?? false,
|
|
6623
|
-
onRetry: onRetryMessage ? () => onRetryMessage(item.id) : void 0
|
|
6624
|
-
}
|
|
6625
|
-
),
|
|
6626
|
-
ListHeaderComponent: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_react_native47.View, { children: [
|
|
6627
|
-
showTypingIndicator ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_react_native47.View, { style: { marginTop: theme.spacing.sm, alignSelf: "flex-start", paddingHorizontal: theme.spacing.lg }, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(TypingIndicator, {}) }) : null,
|
|
6628
|
-
bottomInset > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_react_native47.View, { style: { height: bottomInset } }) : null
|
|
6629
|
-
] })
|
|
7042
|
+
onContentSizeChange: handleContentSizeChange,
|
|
7043
|
+
contentContainerStyle,
|
|
7044
|
+
ItemSeparatorComponent: renderSeparator,
|
|
7045
|
+
renderItem,
|
|
7046
|
+
ListHeaderComponent: listHeader
|
|
6630
7047
|
}
|
|
6631
7048
|
);
|
|
6632
7049
|
}
|
|
@@ -6653,31 +7070,31 @@ function ChatPage({
|
|
|
6653
7070
|
}) {
|
|
6654
7071
|
const theme = useTheme();
|
|
6655
7072
|
const insets = (0, import_react_native_safe_area_context4.useSafeAreaInsets)();
|
|
6656
|
-
const [composerHeight, setComposerHeight] =
|
|
6657
|
-
const [composerTopHeight, setComposerTopHeight] =
|
|
6658
|
-
const footerBottomPadding =
|
|
7073
|
+
const [composerHeight, setComposerHeight] = React39.useState(0);
|
|
7074
|
+
const [composerTopHeight, setComposerTopHeight] = React39.useState(0);
|
|
7075
|
+
const footerBottomPadding = import_react_native49.Platform.OS === "ios" ? insets.bottom - 24 : insets.bottom + 10;
|
|
6659
7076
|
const totalComposerHeight = composerHeight + composerTopHeight;
|
|
6660
7077
|
const overlayBottom = totalComposerHeight + footerBottomPadding + theme.spacing.lg;
|
|
6661
7078
|
const bottomInset = totalComposerHeight + footerBottomPadding + theme.spacing.xl;
|
|
6662
|
-
const resolvedOverlay =
|
|
7079
|
+
const resolvedOverlay = React39.useMemo(() => {
|
|
6663
7080
|
var _a;
|
|
6664
7081
|
if (!overlay) return null;
|
|
6665
|
-
if (!
|
|
7082
|
+
if (!React39.isValidElement(overlay)) return overlay;
|
|
6666
7083
|
const prevStyle = (_a = overlay.props) == null ? void 0 : _a.style;
|
|
6667
|
-
return
|
|
7084
|
+
return React39.cloneElement(overlay, {
|
|
6668
7085
|
style: [prevStyle, { bottom: overlayBottom }]
|
|
6669
7086
|
});
|
|
6670
7087
|
}, [overlay, overlayBottom]);
|
|
6671
|
-
|
|
7088
|
+
React39.useEffect(() => {
|
|
6672
7089
|
if (composerTop) return;
|
|
6673
7090
|
setComposerTopHeight(0);
|
|
6674
7091
|
}, [composerTop]);
|
|
6675
|
-
return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
|
|
6676
|
-
header ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
6677
|
-
topBanner ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
6678
|
-
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
|
|
7092
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_react_native49.View, { style: [{ flex: 1 }, style], children: [
|
|
7093
|
+
header ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_react_native49.View, { children: header }) : null,
|
|
7094
|
+
topBanner ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_react_native49.View, { style: { paddingHorizontal: theme.spacing.lg, paddingTop: theme.spacing.sm }, children: topBanner }) : null,
|
|
7095
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_react_native49.View, { style: { flex: 1 }, children: [
|
|
6679
7096
|
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
|
|
6680
|
-
|
|
7097
|
+
import_react_native49.View,
|
|
6681
7098
|
{
|
|
6682
7099
|
style: { flex: 1 },
|
|
6683
7100
|
children: [
|
|
@@ -6699,7 +7116,7 @@ function ChatPage({
|
|
|
6699
7116
|
}
|
|
6700
7117
|
),
|
|
6701
7118
|
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
|
|
6702
|
-
|
|
7119
|
+
import_react_native49.View,
|
|
6703
7120
|
{
|
|
6704
7121
|
style: {
|
|
6705
7122
|
position: "absolute",
|
|
@@ -6712,7 +7129,7 @@ function ChatPage({
|
|
|
6712
7129
|
},
|
|
6713
7130
|
children: [
|
|
6714
7131
|
composerTop ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
6715
|
-
|
|
7132
|
+
import_react_native49.View,
|
|
6716
7133
|
{
|
|
6717
7134
|
style: { marginBottom: theme.spacing.sm },
|
|
6718
7135
|
onLayout: (e) => setComposerTopHeight(e.nativeEvent.layout.height),
|
|
@@ -6735,15 +7152,15 @@ function ChatPage({
|
|
|
6735
7152
|
}
|
|
6736
7153
|
|
|
6737
7154
|
// src/components/chat/ScrollToBottomButton.tsx
|
|
6738
|
-
var
|
|
6739
|
-
var
|
|
7155
|
+
var React40 = __toESM(require("react"));
|
|
7156
|
+
var import_react_native50 = require("react-native");
|
|
6740
7157
|
var import_react_native_reanimated2 = __toESM(require("react-native-reanimated"));
|
|
6741
7158
|
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
6742
7159
|
function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
6743
7160
|
const theme = useTheme();
|
|
6744
7161
|
const progress = (0, import_react_native_reanimated2.useSharedValue)(visible ? 1 : 0);
|
|
6745
|
-
const [pressed, setPressed] =
|
|
6746
|
-
|
|
7162
|
+
const [pressed, setPressed] = React40.useState(false);
|
|
7163
|
+
React40.useEffect(() => {
|
|
6747
7164
|
progress.value = (0, import_react_native_reanimated2.withTiming)(visible ? 1 : 0, { duration: 200, easing: import_react_native_reanimated2.Easing.out(import_react_native_reanimated2.Easing.ease) });
|
|
6748
7165
|
}, [progress, visible]);
|
|
6749
7166
|
const animStyle = (0, import_react_native_reanimated2.useAnimatedStyle)(() => ({
|
|
@@ -6767,7 +7184,7 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
|
6767
7184
|
animStyle
|
|
6768
7185
|
],
|
|
6769
7186
|
children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
6770
|
-
|
|
7187
|
+
import_react_native50.View,
|
|
6771
7188
|
{
|
|
6772
7189
|
style: {
|
|
6773
7190
|
width: 44,
|
|
@@ -6786,7 +7203,7 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
|
6786
7203
|
opacity: pressed ? 0.85 : 1
|
|
6787
7204
|
},
|
|
6788
7205
|
children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
6789
|
-
|
|
7206
|
+
import_react_native50.Pressable,
|
|
6790
7207
|
{
|
|
6791
7208
|
onPress,
|
|
6792
7209
|
onPressIn: () => setPressed(true),
|
|
@@ -6803,10 +7220,10 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
|
6803
7220
|
}
|
|
6804
7221
|
|
|
6805
7222
|
// src/components/chat/ChatHeader.tsx
|
|
6806
|
-
var
|
|
7223
|
+
var import_react_native51 = require("react-native");
|
|
6807
7224
|
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
6808
7225
|
function ChatHeader({ left, right, center, style }) {
|
|
6809
|
-
const flattenedStyle =
|
|
7226
|
+
const flattenedStyle = import_react_native51.StyleSheet.flatten([
|
|
6810
7227
|
{
|
|
6811
7228
|
paddingTop: 0
|
|
6812
7229
|
},
|
|
@@ -6824,7 +7241,7 @@ function ChatHeader({ left, right, center, style }) {
|
|
|
6824
7241
|
}
|
|
6825
7242
|
|
|
6826
7243
|
// src/components/chat/ForkNoticeBanner.tsx
|
|
6827
|
-
var
|
|
7244
|
+
var import_react_native52 = require("react-native");
|
|
6828
7245
|
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
6829
7246
|
function ForkNoticeBanner({ isOwner = true, title, description, style }) {
|
|
6830
7247
|
const theme = useTheme();
|
|
@@ -6845,7 +7262,7 @@ function ForkNoticeBanner({ isOwner = true, title, description, style }) {
|
|
|
6845
7262
|
},
|
|
6846
7263
|
style
|
|
6847
7264
|
],
|
|
6848
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
7265
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_react_native52.View, { style: { minWidth: 0 }, children: [
|
|
6849
7266
|
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
6850
7267
|
Text,
|
|
6851
7268
|
{
|
|
@@ -6878,16 +7295,16 @@ function ForkNoticeBanner({ isOwner = true, title, description, style }) {
|
|
|
6878
7295
|
}
|
|
6879
7296
|
|
|
6880
7297
|
// src/components/chat/ChatQueue.tsx
|
|
6881
|
-
var
|
|
6882
|
-
var
|
|
7298
|
+
var React41 = __toESM(require("react"));
|
|
7299
|
+
var import_react_native53 = require("react-native");
|
|
6883
7300
|
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
6884
7301
|
function ChatQueue({ items, onRemove }) {
|
|
6885
7302
|
const theme = useTheme();
|
|
6886
|
-
const [expanded, setExpanded] =
|
|
6887
|
-
const [canExpand, setCanExpand] =
|
|
6888
|
-
const [collapsedText, setCollapsedText] =
|
|
6889
|
-
const [removing, setRemoving] =
|
|
6890
|
-
const buildCollapsedText =
|
|
7303
|
+
const [expanded, setExpanded] = React41.useState({});
|
|
7304
|
+
const [canExpand, setCanExpand] = React41.useState({});
|
|
7305
|
+
const [collapsedText, setCollapsedText] = React41.useState({});
|
|
7306
|
+
const [removing, setRemoving] = React41.useState({});
|
|
7307
|
+
const buildCollapsedText = React41.useCallback((lines) => {
|
|
6891
7308
|
var _a, _b;
|
|
6892
7309
|
const line1 = ((_a = lines[0]) == null ? void 0 : _a.text) ?? "";
|
|
6893
7310
|
const line2 = ((_b = lines[1]) == null ? void 0 : _b.text) ?? "";
|
|
@@ -6903,7 +7320,7 @@ function ChatQueue({ items, onRemove }) {
|
|
|
6903
7320
|
return `${line1}
|
|
6904
7321
|
${trimmedLine2}\u2026 `;
|
|
6905
7322
|
}, []);
|
|
6906
|
-
|
|
7323
|
+
React41.useEffect(() => {
|
|
6907
7324
|
if (items.length === 0) return;
|
|
6908
7325
|
const ids = new Set(items.map((item) => item.id));
|
|
6909
7326
|
setExpanded((prev) => Object.fromEntries(Object.entries(prev).filter(([id]) => ids.has(id))));
|
|
@@ -6913,7 +7330,7 @@ ${trimmedLine2}\u2026 `;
|
|
|
6913
7330
|
}, [items]);
|
|
6914
7331
|
if (items.length === 0) return null;
|
|
6915
7332
|
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
|
|
6916
|
-
|
|
7333
|
+
import_react_native53.View,
|
|
6917
7334
|
{
|
|
6918
7335
|
style: {
|
|
6919
7336
|
borderWidth: 1,
|
|
@@ -6925,7 +7342,7 @@ ${trimmedLine2}\u2026 `;
|
|
|
6925
7342
|
},
|
|
6926
7343
|
children: [
|
|
6927
7344
|
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Text, { variant: "caption", style: { marginBottom: theme.spacing.sm }, children: "Queue" }),
|
|
6928
|
-
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
7345
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native53.View, { style: { gap: theme.spacing.sm }, children: items.map((item) => {
|
|
6929
7346
|
const isExpanded = Boolean(expanded[item.id]);
|
|
6930
7347
|
const showToggle = Boolean(canExpand[item.id]);
|
|
6931
7348
|
const prompt = item.prompt ?? "";
|
|
@@ -6933,7 +7350,7 @@ ${trimmedLine2}\u2026 `;
|
|
|
6933
7350
|
const displayPrompt = !isExpanded && showToggle && collapsedText[item.id] ? collapsedText[item.id] : prompt;
|
|
6934
7351
|
const isRemoving = Boolean(removing[item.id]);
|
|
6935
7352
|
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
|
|
6936
|
-
|
|
7353
|
+
import_react_native53.View,
|
|
6937
7354
|
{
|
|
6938
7355
|
style: {
|
|
6939
7356
|
flexDirection: "row",
|
|
@@ -6945,7 +7362,7 @@ ${trimmedLine2}\u2026 `;
|
|
|
6945
7362
|
backgroundColor: withAlpha(theme.colors.surface, theme.scheme === "dark" ? 0.8 : 0.9)
|
|
6946
7363
|
},
|
|
6947
7364
|
children: [
|
|
6948
|
-
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
|
|
7365
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react_native53.View, { style: { flex: 1 }, children: [
|
|
6949
7366
|
!canExpand[item.id] ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
6950
7367
|
Text,
|
|
6951
7368
|
{
|
|
@@ -6985,7 +7402,7 @@ ${trimmedLine2}\u2026 `;
|
|
|
6985
7402
|
}
|
|
6986
7403
|
),
|
|
6987
7404
|
showToggle && isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
6988
|
-
|
|
7405
|
+
import_react_native53.Pressable,
|
|
6989
7406
|
{
|
|
6990
7407
|
onPress: () => setExpanded((prev) => ({ ...prev, [item.id]: false })),
|
|
6991
7408
|
hitSlop: 6,
|
|
@@ -6995,7 +7412,7 @@ ${trimmedLine2}\u2026 `;
|
|
|
6995
7412
|
) : null
|
|
6996
7413
|
] }),
|
|
6997
7414
|
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
6998
|
-
|
|
7415
|
+
import_react_native53.Pressable,
|
|
6999
7416
|
{
|
|
7000
7417
|
onPress: () => {
|
|
7001
7418
|
if (!onRemove || isRemoving) return;
|
|
@@ -7010,7 +7427,7 @@ ${trimmedLine2}\u2026 `;
|
|
|
7010
7427
|
},
|
|
7011
7428
|
hitSlop: 8,
|
|
7012
7429
|
style: { alignSelf: "center" },
|
|
7013
|
-
children: isRemoving ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
7430
|
+
children: isRemoving ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native53.ActivityIndicator, { size: "small", color: theme.colors.text }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(IconClose, { size: 14, colorToken: "text" })
|
|
7014
7431
|
}
|
|
7015
7432
|
)
|
|
7016
7433
|
]
|
|
@@ -7023,8 +7440,137 @@ ${trimmedLine2}\u2026 `;
|
|
|
7023
7440
|
);
|
|
7024
7441
|
}
|
|
7025
7442
|
|
|
7026
|
-
// src/
|
|
7443
|
+
// src/components/chat/AgentProgressCard.tsx
|
|
7444
|
+
var import_react_native54 = require("react-native");
|
|
7027
7445
|
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
7446
|
+
function titleForPhase(phase) {
|
|
7447
|
+
if (phase === "planning") return "Planning";
|
|
7448
|
+
if (phase === "reasoning") return "Reasoning";
|
|
7449
|
+
if (phase === "analyzing") return "Analyzing";
|
|
7450
|
+
if (phase === "editing") return "Editing";
|
|
7451
|
+
if (phase === "executing") return "Executing";
|
|
7452
|
+
if (phase === "validating") return "Validating";
|
|
7453
|
+
if (phase === "finalizing") return "Finalizing";
|
|
7454
|
+
if (phase === "working") return "Working";
|
|
7455
|
+
return "Working";
|
|
7456
|
+
}
|
|
7457
|
+
function titleForStatus(status) {
|
|
7458
|
+
if (status === "succeeded") return "Completed";
|
|
7459
|
+
if (status === "failed") return "Failed";
|
|
7460
|
+
if (status === "cancelled") return "Cancelled";
|
|
7461
|
+
return "In Progress";
|
|
7462
|
+
}
|
|
7463
|
+
function AgentProgressCard({ progress }) {
|
|
7464
|
+
const theme = useTheme();
|
|
7465
|
+
const statusLabel = titleForStatus(progress.status);
|
|
7466
|
+
const phaseLabel = titleForPhase(progress.phase);
|
|
7467
|
+
const subtitle = progress.latestMessage || `Agent is ${phaseLabel.toLowerCase()}...`;
|
|
7468
|
+
const todo = progress.todoSummary;
|
|
7469
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
|
|
7470
|
+
import_react_native54.View,
|
|
7471
|
+
{
|
|
7472
|
+
style: {
|
|
7473
|
+
borderWidth: 1,
|
|
7474
|
+
borderColor: theme.colors.border,
|
|
7475
|
+
borderRadius: theme.radii.lg,
|
|
7476
|
+
marginHorizontal: theme.spacing.md,
|
|
7477
|
+
padding: theme.spacing.md,
|
|
7478
|
+
backgroundColor: withAlpha(theme.colors.surface, theme.scheme === "dark" ? 0.84 : 0.94)
|
|
7479
|
+
},
|
|
7480
|
+
children: [
|
|
7481
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_react_native54.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", marginBottom: 4 }, children: [
|
|
7482
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Text, { variant: "caption", children: statusLabel }),
|
|
7483
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Text, { variant: "captionMuted", children: phaseLabel })
|
|
7484
|
+
] }),
|
|
7485
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Text, { variant: "bodyMuted", children: subtitle }),
|
|
7486
|
+
progress.changedFilesCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(Text, { variant: "captionMuted", style: { marginTop: 8 }, children: [
|
|
7487
|
+
"Updated files: ",
|
|
7488
|
+
progress.changedFilesCount
|
|
7489
|
+
] }) : null,
|
|
7490
|
+
progress.recentFiles.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_react_native54.View, { style: { marginTop: 6 }, children: progress.recentFiles.map((path) => /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(Text, { variant: "captionMuted", numberOfLines: 1, children: [
|
|
7491
|
+
"\u2022 ",
|
|
7492
|
+
path
|
|
7493
|
+
] }, path)) }) : null,
|
|
7494
|
+
todo ? /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(Text, { variant: "captionMuted", style: { marginTop: 8 }, children: [
|
|
7495
|
+
"Todos: ",
|
|
7496
|
+
todo.completed,
|
|
7497
|
+
"/",
|
|
7498
|
+
todo.total,
|
|
7499
|
+
" complete",
|
|
7500
|
+
todo.currentTask ? ` \u2022 ${todo.currentTask}` : ""
|
|
7501
|
+
] }) : null
|
|
7502
|
+
]
|
|
7503
|
+
}
|
|
7504
|
+
);
|
|
7505
|
+
}
|
|
7506
|
+
|
|
7507
|
+
// src/components/chat/BundleProgressCard.tsx
|
|
7508
|
+
var import_react_native55 = require("react-native");
|
|
7509
|
+
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
7510
|
+
function titleForStatus2(status) {
|
|
7511
|
+
if (status === "succeeded") return "Completed";
|
|
7512
|
+
if (status === "failed") return "Failed";
|
|
7513
|
+
return "In Progress";
|
|
7514
|
+
}
|
|
7515
|
+
function BundleProgressCard({ progress }) {
|
|
7516
|
+
const theme = useTheme();
|
|
7517
|
+
const statusLabel = titleForStatus2(progress.status);
|
|
7518
|
+
const percent = Math.round(Math.max(0, Math.min(1, progress.progressValue)) * 100);
|
|
7519
|
+
const fillColor = progress.status === "failed" ? theme.colors.danger : progress.status === "succeeded" ? theme.colors.success : theme.colors.warning;
|
|
7520
|
+
const detail = progress.errorMessage || progress.phaseLabel;
|
|
7521
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
|
|
7522
|
+
import_react_native55.View,
|
|
7523
|
+
{
|
|
7524
|
+
accessible: true,
|
|
7525
|
+
accessibilityRole: "progressbar",
|
|
7526
|
+
accessibilityLabel: `Bundle progress ${statusLabel}`,
|
|
7527
|
+
accessibilityValue: { min: 0, max: 100, now: percent, text: `${percent}%` },
|
|
7528
|
+
style: {
|
|
7529
|
+
borderWidth: 1,
|
|
7530
|
+
borderColor: theme.colors.border,
|
|
7531
|
+
borderRadius: theme.radii.lg,
|
|
7532
|
+
marginHorizontal: theme.spacing.md,
|
|
7533
|
+
padding: theme.spacing.md,
|
|
7534
|
+
backgroundColor: withAlpha(theme.colors.surface, theme.scheme === "dark" ? 0.84 : 0.94)
|
|
7535
|
+
},
|
|
7536
|
+
children: [
|
|
7537
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_react_native55.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", marginBottom: 8 }, children: [
|
|
7538
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Text, { variant: "caption", children: statusLabel }),
|
|
7539
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(Text, { variant: "captionMuted", children: [
|
|
7540
|
+
percent,
|
|
7541
|
+
"%"
|
|
7542
|
+
] })
|
|
7543
|
+
] }),
|
|
7544
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
7545
|
+
import_react_native55.View,
|
|
7546
|
+
{
|
|
7547
|
+
style: {
|
|
7548
|
+
width: "100%",
|
|
7549
|
+
height: 8,
|
|
7550
|
+
borderRadius: 999,
|
|
7551
|
+
backgroundColor: withAlpha(theme.colors.border, theme.scheme === "dark" ? 0.5 : 0.6),
|
|
7552
|
+
overflow: "hidden"
|
|
7553
|
+
},
|
|
7554
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
7555
|
+
import_react_native55.View,
|
|
7556
|
+
{
|
|
7557
|
+
style: {
|
|
7558
|
+
width: `${percent}%`,
|
|
7559
|
+
height: "100%",
|
|
7560
|
+
backgroundColor: fillColor
|
|
7561
|
+
}
|
|
7562
|
+
}
|
|
7563
|
+
)
|
|
7564
|
+
}
|
|
7565
|
+
),
|
|
7566
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Text, { variant: "captionMuted", numberOfLines: 1, style: { marginTop: 8, minHeight: 16 }, children: detail })
|
|
7567
|
+
]
|
|
7568
|
+
}
|
|
7569
|
+
);
|
|
7570
|
+
}
|
|
7571
|
+
|
|
7572
|
+
// src/studio/ui/ChatPanel.tsx
|
|
7573
|
+
var import_jsx_runtime57 = require("react/jsx-runtime");
|
|
7028
7574
|
function ChatPanel({
|
|
7029
7575
|
title = "Chat",
|
|
7030
7576
|
messages,
|
|
@@ -7045,11 +7591,13 @@ function ChatPanel({
|
|
|
7045
7591
|
onRetryMessage,
|
|
7046
7592
|
isRetryingMessage,
|
|
7047
7593
|
queueItems = [],
|
|
7048
|
-
onRemoveQueueItem
|
|
7594
|
+
onRemoveQueueItem,
|
|
7595
|
+
progress = null
|
|
7049
7596
|
}) {
|
|
7050
|
-
const
|
|
7051
|
-
const
|
|
7052
|
-
const
|
|
7597
|
+
const theme = useTheme();
|
|
7598
|
+
const listRef = React42.useRef(null);
|
|
7599
|
+
const [nearBottom, setNearBottom] = React42.useState(true);
|
|
7600
|
+
const handleSend = React42.useCallback(
|
|
7053
7601
|
async (text, composerAttachments) => {
|
|
7054
7602
|
const all = composerAttachments ?? attachments;
|
|
7055
7603
|
await onSend(text, all.length > 0 ? all : void 0);
|
|
@@ -7063,25 +7611,25 @@ function ChatPanel({
|
|
|
7063
7611
|
},
|
|
7064
7612
|
[attachments, nearBottom, onClearAttachments, onSend]
|
|
7065
7613
|
);
|
|
7066
|
-
const handleScrollToBottom =
|
|
7614
|
+
const handleScrollToBottom = React42.useCallback(() => {
|
|
7067
7615
|
var _a;
|
|
7068
7616
|
(_a = listRef.current) == null ? void 0 : _a.scrollToBottom({ animated: true });
|
|
7069
7617
|
}, []);
|
|
7070
|
-
const header = /* @__PURE__ */ (0,
|
|
7618
|
+
const header = /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7071
7619
|
ChatHeader,
|
|
7072
7620
|
{
|
|
7073
|
-
left: /* @__PURE__ */ (0,
|
|
7074
|
-
/* @__PURE__ */ (0,
|
|
7075
|
-
onNavigateHome ? /* @__PURE__ */ (0,
|
|
7621
|
+
left: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_react_native56.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
7622
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(StudioSheetHeaderIconButton, { onPress: onBack, accessibilityLabel: "Back", style: { marginRight: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(IconBack, { size: 20, colorToken: "floatingContent" }) }),
|
|
7623
|
+
onNavigateHome ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(StudioSheetHeaderIconButton, { onPress: onNavigateHome, accessibilityLabel: "Home", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(IconHome, { size: 20, colorToken: "floatingContent" }) }) : null
|
|
7076
7624
|
] }),
|
|
7077
|
-
right: /* @__PURE__ */ (0,
|
|
7078
|
-
onStartDraw ? /* @__PURE__ */ (0,
|
|
7079
|
-
/* @__PURE__ */ (0,
|
|
7625
|
+
right: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_react_native56.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
7626
|
+
onStartDraw ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(StudioSheetHeaderIconButton, { onPress: onStartDraw, accessibilityLabel: "Draw", intent: "danger", style: { marginRight: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(IconDraw, { size: 20, colorToken: "onDanger" }) }) : null,
|
|
7627
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(StudioSheetHeaderIconButton, { onPress: onClose, accessibilityLabel: "Close", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(IconClose, { size: 20, colorToken: "floatingContent" }) })
|
|
7080
7628
|
] }),
|
|
7081
7629
|
center: null
|
|
7082
7630
|
}
|
|
7083
7631
|
);
|
|
7084
|
-
const topBanner = shouldForkOnEdit ? /* @__PURE__ */ (0,
|
|
7632
|
+
const topBanner = shouldForkOnEdit ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7085
7633
|
ForkNoticeBanner,
|
|
7086
7634
|
{
|
|
7087
7635
|
isOwner: !shouldForkOnEdit,
|
|
@@ -7090,18 +7638,22 @@ function ChatPanel({
|
|
|
7090
7638
|
) : null;
|
|
7091
7639
|
const showMessagesLoading = Boolean(loading) && messages.length === 0 || forking;
|
|
7092
7640
|
if (showMessagesLoading) {
|
|
7093
|
-
return /* @__PURE__ */ (0,
|
|
7094
|
-
/* @__PURE__ */ (0,
|
|
7095
|
-
topBanner ? /* @__PURE__ */ (0,
|
|
7096
|
-
/* @__PURE__ */ (0,
|
|
7097
|
-
/* @__PURE__ */ (0,
|
|
7098
|
-
/* @__PURE__ */ (0,
|
|
7099
|
-
/* @__PURE__ */ (0,
|
|
7641
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_react_native56.View, { style: { flex: 1 }, children: [
|
|
7642
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_react_native56.View, { children: header }),
|
|
7643
|
+
topBanner ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_react_native56.View, { style: { paddingHorizontal: 16, paddingTop: 8 }, children: topBanner }) : null,
|
|
7644
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_react_native56.View, { style: { flex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 24, paddingVertical: 12 }, children: [
|
|
7645
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_react_native56.ActivityIndicator, {}),
|
|
7646
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_react_native56.View, { style: { height: 12 } }),
|
|
7647
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Text, { variant: "bodyMuted", children: forking ? "Creating your copy\u2026" : "Loading messages\u2026" })
|
|
7100
7648
|
] })
|
|
7101
7649
|
] });
|
|
7102
7650
|
}
|
|
7103
|
-
const
|
|
7104
|
-
|
|
7651
|
+
const bundleProgress = (progress == null ? void 0 : progress.bundle) ?? null;
|
|
7652
|
+
const queueTop = progress || queueItems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_react_native56.View, { style: { gap: theme.spacing.sm }, children: [
|
|
7653
|
+
progress ? bundleProgress ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(BundleProgressCard, { progress: bundleProgress }) : /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(AgentProgressCard, { progress }) : null,
|
|
7654
|
+
queueItems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ChatQueue, { items: queueItems, onRemove: onRemoveQueueItem }) : null
|
|
7655
|
+
] }) : null;
|
|
7656
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7105
7657
|
ChatPage,
|
|
7106
7658
|
{
|
|
7107
7659
|
header,
|
|
@@ -7114,13 +7666,13 @@ function ChatPanel({
|
|
|
7114
7666
|
composerHorizontalPadding: 0,
|
|
7115
7667
|
listRef,
|
|
7116
7668
|
onNearBottomChange: setNearBottom,
|
|
7117
|
-
overlay: /* @__PURE__ */ (0,
|
|
7669
|
+
overlay: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7118
7670
|
ScrollToBottomButton,
|
|
7119
7671
|
{
|
|
7120
7672
|
visible: !nearBottom,
|
|
7121
7673
|
onPress: handleScrollToBottom,
|
|
7122
7674
|
style: { bottom: 80 },
|
|
7123
|
-
children: /* @__PURE__ */ (0,
|
|
7675
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(IconArrowDown, { size: 20, colorToken: "floatingContent" })
|
|
7124
7676
|
}
|
|
7125
7677
|
),
|
|
7126
7678
|
composer: {
|
|
@@ -7140,12 +7692,12 @@ function ChatPanel({
|
|
|
7140
7692
|
}
|
|
7141
7693
|
|
|
7142
7694
|
// src/components/dialogs/ConfirmMergeRequestDialog.tsx
|
|
7143
|
-
var
|
|
7144
|
-
var
|
|
7695
|
+
var React43 = __toESM(require("react"));
|
|
7696
|
+
var import_react_native58 = require("react-native");
|
|
7145
7697
|
|
|
7146
7698
|
// src/components/primitives/Modal.tsx
|
|
7147
|
-
var
|
|
7148
|
-
var
|
|
7699
|
+
var import_react_native57 = require("react-native");
|
|
7700
|
+
var import_jsx_runtime58 = require("react/jsx-runtime");
|
|
7149
7701
|
function Modal2({
|
|
7150
7702
|
visible,
|
|
7151
7703
|
onRequestClose,
|
|
@@ -7154,30 +7706,30 @@ function Modal2({
|
|
|
7154
7706
|
contentStyle
|
|
7155
7707
|
}) {
|
|
7156
7708
|
const theme = useTheme();
|
|
7157
|
-
return /* @__PURE__ */ (0,
|
|
7158
|
-
|
|
7709
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
7710
|
+
import_react_native57.Modal,
|
|
7159
7711
|
{
|
|
7160
7712
|
visible,
|
|
7161
7713
|
transparent: true,
|
|
7162
7714
|
animationType: "fade",
|
|
7163
7715
|
onRequestClose,
|
|
7164
|
-
children: /* @__PURE__ */ (0,
|
|
7165
|
-
/* @__PURE__ */ (0,
|
|
7166
|
-
|
|
7716
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_react_native57.View, { style: { flex: 1, backgroundColor: theme.colors.backdrop, justifyContent: "center", padding: theme.spacing.lg }, children: [
|
|
7717
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
7718
|
+
import_react_native57.Pressable,
|
|
7167
7719
|
{
|
|
7168
7720
|
accessibilityRole: "button",
|
|
7169
7721
|
onPress: dismissOnBackdropPress ? onRequestClose : void 0,
|
|
7170
7722
|
style: { position: "absolute", inset: 0 }
|
|
7171
7723
|
}
|
|
7172
7724
|
),
|
|
7173
|
-
/* @__PURE__ */ (0,
|
|
7725
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Card, { variant: "surfaceRaised", padded: true, style: [{ borderRadius: theme.radii.xl }, contentStyle], children })
|
|
7174
7726
|
] })
|
|
7175
7727
|
}
|
|
7176
7728
|
);
|
|
7177
7729
|
}
|
|
7178
7730
|
|
|
7179
7731
|
// src/components/dialogs/ConfirmMergeRequestDialog.tsx
|
|
7180
|
-
var
|
|
7732
|
+
var import_jsx_runtime59 = require("react/jsx-runtime");
|
|
7181
7733
|
function ConfirmMergeRequestDialog({
|
|
7182
7734
|
visible,
|
|
7183
7735
|
onOpenChange,
|
|
@@ -7188,14 +7740,14 @@ function ConfirmMergeRequestDialog({
|
|
|
7188
7740
|
onTestFirst
|
|
7189
7741
|
}) {
|
|
7190
7742
|
const theme = useTheme();
|
|
7191
|
-
const close =
|
|
7743
|
+
const close = React43.useCallback(() => onOpenChange(false), [onOpenChange]);
|
|
7192
7744
|
const canConfirm = Boolean(mergeRequest) && !approveDisabled;
|
|
7193
|
-
const handleConfirm =
|
|
7745
|
+
const handleConfirm = React43.useCallback(() => {
|
|
7194
7746
|
if (!mergeRequest) return;
|
|
7195
7747
|
onOpenChange(false);
|
|
7196
7748
|
void onConfirm();
|
|
7197
7749
|
}, [mergeRequest, onConfirm, onOpenChange]);
|
|
7198
|
-
const handleTestFirst =
|
|
7750
|
+
const handleTestFirst = React43.useCallback(() => {
|
|
7199
7751
|
if (!mergeRequest) return;
|
|
7200
7752
|
onOpenChange(false);
|
|
7201
7753
|
void onTestFirst(mergeRequest);
|
|
@@ -7207,7 +7759,7 @@ function ConfirmMergeRequestDialog({
|
|
|
7207
7759
|
justifyContent: "center",
|
|
7208
7760
|
alignSelf: "stretch"
|
|
7209
7761
|
};
|
|
7210
|
-
return /* @__PURE__ */ (0,
|
|
7762
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
|
|
7211
7763
|
Modal2,
|
|
7212
7764
|
{
|
|
7213
7765
|
visible,
|
|
@@ -7218,7 +7770,7 @@ function ConfirmMergeRequestDialog({
|
|
|
7218
7770
|
backgroundColor: theme.colors.background
|
|
7219
7771
|
},
|
|
7220
7772
|
children: [
|
|
7221
|
-
/* @__PURE__ */ (0,
|
|
7773
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_react_native58.View, { children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
7222
7774
|
Text,
|
|
7223
7775
|
{
|
|
7224
7776
|
style: {
|
|
@@ -7230,9 +7782,9 @@ function ConfirmMergeRequestDialog({
|
|
|
7230
7782
|
children: "Are you sure you want to approve this merge request?"
|
|
7231
7783
|
}
|
|
7232
7784
|
) }),
|
|
7233
|
-
/* @__PURE__ */ (0,
|
|
7234
|
-
/* @__PURE__ */ (0,
|
|
7235
|
-
|
|
7785
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_react_native58.View, { style: { marginTop: 16 }, children: [
|
|
7786
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
7787
|
+
import_react_native58.View,
|
|
7236
7788
|
{
|
|
7237
7789
|
style: [
|
|
7238
7790
|
fullWidthButtonBase,
|
|
@@ -7241,22 +7793,22 @@ function ConfirmMergeRequestDialog({
|
|
|
7241
7793
|
opacity: canConfirm ? 1 : 0.5
|
|
7242
7794
|
}
|
|
7243
7795
|
],
|
|
7244
|
-
children: /* @__PURE__ */ (0,
|
|
7245
|
-
|
|
7796
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
7797
|
+
import_react_native58.Pressable,
|
|
7246
7798
|
{
|
|
7247
7799
|
accessibilityRole: "button",
|
|
7248
7800
|
accessibilityLabel: "Approve Merge",
|
|
7249
7801
|
disabled: !canConfirm,
|
|
7250
7802
|
onPress: handleConfirm,
|
|
7251
7803
|
style: [fullWidthButtonBase, { flex: 1 }],
|
|
7252
|
-
children: /* @__PURE__ */ (0,
|
|
7804
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Text, { style: { textAlign: "center", color: theme.colors.onPrimary }, children: "Approve Merge" })
|
|
7253
7805
|
}
|
|
7254
7806
|
)
|
|
7255
7807
|
}
|
|
7256
7808
|
),
|
|
7257
|
-
/* @__PURE__ */ (0,
|
|
7258
|
-
/* @__PURE__ */ (0,
|
|
7259
|
-
|
|
7809
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_react_native58.View, { style: { height: 8 } }),
|
|
7810
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
7811
|
+
import_react_native58.View,
|
|
7260
7812
|
{
|
|
7261
7813
|
style: [
|
|
7262
7814
|
fullWidthButtonBase,
|
|
@@ -7267,22 +7819,22 @@ function ConfirmMergeRequestDialog({
|
|
|
7267
7819
|
opacity: isBuilding || !mergeRequest ? 0.5 : 1
|
|
7268
7820
|
}
|
|
7269
7821
|
],
|
|
7270
|
-
children: /* @__PURE__ */ (0,
|
|
7271
|
-
|
|
7822
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
7823
|
+
import_react_native58.Pressable,
|
|
7272
7824
|
{
|
|
7273
7825
|
accessibilityRole: "button",
|
|
7274
7826
|
accessibilityLabel: isBuilding ? "Preparing\u2026" : "Test edits first",
|
|
7275
7827
|
disabled: isBuilding || !mergeRequest,
|
|
7276
7828
|
onPress: handleTestFirst,
|
|
7277
7829
|
style: [fullWidthButtonBase, { flex: 1 }],
|
|
7278
|
-
children: /* @__PURE__ */ (0,
|
|
7830
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Text, { style: { textAlign: "center", color: theme.colors.text }, children: isBuilding ? "Preparing\u2026" : "Test edits first" })
|
|
7279
7831
|
}
|
|
7280
7832
|
)
|
|
7281
7833
|
}
|
|
7282
7834
|
),
|
|
7283
|
-
/* @__PURE__ */ (0,
|
|
7284
|
-
/* @__PURE__ */ (0,
|
|
7285
|
-
|
|
7835
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_react_native58.View, { style: { height: 8 } }),
|
|
7836
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
7837
|
+
import_react_native58.View,
|
|
7286
7838
|
{
|
|
7287
7839
|
style: [
|
|
7288
7840
|
fullWidthButtonBase,
|
|
@@ -7292,14 +7844,14 @@ function ConfirmMergeRequestDialog({
|
|
|
7292
7844
|
borderColor: theme.colors.border
|
|
7293
7845
|
}
|
|
7294
7846
|
],
|
|
7295
|
-
children: /* @__PURE__ */ (0,
|
|
7296
|
-
|
|
7847
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
7848
|
+
import_react_native58.Pressable,
|
|
7297
7849
|
{
|
|
7298
7850
|
accessibilityRole: "button",
|
|
7299
7851
|
accessibilityLabel: "Cancel",
|
|
7300
7852
|
onPress: close,
|
|
7301
7853
|
style: [fullWidthButtonBase, { flex: 1 }],
|
|
7302
|
-
children: /* @__PURE__ */ (0,
|
|
7854
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Text, { style: { textAlign: "center", color: theme.colors.text }, children: "Cancel" })
|
|
7303
7855
|
}
|
|
7304
7856
|
)
|
|
7305
7857
|
}
|
|
@@ -7311,7 +7863,7 @@ function ConfirmMergeRequestDialog({
|
|
|
7311
7863
|
}
|
|
7312
7864
|
|
|
7313
7865
|
// src/studio/ui/ConfirmMergeFlow.tsx
|
|
7314
|
-
var
|
|
7866
|
+
var import_jsx_runtime60 = require("react/jsx-runtime");
|
|
7315
7867
|
function ConfirmMergeFlow({
|
|
7316
7868
|
visible,
|
|
7317
7869
|
onOpenChange,
|
|
@@ -7322,7 +7874,7 @@ function ConfirmMergeFlow({
|
|
|
7322
7874
|
onConfirm,
|
|
7323
7875
|
onTestFirst
|
|
7324
7876
|
}) {
|
|
7325
|
-
return /* @__PURE__ */ (0,
|
|
7877
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7326
7878
|
ConfirmMergeRequestDialog,
|
|
7327
7879
|
{
|
|
7328
7880
|
visible,
|
|
@@ -7344,7 +7896,7 @@ function ConfirmMergeFlow({
|
|
|
7344
7896
|
}
|
|
7345
7897
|
|
|
7346
7898
|
// src/studio/hooks/useOptimisticChatMessages.ts
|
|
7347
|
-
var
|
|
7899
|
+
var React44 = __toESM(require("react"));
|
|
7348
7900
|
function makeOptimisticId() {
|
|
7349
7901
|
return `optimistic:${Date.now().toString(36)}:${Math.random().toString(36).slice(2, 10)}`;
|
|
7350
7902
|
}
|
|
@@ -7383,11 +7935,11 @@ function useOptimisticChatMessages({
|
|
|
7383
7935
|
chatMessages,
|
|
7384
7936
|
onSendChat
|
|
7385
7937
|
}) {
|
|
7386
|
-
const [optimisticChat, setOptimisticChat] =
|
|
7387
|
-
|
|
7938
|
+
const [optimisticChat, setOptimisticChat] = React44.useState([]);
|
|
7939
|
+
React44.useEffect(() => {
|
|
7388
7940
|
setOptimisticChat([]);
|
|
7389
7941
|
}, [threadId]);
|
|
7390
|
-
const messages =
|
|
7942
|
+
const messages = React44.useMemo(() => {
|
|
7391
7943
|
if (!optimisticChat || optimisticChat.length === 0) return chatMessages;
|
|
7392
7944
|
const unresolved = optimisticChat.filter((o) => !isOptimisticResolvedByServer(chatMessages, o));
|
|
7393
7945
|
if (unresolved.length === 0) return chatMessages;
|
|
@@ -7403,7 +7955,7 @@ function useOptimisticChatMessages({
|
|
|
7403
7955
|
merged.sort((a, b) => String(a.createdAt).localeCompare(String(b.createdAt)));
|
|
7404
7956
|
return merged;
|
|
7405
7957
|
}, [chatMessages, optimisticChat]);
|
|
7406
|
-
|
|
7958
|
+
React44.useEffect(() => {
|
|
7407
7959
|
if (optimisticChat.length === 0) return;
|
|
7408
7960
|
setOptimisticChat((prev) => {
|
|
7409
7961
|
if (prev.length === 0) return prev;
|
|
@@ -7411,7 +7963,7 @@ function useOptimisticChatMessages({
|
|
|
7411
7963
|
return next.length === prev.length ? prev : next;
|
|
7412
7964
|
});
|
|
7413
7965
|
}, [chatMessages, optimisticChat.length]);
|
|
7414
|
-
const onSend =
|
|
7966
|
+
const onSend = React44.useCallback(
|
|
7415
7967
|
async (text, attachments) => {
|
|
7416
7968
|
if (shouldForkOnEdit || disableOptimistic) {
|
|
7417
7969
|
await onSendChat(text, attachments);
|
|
@@ -7439,7 +7991,7 @@ function useOptimisticChatMessages({
|
|
|
7439
7991
|
},
|
|
7440
7992
|
[chatMessages, disableOptimistic, onSendChat, shouldForkOnEdit]
|
|
7441
7993
|
);
|
|
7442
|
-
const onRetry =
|
|
7994
|
+
const onRetry = React44.useCallback(
|
|
7443
7995
|
async (messageId) => {
|
|
7444
7996
|
if (shouldForkOnEdit || disableOptimistic) return;
|
|
7445
7997
|
const target = optimisticChat.find((m) => m.id === messageId);
|
|
@@ -7463,7 +8015,7 @@ function useOptimisticChatMessages({
|
|
|
7463
8015
|
},
|
|
7464
8016
|
[chatMessages, disableOptimistic, onSendChat, optimisticChat, shouldForkOnEdit]
|
|
7465
8017
|
);
|
|
7466
|
-
const isRetrying =
|
|
8018
|
+
const isRetrying = React44.useCallback(
|
|
7467
8019
|
(messageId) => {
|
|
7468
8020
|
return optimisticChat.some((m) => m.id === messageId && m.retrying);
|
|
7469
8021
|
},
|
|
@@ -7474,7 +8026,7 @@ function useOptimisticChatMessages({
|
|
|
7474
8026
|
|
|
7475
8027
|
// src/studio/ui/StudioOverlay.tsx
|
|
7476
8028
|
var import_studio_control = require("@comergehq/studio-control");
|
|
7477
|
-
var
|
|
8029
|
+
var import_jsx_runtime61 = require("react/jsx-runtime");
|
|
7478
8030
|
function StudioOverlay({
|
|
7479
8031
|
captureTargetRef,
|
|
7480
8032
|
app,
|
|
@@ -7507,19 +8059,20 @@ function StudioOverlay({
|
|
|
7507
8059
|
onSendChat,
|
|
7508
8060
|
chatQueueItems,
|
|
7509
8061
|
onRemoveQueueItem,
|
|
8062
|
+
chatProgress,
|
|
7510
8063
|
onNavigateHome,
|
|
7511
8064
|
showBubble,
|
|
7512
8065
|
studioControlOptions
|
|
7513
8066
|
}) {
|
|
7514
8067
|
const theme = useTheme();
|
|
7515
|
-
const { width } = (0,
|
|
7516
|
-
const [sheetOpen, setSheetOpen] =
|
|
7517
|
-
const sheetOpenRef =
|
|
7518
|
-
const [activePage, setActivePage] =
|
|
7519
|
-
const [drawing, setDrawing] =
|
|
7520
|
-
const [chatAttachments, setChatAttachments] =
|
|
7521
|
-
const [commentsAppId, setCommentsAppId] =
|
|
7522
|
-
const [commentsCount, setCommentsCount] =
|
|
8068
|
+
const { width } = (0, import_react_native59.useWindowDimensions)();
|
|
8069
|
+
const [sheetOpen, setSheetOpen] = React45.useState(false);
|
|
8070
|
+
const sheetOpenRef = React45.useRef(sheetOpen);
|
|
8071
|
+
const [activePage, setActivePage] = React45.useState("preview");
|
|
8072
|
+
const [drawing, setDrawing] = React45.useState(false);
|
|
8073
|
+
const [chatAttachments, setChatAttachments] = React45.useState([]);
|
|
8074
|
+
const [commentsAppId, setCommentsAppId] = React45.useState(null);
|
|
8075
|
+
const [commentsCount, setCommentsCount] = React45.useState(null);
|
|
7523
8076
|
const threadId = (app == null ? void 0 : app.threadId) ?? null;
|
|
7524
8077
|
const isForking = chatForking || (app == null ? void 0 : app.status) === "forking";
|
|
7525
8078
|
const queueItemsForChat = isForking ? [] : chatQueueItems;
|
|
@@ -7531,26 +8084,26 @@ function StudioOverlay({
|
|
|
7531
8084
|
chatMessages,
|
|
7532
8085
|
onSendChat
|
|
7533
8086
|
});
|
|
7534
|
-
const [confirmMrId, setConfirmMrId] =
|
|
7535
|
-
const confirmMr =
|
|
8087
|
+
const [confirmMrId, setConfirmMrId] = React45.useState(null);
|
|
8088
|
+
const confirmMr = React45.useMemo(
|
|
7536
8089
|
() => confirmMrId ? incomingMergeRequests.find((m) => m.id === confirmMrId) ?? null : null,
|
|
7537
8090
|
[confirmMrId, incomingMergeRequests]
|
|
7538
8091
|
);
|
|
7539
|
-
const handleSheetOpenChange =
|
|
8092
|
+
const handleSheetOpenChange = React45.useCallback((open) => {
|
|
7540
8093
|
setSheetOpen(open);
|
|
7541
|
-
if (!open)
|
|
8094
|
+
if (!open) import_react_native59.Keyboard.dismiss();
|
|
7542
8095
|
}, []);
|
|
7543
|
-
const closeSheet =
|
|
8096
|
+
const closeSheet = React45.useCallback(() => {
|
|
7544
8097
|
handleSheetOpenChange(false);
|
|
7545
8098
|
}, [handleSheetOpenChange]);
|
|
7546
|
-
const openSheet =
|
|
7547
|
-
const goToChat =
|
|
8099
|
+
const openSheet = React45.useCallback(() => setSheetOpen(true), []);
|
|
8100
|
+
const goToChat = React45.useCallback(() => {
|
|
7548
8101
|
setActivePage("chat");
|
|
7549
8102
|
openSheet();
|
|
7550
8103
|
}, [openSheet]);
|
|
7551
|
-
const backToPreview =
|
|
7552
|
-
if (
|
|
7553
|
-
|
|
8104
|
+
const backToPreview = React45.useCallback(() => {
|
|
8105
|
+
if (import_react_native59.Platform.OS !== "ios") {
|
|
8106
|
+
import_react_native59.Keyboard.dismiss();
|
|
7554
8107
|
setActivePage("preview");
|
|
7555
8108
|
return;
|
|
7556
8109
|
}
|
|
@@ -7562,15 +8115,15 @@ function StudioOverlay({
|
|
|
7562
8115
|
clearTimeout(t);
|
|
7563
8116
|
setActivePage("preview");
|
|
7564
8117
|
};
|
|
7565
|
-
const sub =
|
|
8118
|
+
const sub = import_react_native59.Keyboard.addListener("keyboardDidHide", finalize);
|
|
7566
8119
|
const t = setTimeout(finalize, 350);
|
|
7567
|
-
|
|
8120
|
+
import_react_native59.Keyboard.dismiss();
|
|
7568
8121
|
}, []);
|
|
7569
|
-
const startDraw =
|
|
8122
|
+
const startDraw = React45.useCallback(() => {
|
|
7570
8123
|
setDrawing(true);
|
|
7571
8124
|
closeSheet();
|
|
7572
8125
|
}, [closeSheet]);
|
|
7573
|
-
const handleDrawCapture =
|
|
8126
|
+
const handleDrawCapture = React45.useCallback(
|
|
7574
8127
|
(dataUrl) => {
|
|
7575
8128
|
setChatAttachments((prev) => [...prev, dataUrl]);
|
|
7576
8129
|
setDrawing(false);
|
|
@@ -7579,7 +8132,7 @@ function StudioOverlay({
|
|
|
7579
8132
|
},
|
|
7580
8133
|
[openSheet]
|
|
7581
8134
|
);
|
|
7582
|
-
const toggleSheet =
|
|
8135
|
+
const toggleSheet = React45.useCallback(async () => {
|
|
7583
8136
|
if (!sheetOpen) {
|
|
7584
8137
|
const shouldExitTest = Boolean(testingMrId) || isTesting;
|
|
7585
8138
|
if (shouldExitTest) {
|
|
@@ -7591,7 +8144,7 @@ function StudioOverlay({
|
|
|
7591
8144
|
closeSheet();
|
|
7592
8145
|
}
|
|
7593
8146
|
}, [closeSheet, isTesting, onRestoreBase, sheetOpen, testingMrId]);
|
|
7594
|
-
const handleTestMr =
|
|
8147
|
+
const handleTestMr = React45.useCallback(
|
|
7595
8148
|
async (mr) => {
|
|
7596
8149
|
if (!onTestMr) return;
|
|
7597
8150
|
await onTestMr(mr);
|
|
@@ -7599,10 +8152,10 @@ function StudioOverlay({
|
|
|
7599
8152
|
},
|
|
7600
8153
|
[closeSheet, onTestMr]
|
|
7601
8154
|
);
|
|
7602
|
-
|
|
8155
|
+
React45.useEffect(() => {
|
|
7603
8156
|
sheetOpenRef.current = sheetOpen;
|
|
7604
8157
|
}, [sheetOpen]);
|
|
7605
|
-
|
|
8158
|
+
React45.useEffect(() => {
|
|
7606
8159
|
const poller = (0, import_studio_control.startStudioControlPolling)((action) => {
|
|
7607
8160
|
if (action === "show" && !sheetOpenRef.current) openSheet();
|
|
7608
8161
|
if (action === "hide" && sheetOpenRef.current) closeSheet();
|
|
@@ -7610,17 +8163,17 @@ function StudioOverlay({
|
|
|
7610
8163
|
}, studioControlOptions);
|
|
7611
8164
|
return () => poller.stop();
|
|
7612
8165
|
}, [closeSheet, openSheet, studioControlOptions, toggleSheet]);
|
|
7613
|
-
|
|
8166
|
+
React45.useEffect(() => {
|
|
7614
8167
|
void (0, import_studio_control.publishComergeStudioUIState)(sheetOpen, studioControlOptions);
|
|
7615
8168
|
}, [sheetOpen, studioControlOptions]);
|
|
7616
|
-
return /* @__PURE__ */ (0,
|
|
7617
|
-
/* @__PURE__ */ (0,
|
|
7618
|
-
/* @__PURE__ */ (0,
|
|
8169
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(import_jsx_runtime61.Fragment, { children: [
|
|
8170
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(EdgeGlowFrame, { visible: isTesting, role: "accent", thickness: 40, intensity: 1 }),
|
|
8171
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(StudioBottomSheet, { open: sheetOpen, onOpenChange: handleSheetOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
7619
8172
|
StudioSheetPager,
|
|
7620
8173
|
{
|
|
7621
8174
|
activePage,
|
|
7622
8175
|
width,
|
|
7623
|
-
preview: /* @__PURE__ */ (0,
|
|
8176
|
+
preview: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
7624
8177
|
PreviewPanel,
|
|
7625
8178
|
{
|
|
7626
8179
|
app,
|
|
@@ -7649,7 +8202,7 @@ function StudioOverlay({
|
|
|
7649
8202
|
commentCountOverride: commentsCount ?? void 0
|
|
7650
8203
|
}
|
|
7651
8204
|
),
|
|
7652
|
-
chat: /* @__PURE__ */ (0,
|
|
8205
|
+
chat: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
7653
8206
|
ChatPanel,
|
|
7654
8207
|
{
|
|
7655
8208
|
messages: optimistic.messages,
|
|
@@ -7670,12 +8223,13 @@ function StudioOverlay({
|
|
|
7670
8223
|
onRetryMessage: optimistic.onRetry,
|
|
7671
8224
|
isRetryingMessage: optimistic.isRetrying,
|
|
7672
8225
|
queueItems: queueItemsForChat,
|
|
7673
|
-
onRemoveQueueItem
|
|
8226
|
+
onRemoveQueueItem,
|
|
8227
|
+
progress: chatProgress
|
|
7674
8228
|
}
|
|
7675
8229
|
)
|
|
7676
8230
|
}
|
|
7677
8231
|
) }),
|
|
7678
|
-
showBubble && /* @__PURE__ */ (0,
|
|
8232
|
+
showBubble && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
7679
8233
|
Bubble,
|
|
7680
8234
|
{
|
|
7681
8235
|
visible: !sheetOpen && !drawing,
|
|
@@ -7684,10 +8238,10 @@ function StudioOverlay({
|
|
|
7684
8238
|
onPress: toggleSheet,
|
|
7685
8239
|
isLoading: (app == null ? void 0 : app.status) === "editing" || isBaseBundleDownloading,
|
|
7686
8240
|
loadingBorderTone: isBaseBundleDownloading ? "warning" : "default",
|
|
7687
|
-
children: /* @__PURE__ */ (0,
|
|
8241
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(import_react_native59.View, { style: { width: 28, height: 28, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(MergeIcon, { width: 24, height: 24, color: theme.colors.floatingContent }) })
|
|
7688
8242
|
}
|
|
7689
8243
|
),
|
|
7690
|
-
/* @__PURE__ */ (0,
|
|
8244
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
7691
8245
|
DrawModeOverlay,
|
|
7692
8246
|
{
|
|
7693
8247
|
visible: drawing,
|
|
@@ -7696,7 +8250,7 @@ function StudioOverlay({
|
|
|
7696
8250
|
onCapture: handleDrawCapture
|
|
7697
8251
|
}
|
|
7698
8252
|
),
|
|
7699
|
-
/* @__PURE__ */ (0,
|
|
8253
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
7700
8254
|
ConfirmMergeFlow,
|
|
7701
8255
|
{
|
|
7702
8256
|
visible: Boolean(confirmMr),
|
|
@@ -7710,7 +8264,7 @@ function StudioOverlay({
|
|
|
7710
8264
|
onTestFirst: handleTestMr
|
|
7711
8265
|
}
|
|
7712
8266
|
),
|
|
7713
|
-
/* @__PURE__ */ (0,
|
|
8267
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
7714
8268
|
AppCommentsSheet,
|
|
7715
8269
|
{
|
|
7716
8270
|
appId: commentsAppId,
|
|
@@ -7723,7 +8277,7 @@ function StudioOverlay({
|
|
|
7723
8277
|
}
|
|
7724
8278
|
|
|
7725
8279
|
// src/studio/hooks/useEditQueue.ts
|
|
7726
|
-
var
|
|
8280
|
+
var React46 = __toESM(require("react"));
|
|
7727
8281
|
|
|
7728
8282
|
// src/data/apps/edit-queue/remote.ts
|
|
7729
8283
|
var EditQueueRemoteDataSourceImpl = class extends BaseRemote {
|
|
@@ -7832,17 +8386,17 @@ var editQueueRepository = new EditQueueRepositoryImpl(
|
|
|
7832
8386
|
|
|
7833
8387
|
// src/studio/hooks/useEditQueue.ts
|
|
7834
8388
|
function useEditQueue(appId) {
|
|
7835
|
-
const [items, setItems] =
|
|
7836
|
-
const [loading, setLoading] =
|
|
7837
|
-
const [error, setError] =
|
|
7838
|
-
const activeRequestIdRef =
|
|
8389
|
+
const [items, setItems] = React46.useState([]);
|
|
8390
|
+
const [loading, setLoading] = React46.useState(false);
|
|
8391
|
+
const [error, setError] = React46.useState(null);
|
|
8392
|
+
const activeRequestIdRef = React46.useRef(0);
|
|
7839
8393
|
const foregroundSignal = useForegroundSignal(Boolean(appId));
|
|
7840
|
-
const upsertSorted =
|
|
8394
|
+
const upsertSorted = React46.useCallback((prev, nextItem) => {
|
|
7841
8395
|
const next = prev.some((x) => x.id === nextItem.id) ? prev.map((x) => x.id === nextItem.id ? nextItem : x) : [...prev, nextItem];
|
|
7842
8396
|
next.sort((a, b) => String(a.createdAt).localeCompare(String(b.createdAt)));
|
|
7843
8397
|
return next;
|
|
7844
8398
|
}, []);
|
|
7845
|
-
const refetch =
|
|
8399
|
+
const refetch = React46.useCallback(async () => {
|
|
7846
8400
|
if (!appId) {
|
|
7847
8401
|
setItems([]);
|
|
7848
8402
|
return;
|
|
@@ -7862,10 +8416,10 @@ function useEditQueue(appId) {
|
|
|
7862
8416
|
if (activeRequestIdRef.current === requestId) setLoading(false);
|
|
7863
8417
|
}
|
|
7864
8418
|
}, [appId]);
|
|
7865
|
-
|
|
8419
|
+
React46.useEffect(() => {
|
|
7866
8420
|
void refetch();
|
|
7867
8421
|
}, [refetch]);
|
|
7868
|
-
|
|
8422
|
+
React46.useEffect(() => {
|
|
7869
8423
|
if (!appId) return;
|
|
7870
8424
|
const unsubscribe = editQueueRepository.subscribeEditQueue(appId, {
|
|
7871
8425
|
onInsert: (item) => setItems((prev) => upsertSorted(prev, item)),
|
|
@@ -7874,7 +8428,7 @@ function useEditQueue(appId) {
|
|
|
7874
8428
|
});
|
|
7875
8429
|
return unsubscribe;
|
|
7876
8430
|
}, [appId, upsertSorted, foregroundSignal]);
|
|
7877
|
-
|
|
8431
|
+
React46.useEffect(() => {
|
|
7878
8432
|
if (!appId) return;
|
|
7879
8433
|
if (foregroundSignal <= 0) return;
|
|
7880
8434
|
void refetch();
|
|
@@ -7883,16 +8437,16 @@ function useEditQueue(appId) {
|
|
|
7883
8437
|
}
|
|
7884
8438
|
|
|
7885
8439
|
// src/studio/hooks/useEditQueueActions.ts
|
|
7886
|
-
var
|
|
8440
|
+
var React47 = __toESM(require("react"));
|
|
7887
8441
|
function useEditQueueActions(appId) {
|
|
7888
|
-
const update =
|
|
8442
|
+
const update = React47.useCallback(
|
|
7889
8443
|
async (queueItemId, payload) => {
|
|
7890
8444
|
if (!appId) return;
|
|
7891
8445
|
await editQueueRepository.update(appId, queueItemId, payload);
|
|
7892
8446
|
},
|
|
7893
8447
|
[appId]
|
|
7894
8448
|
);
|
|
7895
|
-
const cancel =
|
|
8449
|
+
const cancel = React47.useCallback(
|
|
7896
8450
|
async (queueItemId) => {
|
|
7897
8451
|
if (!appId) return;
|
|
7898
8452
|
await editQueueRepository.cancel(appId, queueItemId);
|
|
@@ -7902,48 +8456,461 @@ function useEditQueueActions(appId) {
|
|
|
7902
8456
|
return { update, cancel };
|
|
7903
8457
|
}
|
|
7904
8458
|
|
|
8459
|
+
// src/studio/hooks/useAgentRunProgress.ts
|
|
8460
|
+
var React48 = __toESM(require("react"));
|
|
8461
|
+
|
|
8462
|
+
// src/data/agent-progress/repository.ts
|
|
8463
|
+
function mapRun(row) {
|
|
8464
|
+
return {
|
|
8465
|
+
id: row.id,
|
|
8466
|
+
appId: row.app_id,
|
|
8467
|
+
threadId: row.thread_id,
|
|
8468
|
+
queueItemId: row.queue_item_id,
|
|
8469
|
+
status: row.status,
|
|
8470
|
+
currentPhase: row.current_phase,
|
|
8471
|
+
lastSeq: Number(row.last_seq || 0),
|
|
8472
|
+
summary: row.summary || {},
|
|
8473
|
+
errorCode: row.error_code,
|
|
8474
|
+
errorMessage: row.error_message,
|
|
8475
|
+
startedAt: row.started_at,
|
|
8476
|
+
finishedAt: row.finished_at,
|
|
8477
|
+
createdAt: row.created_at,
|
|
8478
|
+
updatedAt: row.updated_at
|
|
8479
|
+
};
|
|
8480
|
+
}
|
|
8481
|
+
function mapEvent(row) {
|
|
8482
|
+
return {
|
|
8483
|
+
id: row.id,
|
|
8484
|
+
runId: row.run_id,
|
|
8485
|
+
appId: row.app_id,
|
|
8486
|
+
threadId: row.thread_id,
|
|
8487
|
+
queueItemId: row.queue_item_id,
|
|
8488
|
+
seq: Number(row.seq || 0),
|
|
8489
|
+
eventType: row.event_type,
|
|
8490
|
+
phase: row.phase,
|
|
8491
|
+
toolName: row.tool_name,
|
|
8492
|
+
path: row.path,
|
|
8493
|
+
payload: row.payload || {},
|
|
8494
|
+
createdAt: row.created_at
|
|
8495
|
+
};
|
|
8496
|
+
}
|
|
8497
|
+
var AgentProgressRepositoryImpl = class {
|
|
8498
|
+
async getLatestRun(threadId) {
|
|
8499
|
+
if (!threadId) return null;
|
|
8500
|
+
const supabase = getSupabaseClient();
|
|
8501
|
+
const { data, error } = await supabase.from("agent_run").select("*").eq("thread_id", threadId).order("started_at", { ascending: false }).limit(1).maybeSingle();
|
|
8502
|
+
if (error) throw new Error(error.message || "Failed to fetch latest agent run");
|
|
8503
|
+
if (!data) return null;
|
|
8504
|
+
return mapRun(data);
|
|
8505
|
+
}
|
|
8506
|
+
async listEvents(runId, afterSeq) {
|
|
8507
|
+
if (!runId) return [];
|
|
8508
|
+
const supabase = getSupabaseClient();
|
|
8509
|
+
let query = supabase.from("agent_run_event").select("*").eq("run_id", runId).order("seq", { ascending: true });
|
|
8510
|
+
if (typeof afterSeq === "number" && Number.isFinite(afterSeq) && afterSeq > 0) {
|
|
8511
|
+
query = query.gt("seq", afterSeq);
|
|
8512
|
+
}
|
|
8513
|
+
const { data, error } = await query;
|
|
8514
|
+
if (error) throw new Error(error.message || "Failed to fetch agent run events");
|
|
8515
|
+
const rows = Array.isArray(data) ? data : [];
|
|
8516
|
+
return rows.map(mapEvent);
|
|
8517
|
+
}
|
|
8518
|
+
subscribeThreadRuns(threadId, handlers) {
|
|
8519
|
+
return subscribeManagedChannel(`agent-progress:runs:thread:${threadId}`, (channel) => {
|
|
8520
|
+
channel.on(
|
|
8521
|
+
"postgres_changes",
|
|
8522
|
+
{ event: "INSERT", schema: "public", table: "agent_run", filter: `thread_id=eq.${threadId}` },
|
|
8523
|
+
(payload) => {
|
|
8524
|
+
var _a;
|
|
8525
|
+
const row = payload.new;
|
|
8526
|
+
(_a = handlers.onInsert) == null ? void 0 : _a.call(handlers, mapRun(row));
|
|
8527
|
+
}
|
|
8528
|
+
).on(
|
|
8529
|
+
"postgres_changes",
|
|
8530
|
+
{ event: "UPDATE", schema: "public", table: "agent_run", filter: `thread_id=eq.${threadId}` },
|
|
8531
|
+
(payload) => {
|
|
8532
|
+
var _a;
|
|
8533
|
+
const row = payload.new;
|
|
8534
|
+
(_a = handlers.onUpdate) == null ? void 0 : _a.call(handlers, mapRun(row));
|
|
8535
|
+
}
|
|
8536
|
+
);
|
|
8537
|
+
});
|
|
8538
|
+
}
|
|
8539
|
+
subscribeRunEvents(runId, handlers) {
|
|
8540
|
+
return subscribeManagedChannel(`agent-progress:events:run:${runId}`, (channel) => {
|
|
8541
|
+
channel.on(
|
|
8542
|
+
"postgres_changes",
|
|
8543
|
+
{ event: "INSERT", schema: "public", table: "agent_run_event", filter: `run_id=eq.${runId}` },
|
|
8544
|
+
(payload) => {
|
|
8545
|
+
var _a;
|
|
8546
|
+
const row = payload.new;
|
|
8547
|
+
(_a = handlers.onInsert) == null ? void 0 : _a.call(handlers, mapEvent(row));
|
|
8548
|
+
}
|
|
8549
|
+
).on(
|
|
8550
|
+
"postgres_changes",
|
|
8551
|
+
{ event: "UPDATE", schema: "public", table: "agent_run_event", filter: `run_id=eq.${runId}` },
|
|
8552
|
+
(payload) => {
|
|
8553
|
+
var _a;
|
|
8554
|
+
const row = payload.new;
|
|
8555
|
+
(_a = handlers.onUpdate) == null ? void 0 : _a.call(handlers, mapEvent(row));
|
|
8556
|
+
}
|
|
8557
|
+
);
|
|
8558
|
+
});
|
|
8559
|
+
}
|
|
8560
|
+
};
|
|
8561
|
+
var agentProgressRepository = new AgentProgressRepositoryImpl();
|
|
8562
|
+
|
|
8563
|
+
// src/studio/hooks/useAgentRunProgress.ts
|
|
8564
|
+
function upsertBySeq(prev, next) {
|
|
8565
|
+
const map = /* @__PURE__ */ new Map();
|
|
8566
|
+
for (const item of prev) map.set(item.seq, item);
|
|
8567
|
+
map.set(next.seq, next);
|
|
8568
|
+
return Array.from(map.values()).sort((a, b) => a.seq - b.seq);
|
|
8569
|
+
}
|
|
8570
|
+
function mergeMany(prev, incoming) {
|
|
8571
|
+
if (incoming.length === 0) return prev;
|
|
8572
|
+
const map = /* @__PURE__ */ new Map();
|
|
8573
|
+
for (const item of prev) map.set(item.seq, item);
|
|
8574
|
+
for (const item of incoming) map.set(item.seq, item);
|
|
8575
|
+
return Array.from(map.values()).sort((a, b) => a.seq - b.seq);
|
|
8576
|
+
}
|
|
8577
|
+
function toMs(v) {
|
|
8578
|
+
if (!v) return 0;
|
|
8579
|
+
const n = Date.parse(v);
|
|
8580
|
+
return Number.isFinite(n) ? n : 0;
|
|
8581
|
+
}
|
|
8582
|
+
function shouldSwitchRun(current, candidate) {
|
|
8583
|
+
if (!current) return true;
|
|
8584
|
+
if (candidate.id === current.id) return true;
|
|
8585
|
+
return toMs(candidate.startedAt) >= toMs(current.startedAt);
|
|
8586
|
+
}
|
|
8587
|
+
function toInt(value) {
|
|
8588
|
+
const n = Number(value);
|
|
8589
|
+
return Number.isFinite(n) ? n : 0;
|
|
8590
|
+
}
|
|
8591
|
+
function toBundleStage(value) {
|
|
8592
|
+
if (value === "queued") return "queued";
|
|
8593
|
+
if (value === "building") return "building";
|
|
8594
|
+
if (value === "fixing") return "fixing";
|
|
8595
|
+
if (value === "retrying") return "retrying";
|
|
8596
|
+
if (value === "finalizing") return "finalizing";
|
|
8597
|
+
if (value === "ready") return "ready";
|
|
8598
|
+
if (value === "failed") return "failed";
|
|
8599
|
+
return null;
|
|
8600
|
+
}
|
|
8601
|
+
function toBundlePlatform(value) {
|
|
8602
|
+
if (value === "ios" || value === "android") return value;
|
|
8603
|
+
return "both";
|
|
8604
|
+
}
|
|
8605
|
+
function clamp01(value) {
|
|
8606
|
+
if (value <= 0) return 0;
|
|
8607
|
+
if (value >= 1) return 1;
|
|
8608
|
+
return value;
|
|
8609
|
+
}
|
|
8610
|
+
function defaultBundleLabel(stage) {
|
|
8611
|
+
if (stage === "queued") return "Queued for build";
|
|
8612
|
+
if (stage === "building") return "Building bundle";
|
|
8613
|
+
if (stage === "fixing") return "Applying auto-fix";
|
|
8614
|
+
if (stage === "retrying") return "Retrying bundle";
|
|
8615
|
+
if (stage === "finalizing") return "Finalizing artifacts";
|
|
8616
|
+
if (stage === "ready") return "Bundle ready";
|
|
8617
|
+
if (stage === "failed") return "Bundle failed";
|
|
8618
|
+
return "Building bundle";
|
|
8619
|
+
}
|
|
8620
|
+
function fallbackBundleProgress(stage, startedAtMs, nowMs) {
|
|
8621
|
+
if (stage === "ready") return 1;
|
|
8622
|
+
if (stage === "failed") return 0.96;
|
|
8623
|
+
const elapsed = Math.max(0, nowMs - startedAtMs);
|
|
8624
|
+
const expectedMs = 6e4;
|
|
8625
|
+
if (elapsed <= expectedMs) {
|
|
8626
|
+
const t = clamp01(elapsed / expectedMs);
|
|
8627
|
+
return 0.05 + 0.85 * (1 - Math.pow(1 - t, 2));
|
|
8628
|
+
}
|
|
8629
|
+
const over = elapsed - expectedMs;
|
|
8630
|
+
return Math.min(0.9 + 0.07 * (1 - Math.exp(-over / 25e3)), 0.97);
|
|
8631
|
+
}
|
|
8632
|
+
function deriveView(run, events, nowMs) {
|
|
8633
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
8634
|
+
const files = [];
|
|
8635
|
+
const fileSeen = /* @__PURE__ */ new Set();
|
|
8636
|
+
let todoSummary = null;
|
|
8637
|
+
let latestMessage = null;
|
|
8638
|
+
let phase = (run == null ? void 0 : run.currentPhase) ?? null;
|
|
8639
|
+
let bundleStage = null;
|
|
8640
|
+
let bundleLabel = null;
|
|
8641
|
+
let bundleError = null;
|
|
8642
|
+
let bundleProgressHint = null;
|
|
8643
|
+
let bundlePlatform = "both";
|
|
8644
|
+
let bundleStartedAtMs = null;
|
|
8645
|
+
let lastBundleSig = null;
|
|
8646
|
+
for (const ev of events) {
|
|
8647
|
+
if (ev.eventType === "phase_changed") {
|
|
8648
|
+
if (typeof ((_a = ev.payload) == null ? void 0 : _a.message) === "string") latestMessage = ev.payload.message;
|
|
8649
|
+
if (ev.phase) phase = ev.phase;
|
|
8650
|
+
}
|
|
8651
|
+
if (ev.eventType === "file_changed") {
|
|
8652
|
+
if (ev.path && !fileSeen.has(ev.path)) {
|
|
8653
|
+
fileSeen.add(ev.path);
|
|
8654
|
+
files.push(ev.path);
|
|
8655
|
+
}
|
|
8656
|
+
}
|
|
8657
|
+
if (ev.eventType === "todo_updated") {
|
|
8658
|
+
todoSummary = {
|
|
8659
|
+
total: toInt((_b = ev.payload) == null ? void 0 : _b.total),
|
|
8660
|
+
pending: toInt((_c = ev.payload) == null ? void 0 : _c.pending),
|
|
8661
|
+
inProgress: toInt((_d = ev.payload) == null ? void 0 : _d.inProgress),
|
|
8662
|
+
completed: toInt((_e = ev.payload) == null ? void 0 : _e.completed),
|
|
8663
|
+
currentTask: typeof ((_f = ev.payload) == null ? void 0 : _f.currentTask) === "string" ? ev.payload.currentTask : null
|
|
8664
|
+
};
|
|
8665
|
+
}
|
|
8666
|
+
const stageType = typeof ((_g = ev.payload) == null ? void 0 : _g.stage) === "string" ? ev.payload.stage : null;
|
|
8667
|
+
if (stageType !== "bundle") continue;
|
|
8668
|
+
const nextStage = toBundleStage((_h = ev.payload) == null ? void 0 : _h.bundlePhase);
|
|
8669
|
+
if (!nextStage) continue;
|
|
8670
|
+
const nextPlatform = toBundlePlatform((_i = ev.payload) == null ? void 0 : _i.platform);
|
|
8671
|
+
const message = typeof ((_j = ev.payload) == null ? void 0 : _j.message) === "string" ? ev.payload.message : null;
|
|
8672
|
+
const phaseLabel = message || (typeof ((_k = ev.payload) == null ? void 0 : _k.message) === "string" ? ev.payload.message : null);
|
|
8673
|
+
const hintRaw = Number((_l = ev.payload) == null ? void 0 : _l.progressHint);
|
|
8674
|
+
const progressHint = Number.isFinite(hintRaw) ? clamp01(hintRaw) : null;
|
|
8675
|
+
const errorText = typeof ((_m = ev.payload) == null ? void 0 : _m.error) === "string" ? ev.payload.error : null;
|
|
8676
|
+
const sig = `${ev.seq}:${nextStage}:${nextPlatform}:${progressHint ?? "none"}:${phaseLabel ?? "none"}:${errorText ?? "none"}`;
|
|
8677
|
+
if (sig === lastBundleSig) continue;
|
|
8678
|
+
lastBundleSig = sig;
|
|
8679
|
+
bundleStage = nextStage;
|
|
8680
|
+
bundlePlatform = nextPlatform;
|
|
8681
|
+
if (phaseLabel) bundleLabel = phaseLabel;
|
|
8682
|
+
if (progressHint != null) bundleProgressHint = progressHint;
|
|
8683
|
+
if (errorText) bundleError = errorText;
|
|
8684
|
+
const evMs = toMs(ev.createdAt);
|
|
8685
|
+
if (!bundleStartedAtMs && evMs > 0) bundleStartedAtMs = evMs;
|
|
8686
|
+
}
|
|
8687
|
+
if (!latestMessage) {
|
|
8688
|
+
if (phase === "planning") latestMessage = "Planning changes...";
|
|
8689
|
+
else if (phase === "analyzing") latestMessage = "Analyzing relevant files...";
|
|
8690
|
+
else if (phase === "editing") latestMessage = "Applying code updates...";
|
|
8691
|
+
else if (phase === "validating") latestMessage = "Validating updates...";
|
|
8692
|
+
else if (phase === "finalizing") latestMessage = "Finalizing response...";
|
|
8693
|
+
else if (phase) latestMessage = `Working (${phase})...`;
|
|
8694
|
+
}
|
|
8695
|
+
const runFinished = (run == null ? void 0 : run.status) === "succeeded" || (run == null ? void 0 : run.status) === "failed" || (run == null ? void 0 : run.status) === "cancelled";
|
|
8696
|
+
let bundle = null;
|
|
8697
|
+
if (bundleStage && !runFinished) {
|
|
8698
|
+
const baseTime = bundleStartedAtMs ?? toMs(run == null ? void 0 : run.startedAt) ?? nowMs;
|
|
8699
|
+
const fallback = fallbackBundleProgress(bundleStage, baseTime || nowMs, nowMs);
|
|
8700
|
+
const value = bundleProgressHint != null ? Math.max(fallback, bundleProgressHint) : fallback;
|
|
8701
|
+
const status = bundleStage === "failed" ? "failed" : bundleStage === "ready" ? "succeeded" : "loading";
|
|
8702
|
+
bundle = {
|
|
8703
|
+
active: status === "loading",
|
|
8704
|
+
status,
|
|
8705
|
+
phaseLabel: bundleLabel || defaultBundleLabel(bundleStage),
|
|
8706
|
+
progressValue: clamp01(value),
|
|
8707
|
+
errorMessage: bundleError,
|
|
8708
|
+
platform: bundlePlatform
|
|
8709
|
+
};
|
|
8710
|
+
}
|
|
8711
|
+
return {
|
|
8712
|
+
runId: (run == null ? void 0 : run.id) ?? null,
|
|
8713
|
+
status: (run == null ? void 0 : run.status) ?? null,
|
|
8714
|
+
phase,
|
|
8715
|
+
latestMessage,
|
|
8716
|
+
changedFilesCount: fileSeen.size,
|
|
8717
|
+
recentFiles: files.slice(-5),
|
|
8718
|
+
todoSummary,
|
|
8719
|
+
bundle,
|
|
8720
|
+
events
|
|
8721
|
+
};
|
|
8722
|
+
}
|
|
8723
|
+
function useAgentRunProgress(threadId, opts) {
|
|
8724
|
+
var _a;
|
|
8725
|
+
const enabled = Boolean((opts == null ? void 0 : opts.enabled) ?? true);
|
|
8726
|
+
const [run, setRun] = React48.useState(null);
|
|
8727
|
+
const [events, setEvents] = React48.useState([]);
|
|
8728
|
+
const [loading, setLoading] = React48.useState(false);
|
|
8729
|
+
const [error, setError] = React48.useState(null);
|
|
8730
|
+
const activeRequestIdRef = React48.useRef(0);
|
|
8731
|
+
const lastSeqRef = React48.useRef(0);
|
|
8732
|
+
const runRef = React48.useRef(null);
|
|
8733
|
+
const foregroundSignal = useForegroundSignal(Boolean(threadId) && enabled);
|
|
8734
|
+
const [bundleTick, setBundleTick] = React48.useState(0);
|
|
8735
|
+
React48.useEffect(() => {
|
|
8736
|
+
lastSeqRef.current = 0;
|
|
8737
|
+
runRef.current = null;
|
|
8738
|
+
}, [threadId]);
|
|
8739
|
+
React48.useEffect(() => {
|
|
8740
|
+
runRef.current = run;
|
|
8741
|
+
}, [run]);
|
|
8742
|
+
const refetch = React48.useCallback(async () => {
|
|
8743
|
+
if (!threadId || !enabled) {
|
|
8744
|
+
setRun(null);
|
|
8745
|
+
setEvents([]);
|
|
8746
|
+
setLoading(false);
|
|
8747
|
+
setError(null);
|
|
8748
|
+
return;
|
|
8749
|
+
}
|
|
8750
|
+
const requestId = ++activeRequestIdRef.current;
|
|
8751
|
+
setLoading(true);
|
|
8752
|
+
setError(null);
|
|
8753
|
+
try {
|
|
8754
|
+
const latestRun = await agentProgressRepository.getLatestRun(threadId);
|
|
8755
|
+
if (activeRequestIdRef.current !== requestId) return;
|
|
8756
|
+
if (!latestRun) {
|
|
8757
|
+
setRun(null);
|
|
8758
|
+
setEvents([]);
|
|
8759
|
+
lastSeqRef.current = 0;
|
|
8760
|
+
return;
|
|
8761
|
+
}
|
|
8762
|
+
const initialEvents = await agentProgressRepository.listEvents(latestRun.id);
|
|
8763
|
+
if (activeRequestIdRef.current !== requestId) return;
|
|
8764
|
+
const sorted = [...initialEvents].sort((a, b) => a.seq - b.seq);
|
|
8765
|
+
setRun(latestRun);
|
|
8766
|
+
setEvents(sorted);
|
|
8767
|
+
lastSeqRef.current = sorted.length > 0 ? sorted[sorted.length - 1].seq : 0;
|
|
8768
|
+
} catch (e) {
|
|
8769
|
+
if (activeRequestIdRef.current !== requestId) return;
|
|
8770
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
8771
|
+
setRun(null);
|
|
8772
|
+
setEvents([]);
|
|
8773
|
+
lastSeqRef.current = 0;
|
|
8774
|
+
} finally {
|
|
8775
|
+
if (activeRequestIdRef.current === requestId) setLoading(false);
|
|
8776
|
+
}
|
|
8777
|
+
}, [enabled, threadId]);
|
|
8778
|
+
React48.useEffect(() => {
|
|
8779
|
+
void refetch();
|
|
8780
|
+
}, [refetch]);
|
|
8781
|
+
React48.useEffect(() => {
|
|
8782
|
+
if (!threadId || !enabled) return;
|
|
8783
|
+
if (foregroundSignal <= 0) return;
|
|
8784
|
+
void refetch();
|
|
8785
|
+
}, [enabled, foregroundSignal, refetch, threadId]);
|
|
8786
|
+
React48.useEffect(() => {
|
|
8787
|
+
if (!threadId || !enabled) return;
|
|
8788
|
+
const unsubRuns = agentProgressRepository.subscribeThreadRuns(threadId, {
|
|
8789
|
+
onInsert: (nextRun) => {
|
|
8790
|
+
const currentRun = runRef.current;
|
|
8791
|
+
if (!shouldSwitchRun(currentRun, nextRun)) return;
|
|
8792
|
+
setRun(nextRun);
|
|
8793
|
+
runRef.current = nextRun;
|
|
8794
|
+
if (!currentRun || currentRun.id !== nextRun.id) {
|
|
8795
|
+
lastSeqRef.current = 0;
|
|
8796
|
+
setEvents([]);
|
|
8797
|
+
void agentProgressRepository.listEvents(nextRun.id).then((initial) => {
|
|
8798
|
+
var _a2;
|
|
8799
|
+
if (((_a2 = runRef.current) == null ? void 0 : _a2.id) !== nextRun.id) return;
|
|
8800
|
+
setEvents((prev) => mergeMany(prev, initial));
|
|
8801
|
+
const maxSeq = initial.length > 0 ? initial[initial.length - 1].seq : 0;
|
|
8802
|
+
if (maxSeq > lastSeqRef.current) lastSeqRef.current = maxSeq;
|
|
8803
|
+
}).catch(() => {
|
|
8804
|
+
});
|
|
8805
|
+
}
|
|
8806
|
+
},
|
|
8807
|
+
onUpdate: (nextRun) => {
|
|
8808
|
+
const currentRun = runRef.current;
|
|
8809
|
+
if (!shouldSwitchRun(currentRun, nextRun)) return;
|
|
8810
|
+
setRun(nextRun);
|
|
8811
|
+
runRef.current = nextRun;
|
|
8812
|
+
}
|
|
8813
|
+
});
|
|
8814
|
+
return unsubRuns;
|
|
8815
|
+
}, [enabled, threadId, foregroundSignal]);
|
|
8816
|
+
React48.useEffect(() => {
|
|
8817
|
+
if (!enabled || !(run == null ? void 0 : run.id)) return;
|
|
8818
|
+
const runId = run.id;
|
|
8819
|
+
const processIncoming = (incoming) => {
|
|
8820
|
+
var _a2;
|
|
8821
|
+
if (((_a2 = runRef.current) == null ? void 0 : _a2.id) !== runId) return;
|
|
8822
|
+
setEvents((prev) => upsertBySeq(prev, incoming));
|
|
8823
|
+
if (incoming.seq > lastSeqRef.current) {
|
|
8824
|
+
const expectedNext = lastSeqRef.current + 1;
|
|
8825
|
+
const seenSeq = incoming.seq;
|
|
8826
|
+
const currentLast = lastSeqRef.current;
|
|
8827
|
+
lastSeqRef.current = seenSeq;
|
|
8828
|
+
if (seenSeq > expectedNext) {
|
|
8829
|
+
void agentProgressRepository.listEvents(runId, currentLast).then((missing) => {
|
|
8830
|
+
var _a3;
|
|
8831
|
+
if (((_a3 = runRef.current) == null ? void 0 : _a3.id) !== runId) return;
|
|
8832
|
+
setEvents((prev) => mergeMany(prev, missing));
|
|
8833
|
+
if (missing.length > 0) {
|
|
8834
|
+
const maxSeq = missing[missing.length - 1].seq;
|
|
8835
|
+
if (maxSeq > lastSeqRef.current) lastSeqRef.current = maxSeq;
|
|
8836
|
+
}
|
|
8837
|
+
}).catch(() => {
|
|
8838
|
+
});
|
|
8839
|
+
}
|
|
8840
|
+
}
|
|
8841
|
+
};
|
|
8842
|
+
const unsubscribe = agentProgressRepository.subscribeRunEvents(runId, {
|
|
8843
|
+
onInsert: processIncoming,
|
|
8844
|
+
onUpdate: processIncoming
|
|
8845
|
+
});
|
|
8846
|
+
return unsubscribe;
|
|
8847
|
+
}, [enabled, run == null ? void 0 : run.id, foregroundSignal]);
|
|
8848
|
+
const view = React48.useMemo(() => deriveView(run, events, Date.now()), [bundleTick, events, run]);
|
|
8849
|
+
React48.useEffect(() => {
|
|
8850
|
+
var _a2;
|
|
8851
|
+
if (!((_a2 = view.bundle) == null ? void 0 : _a2.active)) return;
|
|
8852
|
+
const interval = setInterval(() => {
|
|
8853
|
+
setBundleTick((v) => v + 1);
|
|
8854
|
+
}, 300);
|
|
8855
|
+
return () => clearInterval(interval);
|
|
8856
|
+
}, [(_a = view.bundle) == null ? void 0 : _a.active]);
|
|
8857
|
+
const hasLiveProgress = Boolean(run) && (run == null ? void 0 : run.status) === "running";
|
|
8858
|
+
return { run, view, loading, error, hasLiveProgress, refetch };
|
|
8859
|
+
}
|
|
8860
|
+
|
|
7905
8861
|
// src/studio/ComergeStudio.tsx
|
|
7906
|
-
var
|
|
8862
|
+
var import_jsx_runtime62 = require("react/jsx-runtime");
|
|
7907
8863
|
function ComergeStudio({
|
|
7908
8864
|
appId,
|
|
7909
8865
|
clientKey: clientKey2,
|
|
7910
8866
|
appKey = "MicroMain",
|
|
8867
|
+
analyticsEnabled,
|
|
7911
8868
|
onNavigateHome,
|
|
7912
8869
|
style,
|
|
7913
8870
|
showBubble = true,
|
|
8871
|
+
enableAgentProgress = true,
|
|
7914
8872
|
studioControlOptions,
|
|
7915
8873
|
embeddedBaseBundles
|
|
7916
8874
|
}) {
|
|
7917
|
-
const [activeAppId, setActiveAppId] =
|
|
7918
|
-
const [runtimeAppId, setRuntimeAppId] =
|
|
7919
|
-
const [pendingRuntimeTargetAppId, setPendingRuntimeTargetAppId] =
|
|
7920
|
-
const platform =
|
|
7921
|
-
|
|
8875
|
+
const [activeAppId, setActiveAppId] = React49.useState(appId);
|
|
8876
|
+
const [runtimeAppId, setRuntimeAppId] = React49.useState(appId);
|
|
8877
|
+
const [pendingRuntimeTargetAppId, setPendingRuntimeTargetAppId] = React49.useState(null);
|
|
8878
|
+
const platform = React49.useMemo(() => import_react_native60.Platform.OS === "ios" ? "ios" : "android", []);
|
|
8879
|
+
React49.useEffect(() => {
|
|
7922
8880
|
setActiveAppId(appId);
|
|
7923
8881
|
setRuntimeAppId(appId);
|
|
7924
8882
|
setPendingRuntimeTargetAppId(null);
|
|
7925
8883
|
}, [appId]);
|
|
7926
|
-
const captureTargetRef =
|
|
7927
|
-
return /* @__PURE__ */ (0,
|
|
7928
|
-
|
|
8884
|
+
const captureTargetRef = React49.useRef(null);
|
|
8885
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
8886
|
+
StudioBootstrap,
|
|
7929
8887
|
{
|
|
7930
|
-
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
runtimeAppId,
|
|
7934
|
-
|
|
7935
|
-
|
|
7936
|
-
|
|
7937
|
-
|
|
7938
|
-
|
|
7939
|
-
|
|
7940
|
-
|
|
7941
|
-
|
|
7942
|
-
|
|
7943
|
-
|
|
7944
|
-
|
|
8888
|
+
clientKey: clientKey2,
|
|
8889
|
+
analyticsEnabled,
|
|
8890
|
+
fallback: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_react_native60.View, { style: { flex: 1 } }),
|
|
8891
|
+
children: ({ userId }) => /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_bottom_sheet6.BottomSheetModalProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(LiquidGlassResetProvider, { resetTriggers: [appId, activeAppId, runtimeAppId], children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
8892
|
+
ComergeStudioInner,
|
|
8893
|
+
{
|
|
8894
|
+
userId,
|
|
8895
|
+
activeAppId,
|
|
8896
|
+
setActiveAppId,
|
|
8897
|
+
runtimeAppId,
|
|
8898
|
+
setRuntimeAppId,
|
|
8899
|
+
pendingRuntimeTargetAppId,
|
|
8900
|
+
setPendingRuntimeTargetAppId,
|
|
8901
|
+
appKey,
|
|
8902
|
+
platform,
|
|
8903
|
+
onNavigateHome,
|
|
8904
|
+
captureTargetRef,
|
|
8905
|
+
style,
|
|
8906
|
+
showBubble,
|
|
8907
|
+
enableAgentProgress,
|
|
8908
|
+
studioControlOptions,
|
|
8909
|
+
embeddedBaseBundles
|
|
8910
|
+
}
|
|
8911
|
+
) }) })
|
|
7945
8912
|
}
|
|
7946
|
-
)
|
|
8913
|
+
);
|
|
7947
8914
|
}
|
|
7948
8915
|
function ComergeStudioInner({
|
|
7949
8916
|
userId,
|
|
@@ -7959,17 +8926,19 @@ function ComergeStudioInner({
|
|
|
7959
8926
|
captureTargetRef,
|
|
7960
8927
|
style,
|
|
7961
8928
|
showBubble,
|
|
8929
|
+
enableAgentProgress,
|
|
7962
8930
|
studioControlOptions,
|
|
7963
8931
|
embeddedBaseBundles
|
|
7964
8932
|
}) {
|
|
8933
|
+
var _a;
|
|
7965
8934
|
const { app, loading: appLoading } = useApp(activeAppId);
|
|
7966
8935
|
const { app: runtimeAppFromHook } = useApp(runtimeAppId, { enabled: runtimeAppId !== activeAppId });
|
|
7967
8936
|
const runtimeApp = runtimeAppId === activeAppId ? app : runtimeAppFromHook;
|
|
7968
|
-
const sawEditingOnPendingTargetRef =
|
|
7969
|
-
|
|
8937
|
+
const sawEditingOnPendingTargetRef = React49.useRef(false);
|
|
8938
|
+
React49.useEffect(() => {
|
|
7970
8939
|
sawEditingOnPendingTargetRef.current = false;
|
|
7971
8940
|
}, [pendingRuntimeTargetAppId]);
|
|
7972
|
-
|
|
8941
|
+
React49.useEffect(() => {
|
|
7973
8942
|
if (!pendingRuntimeTargetAppId) return;
|
|
7974
8943
|
if (activeAppId !== pendingRuntimeTargetAppId) return;
|
|
7975
8944
|
if ((app == null ? void 0 : app.status) === "editing") {
|
|
@@ -7987,13 +8956,13 @@ function ComergeStudioInner({
|
|
|
7987
8956
|
canRequestLatest: (runtimeApp == null ? void 0 : runtimeApp.status) === "ready",
|
|
7988
8957
|
embeddedBaseBundles
|
|
7989
8958
|
});
|
|
7990
|
-
const sawEditingOnActiveAppRef =
|
|
7991
|
-
const [showPostEditPreparing, setShowPostEditPreparing] =
|
|
7992
|
-
|
|
8959
|
+
const sawEditingOnActiveAppRef = React49.useRef(false);
|
|
8960
|
+
const [showPostEditPreparing, setShowPostEditPreparing] = React49.useState(false);
|
|
8961
|
+
React49.useEffect(() => {
|
|
7993
8962
|
sawEditingOnActiveAppRef.current = false;
|
|
7994
8963
|
setShowPostEditPreparing(false);
|
|
7995
8964
|
}, [activeAppId]);
|
|
7996
|
-
|
|
8965
|
+
React49.useEffect(() => {
|
|
7997
8966
|
if (!(app == null ? void 0 : app.id)) return;
|
|
7998
8967
|
if (app.status === "editing") {
|
|
7999
8968
|
sawEditingOnActiveAppRef.current = true;
|
|
@@ -8005,7 +8974,7 @@ function ComergeStudioInner({
|
|
|
8005
8974
|
sawEditingOnActiveAppRef.current = false;
|
|
8006
8975
|
}
|
|
8007
8976
|
}, [app == null ? void 0 : app.id, app == null ? void 0 : app.status]);
|
|
8008
|
-
|
|
8977
|
+
React49.useEffect(() => {
|
|
8009
8978
|
if (!showPostEditPreparing) return;
|
|
8010
8979
|
const stillProcessingBaseBundle = bundle.loading && bundle.loadingMode === "base" && !bundle.isTesting;
|
|
8011
8980
|
if (!stillProcessingBaseBundle) {
|
|
@@ -8015,20 +8984,21 @@ function ComergeStudioInner({
|
|
|
8015
8984
|
const threadId = (app == null ? void 0 : app.threadId) ?? "";
|
|
8016
8985
|
const thread = useThreadMessages(threadId);
|
|
8017
8986
|
const editQueue = useEditQueue(activeAppId);
|
|
8987
|
+
const agentProgress = useAgentRunProgress(threadId, { enabled: enableAgentProgress });
|
|
8018
8988
|
const editQueueActions = useEditQueueActions(activeAppId);
|
|
8019
|
-
const [lastEditQueueInfo, setLastEditQueueInfo] =
|
|
8020
|
-
const lastEditQueueInfoRef =
|
|
8021
|
-
const [suppressQueueUntilResponse, setSuppressQueueUntilResponse] =
|
|
8989
|
+
const [lastEditQueueInfo, setLastEditQueueInfo] = React49.useState(null);
|
|
8990
|
+
const lastEditQueueInfoRef = React49.useRef(null);
|
|
8991
|
+
const [suppressQueueUntilResponse, setSuppressQueueUntilResponse] = React49.useState(false);
|
|
8022
8992
|
const mergeRequests = useMergeRequests({ appId: activeAppId });
|
|
8023
|
-
const hasOpenOutgoingMr =
|
|
8993
|
+
const hasOpenOutgoingMr = React49.useMemo(() => {
|
|
8024
8994
|
return mergeRequests.lists.outgoing.some((mr) => mr.status === "open");
|
|
8025
8995
|
}, [mergeRequests.lists.outgoing]);
|
|
8026
|
-
const incomingReviewMrs =
|
|
8996
|
+
const incomingReviewMrs = React49.useMemo(() => {
|
|
8027
8997
|
if (!userId) return mergeRequests.lists.incoming;
|
|
8028
8998
|
return mergeRequests.lists.incoming.filter((mr) => mr.createdBy !== userId);
|
|
8029
8999
|
}, [mergeRequests.lists.incoming, userId]);
|
|
8030
9000
|
const uploader = useAttachmentUpload();
|
|
8031
|
-
const updateLastEditQueueInfo =
|
|
9001
|
+
const updateLastEditQueueInfo = React49.useCallback(
|
|
8032
9002
|
(info) => {
|
|
8033
9003
|
lastEditQueueInfoRef.current = info;
|
|
8034
9004
|
setLastEditQueueInfo(info);
|
|
@@ -8062,32 +9032,35 @@ function ComergeStudioInner({
|
|
|
8062
9032
|
}
|
|
8063
9033
|
},
|
|
8064
9034
|
onEditFinished: () => {
|
|
8065
|
-
var
|
|
8066
|
-
if (((
|
|
9035
|
+
var _a2;
|
|
9036
|
+
if (((_a2 = lastEditQueueInfoRef.current) == null ? void 0 : _a2.queuePosition) !== 1) {
|
|
8067
9037
|
setSuppressQueueUntilResponse(false);
|
|
8068
9038
|
}
|
|
8069
9039
|
}
|
|
8070
9040
|
});
|
|
8071
9041
|
const chatSendDisabled = false;
|
|
8072
|
-
const [processingMrId, setProcessingMrId] =
|
|
8073
|
-
const [testingMrId, setTestingMrId] =
|
|
8074
|
-
const [syncingUpstream, setSyncingUpstream] =
|
|
8075
|
-
const [upstreamSyncStatus, setUpstreamSyncStatus] =
|
|
9042
|
+
const [processingMrId, setProcessingMrId] = React49.useState(null);
|
|
9043
|
+
const [testingMrId, setTestingMrId] = React49.useState(null);
|
|
9044
|
+
const [syncingUpstream, setSyncingUpstream] = React49.useState(false);
|
|
9045
|
+
const [upstreamSyncStatus, setUpstreamSyncStatus] = React49.useState(null);
|
|
8076
9046
|
const isMrTestBuildInProgress = bundle.loading && bundle.loadingMode === "test";
|
|
8077
9047
|
const isBaseBundleDownloading = bundle.loading && bundle.loadingMode === "base" && !bundle.isTesting;
|
|
8078
|
-
const
|
|
8079
|
-
|
|
9048
|
+
const runtimePreparingText = bundle.bundleStatus === "pending" ? "Bundling app\u2026 this may take a few minutes" : "Preparing app\u2026";
|
|
9049
|
+
const chatShowTypingIndicator = React49.useMemo(() => {
|
|
9050
|
+
var _a2;
|
|
9051
|
+
if (agentProgress.hasLiveProgress) return false;
|
|
8080
9052
|
if (!thread.raw || thread.raw.length === 0) return false;
|
|
8081
9053
|
const last = thread.raw[thread.raw.length - 1];
|
|
8082
|
-
const payloadType = typeof ((
|
|
9054
|
+
const payloadType = typeof ((_a2 = last.payload) == null ? void 0 : _a2.type) === "string" ? String(last.payload.type) : void 0;
|
|
8083
9055
|
return payloadType !== "outcome";
|
|
8084
|
-
}, [thread.raw]);
|
|
8085
|
-
|
|
9056
|
+
}, [agentProgress.hasLiveProgress, thread.raw]);
|
|
9057
|
+
const showChatProgress = agentProgress.hasLiveProgress || Boolean((_a = agentProgress.view.bundle) == null ? void 0 : _a.active);
|
|
9058
|
+
React49.useEffect(() => {
|
|
8086
9059
|
updateLastEditQueueInfo(null);
|
|
8087
9060
|
setSuppressQueueUntilResponse(false);
|
|
8088
9061
|
setUpstreamSyncStatus(null);
|
|
8089
9062
|
}, [activeAppId, updateLastEditQueueInfo]);
|
|
8090
|
-
const handleSyncUpstream =
|
|
9063
|
+
const handleSyncUpstream = React49.useCallback(async () => {
|
|
8091
9064
|
if (!(app == null ? void 0 : app.id)) {
|
|
8092
9065
|
throw new Error("Missing app");
|
|
8093
9066
|
}
|
|
@@ -8100,7 +9073,7 @@ function ComergeStudioInner({
|
|
|
8100
9073
|
setSyncingUpstream(false);
|
|
8101
9074
|
}
|
|
8102
9075
|
}, [activeAppId, app == null ? void 0 : app.id]);
|
|
8103
|
-
|
|
9076
|
+
React49.useEffect(() => {
|
|
8104
9077
|
if (!(lastEditQueueInfo == null ? void 0 : lastEditQueueInfo.queueItemId)) return;
|
|
8105
9078
|
const stillPresent = editQueue.items.some((item) => item.id === lastEditQueueInfo.queueItemId);
|
|
8106
9079
|
if (!stillPresent) {
|
|
@@ -8108,31 +9081,32 @@ function ComergeStudioInner({
|
|
|
8108
9081
|
setSuppressQueueUntilResponse(false);
|
|
8109
9082
|
}
|
|
8110
9083
|
}, [editQueue.items, lastEditQueueInfo == null ? void 0 : lastEditQueueInfo.queueItemId]);
|
|
8111
|
-
const chatQueueItems =
|
|
8112
|
-
var
|
|
9084
|
+
const chatQueueItems = React49.useMemo(() => {
|
|
9085
|
+
var _a2;
|
|
8113
9086
|
if (suppressQueueUntilResponse && editQueue.items.length <= 1) {
|
|
8114
9087
|
return [];
|
|
8115
9088
|
}
|
|
8116
9089
|
if (!lastEditQueueInfo || lastEditQueueInfo.queuePosition !== 1 || !lastEditQueueInfo.queueItemId) {
|
|
8117
9090
|
return editQueue.items;
|
|
8118
9091
|
}
|
|
8119
|
-
if (editQueue.items.length === 1 && ((
|
|
9092
|
+
if (editQueue.items.length === 1 && ((_a2 = editQueue.items[0]) == null ? void 0 : _a2.id) === lastEditQueueInfo.queueItemId) {
|
|
8120
9093
|
return [];
|
|
8121
9094
|
}
|
|
8122
9095
|
return editQueue.items;
|
|
8123
9096
|
}, [editQueue.items, lastEditQueueInfo, suppressQueueUntilResponse]);
|
|
8124
|
-
return /* @__PURE__ */ (0,
|
|
8125
|
-
/* @__PURE__ */ (0,
|
|
9097
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_react_native60.View, { style: [{ flex: 1 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(import_react_native60.View, { ref: captureTargetRef, style: { flex: 1 }, collapsable: false, children: [
|
|
9098
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
8126
9099
|
RuntimeRenderer,
|
|
8127
9100
|
{
|
|
8128
9101
|
appKey,
|
|
8129
9102
|
bundlePath: bundle.bundlePath,
|
|
9103
|
+
preparingText: runtimePreparingText,
|
|
8130
9104
|
forcePreparing: showPostEditPreparing,
|
|
8131
9105
|
renderToken: bundle.renderToken,
|
|
8132
9106
|
allowInitialPreparing: !embeddedBaseBundles
|
|
8133
9107
|
}
|
|
8134
9108
|
),
|
|
8135
|
-
/* @__PURE__ */ (0,
|
|
9109
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
8136
9110
|
StudioOverlay,
|
|
8137
9111
|
{
|
|
8138
9112
|
captureTargetRef,
|
|
@@ -8191,6 +9165,7 @@ function ComergeStudioInner({
|
|
|
8191
9165
|
onSendChat: (text, attachments) => actions.sendEdit({ prompt: text, attachments }),
|
|
8192
9166
|
chatQueueItems,
|
|
8193
9167
|
onRemoveQueueItem: (id) => editQueueActions.cancel(id),
|
|
9168
|
+
chatProgress: showChatProgress ? agentProgress.view : null,
|
|
8194
9169
|
onNavigateHome,
|
|
8195
9170
|
showBubble,
|
|
8196
9171
|
studioControlOptions
|