@comergehq/studio 0.1.27 → 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.js CHANGED
@@ -38,11 +38,11 @@ module.exports = __toCommonJS(index_exports);
38
38
 
39
39
  // src/studio/ComergeStudio.tsx
40
40
  var React49 = __toESM(require("react"));
41
- var import_react_native59 = require("react-native");
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 import_react_native3 = require("react-native");
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 requireAuth = isSupabaseClientInjected();
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({ children, fallback, renderError, clientKey: clientKey2 }) {
349
- const { ready, error, userId } = useStudioBootstrap({ clientKey: clientKey2 });
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)(import_react_native3.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 }) });
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)(import_react_native3.View, { style: { flex: 1, justifyContent: "center", alignItems: "center", padding: 24 }, children: fallback ?? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { variant: "bodyMuted", children: "Loading\u2026" }) });
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 import_react_native4 = require("react-native");
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(import_react_native4.AppState.currentState);
939
+ const lastStateRef = React2.useRef(import_react_native5.AppState.currentState);
849
940
  React2.useEffect(() => {
850
941
  if (!enabled) return;
851
- const sub = import_react_native4.AppState.addEventListener("change", (nextState) => {
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));
@@ -1759,7 +1998,22 @@ function useBundleManager({
1759
1998
  await load(baseRef.current, "base");
1760
1999
  }, [load]);
1761
2000
  const loadTest = React5.useCallback(async (src) => {
1762
- await load(src, "test");
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
+ }
1763
2017
  }, [load]);
1764
2018
  const restoreBase = React5.useCallback(async () => {
1765
2019
  const src = baseRef.current;
@@ -1997,24 +2251,68 @@ function useMergeRequests(params) {
1997
2251
  }, [appId]);
1998
2252
  React6.useEffect(() => {
1999
2253
  void refresh();
2000
- }, [refresh]);
2254
+ }, [appId, refresh]);
2001
2255
  const openMergeRequest = React6.useCallback(async (sourceAppId) => {
2002
- const mr = await mergeRequestsRepository.open({ sourceAppId });
2003
- await refresh();
2004
- return mr;
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
+ }
2005
2273
  }, [refresh]);
2006
2274
  const approve = React6.useCallback(async (mrId) => {
2007
- const mr = await mergeRequestsRepository.update(mrId, { status: "approved" });
2008
- await refresh();
2009
- const merged = await pollUntilMerged(mrId);
2010
- await refresh();
2011
- return merged ?? mr;
2012
- }, [pollUntilMerged, refresh]);
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]);
2013
2296
  const reject = React6.useCallback(async (mrId) => {
2014
- const mr = await mergeRequestsRepository.update(mrId, { status: "rejected" });
2015
- await refresh();
2016
- return mr;
2017
- }, [refresh]);
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]);
2018
2316
  const toSummary = React6.useCallback((mr) => {
2019
2317
  const stats = creatorStatsById[mr.createdBy];
2020
2318
  return {
@@ -2050,7 +2348,7 @@ function useMergeRequests(params) {
2050
2348
 
2051
2349
  // src/studio/hooks/useAttachmentUpload.ts
2052
2350
  var React7 = __toESM(require("react"));
2053
- var import_react_native5 = require("react-native");
2351
+ var import_react_native6 = require("react-native");
2054
2352
  var FileSystem2 = __toESM(require("expo-file-system/legacy"));
2055
2353
 
2056
2354
  // src/data/attachment/remote.ts
@@ -2137,7 +2435,7 @@ function useAttachmentUpload() {
2137
2435
  const blobs = await Promise.all(
2138
2436
  dataUrls.map(async (dataUrl, idx) => {
2139
2437
  const normalized = dataUrl.startsWith("data:") ? dataUrl : `data:image/png;base64,${dataUrl}`;
2140
- const blob = import_react_native5.Platform.OS === "android" ? await dataUrlToBlobAndroid(normalized) : await (await fetch(normalized)).blob();
2438
+ const blob = import_react_native6.Platform.OS === "android" ? await dataUrlToBlobAndroid(normalized) : await (await fetch(normalized)).blob();
2141
2439
  const mimeType = getMimeTypeFromDataUrl(normalized);
2142
2440
  return { blob, idx, mimeType };
2143
2441
  })
@@ -2255,13 +2553,21 @@ function useStudioActions({
2255
2553
  if (sending) return;
2256
2554
  setSending(true);
2257
2555
  setError(null);
2556
+ let forkSucceeded = false;
2258
2557
  try {
2259
2558
  let targetApp = app;
2559
+ const sourceAppId = app.id;
2260
2560
  if (shouldForkOnEdit) {
2261
2561
  setForking(true);
2262
- const sourceAppId = app.id;
2263
2562
  const forked = await appsRepository.fork(app.id, {});
2264
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;
2265
2571
  onForkedApp == null ? void 0 : onForkedApp(forked.id, { keepRenderingAppId: sourceAppId });
2266
2572
  }
2267
2573
  setForking(false);
@@ -2289,9 +2595,33 @@ function useStudioActions({
2289
2595
  queueItemId: editResult.queueItemId ?? null,
2290
2596
  queuePosition: editResult.queuePosition ?? null
2291
2597
  });
2598
+ await trackEditApp({
2599
+ appId: targetApp.id,
2600
+ threadId,
2601
+ promptLength: prompt.trim().length,
2602
+ success: true
2603
+ });
2292
2604
  } catch (e) {
2293
2605
  const err = e instanceof Error ? e : new Error(String(e));
2294
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
+ }
2295
2625
  throw err;
2296
2626
  } finally {
2297
2627
  setForking(false);
@@ -2306,7 +2636,7 @@ function useStudioActions({
2306
2636
 
2307
2637
  // src/studio/ui/RuntimeRenderer.tsx
2308
2638
  var React9 = __toESM(require("react"));
2309
- var import_react_native6 = require("react-native");
2639
+ var import_react_native7 = require("react-native");
2310
2640
  var import_runtime = require("@comergehq/runtime");
2311
2641
  var import_jsx_runtime3 = require("react/jsx-runtime");
2312
2642
  function RuntimeRenderer({
@@ -2326,11 +2656,11 @@ function RuntimeRenderer({
2326
2656
  }, [bundlePath]);
2327
2657
  if (!bundlePath || forcePreparing) {
2328
2658
  if (!hasRenderedOnce && !forcePreparing && !allowInitialPreparing) {
2329
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native6.View, { style: [{ flex: 1 }, style] });
2659
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native7.View, { style: [{ flex: 1 }, style] });
2330
2660
  }
2331
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native6.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" }) });
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" }) });
2332
2662
  }
2333
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native6.View, { style: [{ flex: 1 }, style], children: /* @__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)(
2334
2664
  import_runtime.ComergeRuntimeRenderer,
2335
2665
  {
2336
2666
  appKey,
@@ -2343,16 +2673,16 @@ function RuntimeRenderer({
2343
2673
 
2344
2674
  // src/studio/ui/StudioOverlay.tsx
2345
2675
  var React45 = __toESM(require("react"));
2346
- var import_react_native58 = require("react-native");
2676
+ var import_react_native59 = require("react-native");
2347
2677
 
2348
2678
  // src/components/studio-sheet/StudioBottomSheet.tsx
2349
2679
  var React12 = __toESM(require("react"));
2350
- var import_react_native9 = require("react-native");
2680
+ var import_react_native10 = require("react-native");
2351
2681
  var import_bottom_sheet = require("@gorhom/bottom-sheet");
2352
2682
  var import_react_native_safe_area_context = require("react-native-safe-area-context");
2353
2683
 
2354
2684
  // src/components/studio-sheet/StudioSheetBackground.tsx
2355
- var import_react_native8 = require("react-native");
2685
+ var import_react_native9 = require("react-native");
2356
2686
  var import_liquid_glass2 = require("@callstack/liquid-glass");
2357
2687
 
2358
2688
  // src/components/utils/ResettableLiquidGlassView.tsx
@@ -2361,7 +2691,7 @@ var import_liquid_glass = require("@callstack/liquid-glass");
2361
2691
 
2362
2692
  // src/components/utils/liquidGlassReset.tsx
2363
2693
  var React10 = __toESM(require("react"));
2364
- var import_react_native7 = require("react-native");
2694
+ var import_react_native8 = require("react-native");
2365
2695
  var import_jsx_runtime4 = require("react/jsx-runtime");
2366
2696
  var LiquidGlassResetContext = React10.createContext(0);
2367
2697
  function LiquidGlassResetProvider({
@@ -2370,11 +2700,11 @@ function LiquidGlassResetProvider({
2370
2700
  }) {
2371
2701
  const [token, setToken] = React10.useState(0);
2372
2702
  React10.useEffect(() => {
2373
- if (import_react_native7.Platform.OS !== "ios") return;
2703
+ if (import_react_native8.Platform.OS !== "ios") return;
2374
2704
  const onChange = (state) => {
2375
2705
  if (state === "active") setToken((t) => t + 1);
2376
2706
  };
2377
- const sub = import_react_native7.AppState.addEventListener("change", onChange);
2707
+ const sub = import_react_native8.AppState.addEventListener("change", onChange);
2378
2708
  return () => sub.remove();
2379
2709
  }, []);
2380
2710
  React10.useEffect(() => {
@@ -2411,7 +2741,7 @@ function StudioSheetBackground({
2411
2741
  renderBackground
2412
2742
  }) {
2413
2743
  const theme = useTheme();
2414
- const radius = import_react_native8.Platform.OS === "ios" ? 39 : 16;
2744
+ const radius = import_react_native9.Platform.OS === "ios" ? 39 : 16;
2415
2745
  const fallbackBgColor = theme.scheme === "dark" ? "rgba(11, 8, 15, 0.85)" : "rgba(255, 255, 255, 0.85)";
2416
2746
  const secondaryBgBaseColor = theme.scheme === "dark" ? "rgb(24, 24, 27)" : "rgb(173, 173, 173)";
2417
2747
  const containerStyle = {
@@ -2432,7 +2762,7 @@ function StudioSheetBackground({
2432
2762
  }
2433
2763
  ),
2434
2764
  import_liquid_glass2.isLiquidGlassSupported && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2435
- import_react_native8.View,
2765
+ import_react_native9.View,
2436
2766
  {
2437
2767
  style: [
2438
2768
  containerStyle,
@@ -2469,12 +2799,12 @@ function StudioBottomSheet({
2469
2799
  const resolvedSheetRef = sheetRef ?? internalSheetRef;
2470
2800
  const resolvedSnapPoints = React12.useMemo(() => [...snapPoints], [snapPoints]);
2471
2801
  const currentIndexRef = React12.useRef(open ? resolvedSnapPoints.length - 1 : -1);
2472
- const lastAppStateRef = React12.useRef(import_react_native9.AppState.currentState);
2802
+ const lastAppStateRef = React12.useRef(import_react_native10.AppState.currentState);
2473
2803
  React12.useEffect(() => {
2474
- const sub = import_react_native9.AppState.addEventListener("change", (state) => {
2804
+ const sub = import_react_native10.AppState.addEventListener("change", (state) => {
2475
2805
  lastAppStateRef.current = state;
2476
2806
  if (state === "background" || state === "inactive") {
2477
- import_react_native9.Keyboard.dismiss();
2807
+ import_react_native10.Keyboard.dismiss();
2478
2808
  return;
2479
2809
  }
2480
2810
  });
@@ -2515,19 +2845,19 @@ function StudioBottomSheet({
2515
2845
  ...bottomSheetProps,
2516
2846
  onChange: handleChange,
2517
2847
  onDismiss: () => onOpenChange == null ? void 0 : onOpenChange(false),
2518
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native9.View, { style: { flex: 1, overflow: "hidden" }, children })
2848
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native10.View, { style: { flex: 1, overflow: "hidden" }, children })
2519
2849
  }
2520
2850
  );
2521
2851
  }
2522
2852
 
2523
2853
  // src/components/studio-sheet/StudioSheetPager.tsx
2524
2854
  var React13 = __toESM(require("react"));
2525
- var import_react_native10 = require("react-native");
2855
+ var import_react_native11 = require("react-native");
2526
2856
  var import_jsx_runtime8 = require("react/jsx-runtime");
2527
2857
  function StudioSheetPager({ activePage, width, preview, chat, style }) {
2528
- const anim = React13.useRef(new import_react_native10.Animated.Value(activePage === "chat" ? 1 : 0)).current;
2858
+ const anim = React13.useRef(new import_react_native11.Animated.Value(activePage === "chat" ? 1 : 0)).current;
2529
2859
  React13.useEffect(() => {
2530
- import_react_native10.Animated.spring(anim, {
2860
+ import_react_native11.Animated.spring(anim, {
2531
2861
  toValue: activePage === "chat" ? 1 : 0,
2532
2862
  useNativeDriver: true,
2533
2863
  tension: 65,
@@ -2536,9 +2866,9 @@ function StudioSheetPager({ activePage, width, preview, chat, style }) {
2536
2866
  }, [activePage, anim]);
2537
2867
  const previewTranslateX = anim.interpolate({ inputRange: [0, 1], outputRange: [0, -width] });
2538
2868
  const chatTranslateX = anim.interpolate({ inputRange: [0, 1], outputRange: [width, 0] });
2539
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native10.Animated.View, { style: [{ flex: 1 }, style], children: [
2869
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native11.Animated.View, { style: [{ flex: 1 }, style], children: [
2540
2870
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2541
- import_react_native10.Animated.View,
2871
+ import_react_native11.Animated.View,
2542
2872
  {
2543
2873
  style: [
2544
2874
  {
@@ -2555,7 +2885,7 @@ function StudioSheetPager({ activePage, width, preview, chat, style }) {
2555
2885
  }
2556
2886
  ),
2557
2887
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2558
- import_react_native10.Animated.View,
2888
+ import_react_native11.Animated.View,
2559
2889
  {
2560
2890
  style: [
2561
2891
  {
@@ -2576,7 +2906,7 @@ function StudioSheetPager({ activePage, width, preview, chat, style }) {
2576
2906
 
2577
2907
  // src/components/bubble/Bubble.tsx
2578
2908
  var import_react = require("react");
2579
- var import_react_native11 = require("react-native");
2909
+ var import_react_native12 = require("react-native");
2580
2910
  var Haptics = __toESM(require("expo-haptics"));
2581
2911
  var import_react_native_reanimated = __toESM(require("react-native-reanimated"));
2582
2912
  var import_liquid_glass3 = require("@callstack/liquid-glass");
@@ -2648,7 +2978,7 @@ function Bubble({
2648
2978
  backgroundColor
2649
2979
  }) {
2650
2980
  const theme = useTheme();
2651
- const { width, height } = (0, import_react_native11.useWindowDimensions)();
2981
+ const { width, height } = (0, import_react_native12.useWindowDimensions)();
2652
2982
  const isDanger = variant === "danger";
2653
2983
  const onPressRef = (0, import_react.useRef)(onPress);
2654
2984
  (0, import_react.useEffect)(() => {
@@ -2741,7 +3071,7 @@ function Bubble({
2741
3071
  }
2742
3072
  }, [forceShowTrigger, visible, animateIn]);
2743
3073
  const panResponder = (0, import_react.useRef)(
2744
- import_react_native11.PanResponder.create({
3074
+ import_react_native12.PanResponder.create({
2745
3075
  onStartShouldSetPanResponder: () => true,
2746
3076
  onMoveShouldSetPanResponder: () => true,
2747
3077
  onPanResponderGrant: () => {
@@ -2804,24 +3134,24 @@ function Bubble({
2804
3134
  interactive: true,
2805
3135
  effect: "clear",
2806
3136
  children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2807
- import_react_native11.Pressable,
3137
+ import_react_native12.Pressable,
2808
3138
  {
2809
3139
  onPress: () => {
2810
3140
  if (!disabled) animateOut();
2811
3141
  },
2812
3142
  style: styles.buttonInner,
2813
3143
  android_ripple: { color: "rgba(255, 255, 255, 0.3)", borderless: true },
2814
- children: children ?? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native11.View, {})
3144
+ children: children ?? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native12.View, {})
2815
3145
  }
2816
3146
  )
2817
3147
  }
2818
3148
  ) }),
2819
- badgeCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native11.View, { style: [styles.badge, { backgroundColor: theme.colors.danger }], children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native11.Text, { style: [styles.badgeText, { color: theme.colors.onDanger }], children: badgeCount > 99 ? "99+" : badgeCount }) })
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 }) })
2820
3150
  ]
2821
3151
  }
2822
3152
  );
2823
3153
  }
2824
- var styles = import_react_native11.StyleSheet.create({
3154
+ var styles = import_react_native12.StyleSheet.create({
2825
3155
  floatingButton: {
2826
3156
  position: "absolute",
2827
3157
  justifyContent: "center",
@@ -2858,7 +3188,7 @@ var styles = import_react_native11.StyleSheet.create({
2858
3188
 
2859
3189
  // src/components/overlays/EdgeGlowFrame.tsx
2860
3190
  var React14 = __toESM(require("react"));
2861
- var import_react_native12 = require("react-native");
3191
+ var import_react_native13 = require("react-native");
2862
3192
  var import_expo_linear_gradient = require("expo-linear-gradient");
2863
3193
  var import_jsx_runtime10 = require("react/jsx-runtime");
2864
3194
  function baseColor(role, theme) {
@@ -2883,9 +3213,9 @@ function EdgeGlowFrame({
2883
3213
  }) {
2884
3214
  const theme = useTheme();
2885
3215
  const alpha = Math.max(0, Math.min(1, intensity));
2886
- const anim = React14.useRef(new import_react_native12.Animated.Value(visible ? 1 : 0)).current;
3216
+ const anim = React14.useRef(new import_react_native13.Animated.Value(visible ? 1 : 0)).current;
2887
3217
  React14.useEffect(() => {
2888
- import_react_native12.Animated.timing(anim, {
3218
+ import_react_native13.Animated.timing(anim, {
2889
3219
  toValue: visible ? 1 : 0,
2890
3220
  duration: 300,
2891
3221
  useNativeDriver: true
@@ -2894,8 +3224,8 @@ function EdgeGlowFrame({
2894
3224
  const c = baseColor(role, theme);
2895
3225
  const strong = withAlpha(c, 0.6 * alpha);
2896
3226
  const soft = withAlpha(c, 0.22 * alpha);
2897
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native12.Animated.View, { pointerEvents: "none", style: [{ position: "absolute", inset: 0, opacity: anim }, style], children: [
2898
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native12.View, { style: { position: "absolute", top: 0, left: 0, right: 0, height: thickness }, children: /* @__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)(
2899
3229
  import_expo_linear_gradient.LinearGradient,
2900
3230
  {
2901
3231
  colors: [strong, soft, "transparent"],
@@ -2904,7 +3234,7 @@ function EdgeGlowFrame({
2904
3234
  style: { width: "100%", height: "100%" }
2905
3235
  }
2906
3236
  ) }),
2907
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native12.View, { style: { position: "absolute", bottom: 0, left: 0, right: 0, height: thickness }, children: /* @__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)(
2908
3238
  import_expo_linear_gradient.LinearGradient,
2909
3239
  {
2910
3240
  colors: ["transparent", soft, strong],
@@ -2913,7 +3243,7 @@ function EdgeGlowFrame({
2913
3243
  style: { width: "100%", height: "100%" }
2914
3244
  }
2915
3245
  ) }),
2916
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native12.View, { style: { position: "absolute", top: 0, bottom: 0, left: 0, width: thickness }, children: /* @__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)(
2917
3247
  import_expo_linear_gradient.LinearGradient,
2918
3248
  {
2919
3249
  colors: [strong, soft, "transparent"],
@@ -2922,7 +3252,7 @@ function EdgeGlowFrame({
2922
3252
  style: { width: "100%", height: "100%" }
2923
3253
  }
2924
3254
  ) }),
2925
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native12.View, { style: { position: "absolute", top: 0, bottom: 0, right: 0, width: thickness }, children: /* @__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)(
2926
3256
  import_expo_linear_gradient.LinearGradient,
2927
3257
  {
2928
3258
  colors: ["transparent", soft, strong],
@@ -2936,12 +3266,12 @@ function EdgeGlowFrame({
2936
3266
 
2937
3267
  // src/components/draw/DrawModeOverlay.tsx
2938
3268
  var React17 = __toESM(require("react"));
2939
- var import_react_native16 = require("react-native");
3269
+ var import_react_native17 = require("react-native");
2940
3270
  var import_react_native_view_shot = require("react-native-view-shot");
2941
3271
 
2942
3272
  // src/components/draw/DrawSurface.tsx
2943
3273
  var React15 = __toESM(require("react"));
2944
- var import_react_native13 = require("react-native");
3274
+ var import_react_native14 = require("react-native");
2945
3275
  var import_react_native_svg = __toESM(require("react-native-svg"));
2946
3276
 
2947
3277
  // src/components/draw/strokes.ts
@@ -3012,7 +3342,7 @@ function DrawSurface({
3012
3342
  triggerRender();
3013
3343
  }, [color, onAddStroke, strokeWidth, triggerRender]);
3014
3344
  const panResponder = React15.useMemo(
3015
- () => import_react_native13.PanResponder.create({
3345
+ () => import_react_native14.PanResponder.create({
3016
3346
  onStartShouldSetPanResponder: () => true,
3017
3347
  onMoveShouldSetPanResponder: () => true,
3018
3348
  onPanResponderGrant: onStart,
@@ -3024,7 +3354,7 @@ function DrawSurface({
3024
3354
  );
3025
3355
  const currentPath = pointsToSmoothPath(currentPointsRef.current);
3026
3356
  void renderTick;
3027
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native13.View, { style: [import_react_native13.StyleSheet.absoluteFill, styles2.container, style], ...panResponder.panHandlers, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native_svg.default, { style: import_react_native13.StyleSheet.absoluteFill, width: "100%", height: "100%", children: [
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: [
3028
3358
  strokes.map((s, idx) => {
3029
3359
  const d = pointsToSmoothPath(s.points);
3030
3360
  if (!d) return null;
@@ -3054,7 +3384,7 @@ function DrawSurface({
3054
3384
  ) : null
3055
3385
  ] }) });
3056
3386
  }
3057
- var styles2 = import_react_native13.StyleSheet.create({
3387
+ var styles2 = import_react_native14.StyleSheet.create({
3058
3388
  container: {
3059
3389
  zIndex: 5
3060
3390
  }
@@ -3062,7 +3392,7 @@ var styles2 = import_react_native13.StyleSheet.create({
3062
3392
 
3063
3393
  // src/components/draw/DrawToolbar.tsx
3064
3394
  var React16 = __toESM(require("react"));
3065
- var import_react_native15 = require("react-native");
3395
+ var import_react_native16 = require("react-native");
3066
3396
  var import_react_native_safe_area_context2 = require("react-native-safe-area-context");
3067
3397
  var import_lucide_react_native = require("lucide-react-native");
3068
3398
 
@@ -3081,7 +3411,7 @@ async function impact(style) {
3081
3411
  }
3082
3412
 
3083
3413
  // src/components/draw/DrawColorPicker.tsx
3084
- var import_react_native14 = require("react-native");
3414
+ var import_react_native15 = require("react-native");
3085
3415
  var import_jsx_runtime12 = require("react/jsx-runtime");
3086
3416
  function DrawColorPicker({
3087
3417
  colors,
@@ -3116,10 +3446,10 @@ function DrawColorPicker({
3116
3446
  return { ...base, ...selectedStyle, ...whiteStyle };
3117
3447
  };
3118
3448
  if (!expanded) {
3119
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native14.Pressable, { onPress: onToggle, style: [swatchStyle(selected, true), style] });
3449
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native15.Pressable, { onPress: onToggle, style: [swatchStyle(selected, true), style] });
3120
3450
  }
3121
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native14.View, { style: [{ flexDirection: "row", alignItems: "center", gap: 8 }, style], children: colors.map((c, idx) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3122
- import_react_native14.Pressable,
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,
3123
3453
  {
3124
3454
  onPress: () => {
3125
3455
  onSelect(c);
@@ -3150,14 +3480,14 @@ function DrawToolbar({
3150
3480
  style
3151
3481
  }) {
3152
3482
  const insets = (0, import_react_native_safe_area_context2.useSafeAreaInsets)();
3153
- const { width: screenWidth, height: screenHeight } = (0, import_react_native15.useWindowDimensions)();
3483
+ const { width: screenWidth, height: screenHeight } = (0, import_react_native16.useWindowDimensions)();
3154
3484
  const [expanded, setExpanded] = React16.useState(false);
3155
- const pos = React16.useRef(new import_react_native15.Animated.ValueXY({ x: screenWidth / 2 - 110, y: -140 })).current;
3485
+ const pos = React16.useRef(new import_react_native16.Animated.ValueXY({ x: screenWidth / 2 - 110, y: -140 })).current;
3156
3486
  const start = React16.useRef({ x: 0, y: 0 });
3157
3487
  const currentPos = React16.useRef({ x: 0, y: 0 });
3158
3488
  React16.useEffect(() => {
3159
3489
  if (hidden) return;
3160
- import_react_native15.Animated.spring(pos.y, {
3490
+ import_react_native16.Animated.spring(pos.y, {
3161
3491
  toValue: insets.top + 60,
3162
3492
  useNativeDriver: true,
3163
3493
  damping: 12,
@@ -3184,7 +3514,7 @@ function DrawToolbar({
3184
3514
  [insets.top, screenHeight, screenWidth]
3185
3515
  );
3186
3516
  const panResponder = React16.useMemo(
3187
- () => import_react_native15.PanResponder.create({
3517
+ () => import_react_native16.PanResponder.create({
3188
3518
  onStartShouldSetPanResponder: () => false,
3189
3519
  onMoveShouldSetPanResponder: (_e, g) => Math.abs(g.dx) > 5 || Math.abs(g.dy) > 5,
3190
3520
  onPanResponderGrant: () => {
@@ -3196,7 +3526,7 @@ function DrawToolbar({
3196
3526
  },
3197
3527
  onPanResponderRelease: () => {
3198
3528
  const next = clamp2(currentPos.current.x, currentPos.current.y);
3199
- import_react_native15.Animated.spring(pos, { toValue: next, useNativeDriver: true }).start();
3529
+ import_react_native16.Animated.spring(pos, { toValue: next, useNativeDriver: true }).start();
3200
3530
  }
3201
3531
  }),
3202
3532
  [clamp2, pos]
@@ -3213,7 +3543,7 @@ function DrawToolbar({
3213
3543
  const isDisabled = Boolean(disabled) || Boolean(capturingDisabled);
3214
3544
  const [pressed, setPressed] = React16.useState(false);
3215
3545
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3216
- import_react_native15.View,
3546
+ import_react_native16.View,
3217
3547
  {
3218
3548
  style: {
3219
3549
  width: 28,
@@ -3225,7 +3555,7 @@ function DrawToolbar({
3225
3555
  opacity: isDisabled ? 0.5 : pressed ? 0.85 : 1
3226
3556
  },
3227
3557
  children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3228
- import_react_native15.Pressable,
3558
+ import_react_native16.Pressable,
3229
3559
  {
3230
3560
  accessibilityRole: "button",
3231
3561
  accessibilityLabel,
@@ -3242,7 +3572,7 @@ function DrawToolbar({
3242
3572
  );
3243
3573
  }
3244
3574
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3245
- import_react_native15.Animated.View,
3575
+ import_react_native16.Animated.View,
3246
3576
  {
3247
3577
  style: [
3248
3578
  {
@@ -3259,7 +3589,7 @@ function DrawToolbar({
3259
3589
  ],
3260
3590
  ...panResponder.panHandlers,
3261
3591
  children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3262
- import_react_native15.View,
3592
+ import_react_native16.View,
3263
3593
  {
3264
3594
  style: {
3265
3595
  backgroundColor: "#F43F5E",
@@ -3267,7 +3597,7 @@ function DrawToolbar({
3267
3597
  padding: 12,
3268
3598
  minWidth: 220
3269
3599
  },
3270
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native15.View, { style: { flexDirection: "row", alignItems: "center", gap: 8 }, children: [
3600
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native16.View, { style: { flexDirection: "row", alignItems: "center", gap: 8 }, children: [
3271
3601
  renderDragHandle ? renderDragHandle() : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react_native.GripVertical, { size: 20, color: "rgba(255, 255, 255, 0.6)" }),
3272
3602
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3273
3603
  DrawColorPicker,
@@ -3285,7 +3615,7 @@ function DrawToolbar({
3285
3615
  }
3286
3616
  }
3287
3617
  ),
3288
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.View, { style: { width: 1, height: 20, backgroundColor: "rgba(255, 255, 255, 0.3)", marginHorizontal: 4 } }),
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 } }),
3289
3619
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3290
3620
  CircleActionButton,
3291
3621
  {
@@ -3323,7 +3653,7 @@ function DrawToolbar({
3323
3653
  void impact("medium");
3324
3654
  onDone();
3325
3655
  },
3326
- children: capturing ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.ActivityIndicator, { color: "#FFFFFF", size: "small" }) : renderDoneIcon ? renderDoneIcon() : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react_native.Check, { size: 16, color: "#FFFFFF" })
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" })
3327
3657
  }
3328
3658
  )
3329
3659
  ] })
@@ -3408,7 +3738,7 @@ function DrawModeOverlay({
3408
3738
  }
3409
3739
  }, [captureTargetRef, capturing, onCapture]);
3410
3740
  if (!visible) return null;
3411
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native16.View, { style: [import_react_native16.StyleSheet.absoluteFill, styles3.root, style], pointerEvents: "box-none", children: [
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: [
3412
3742
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(EdgeGlowFrame, { visible: !hideUi, role: "danger", thickness: 50, intensity: 1 }),
3413
3743
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3414
3744
  DrawSurface,
@@ -3439,7 +3769,7 @@ function DrawModeOverlay({
3439
3769
  )
3440
3770
  ] });
3441
3771
  }
3442
- var styles3 = import_react_native16.StyleSheet.create({
3772
+ var styles3 = import_react_native17.StyleSheet.create({
3443
3773
  root: {
3444
3774
  zIndex: 9999
3445
3775
  }
@@ -3447,7 +3777,7 @@ var styles3 = import_react_native16.StyleSheet.create({
3447
3777
 
3448
3778
  // src/components/comments/AppCommentsSheet.tsx
3449
3779
  var React24 = __toESM(require("react"));
3450
- var import_react_native22 = require("react-native");
3780
+ var import_react_native23 = require("react-native");
3451
3781
  var import_bottom_sheet3 = require("@gorhom/bottom-sheet");
3452
3782
  var import_react_native_safe_area_context3 = require("react-native-safe-area-context");
3453
3783
  var import_liquid_glass5 = require("@callstack/liquid-glass");
@@ -3455,13 +3785,13 @@ var import_lucide_react_native4 = require("lucide-react-native");
3455
3785
 
3456
3786
  // src/components/chat/ChatComposer.tsx
3457
3787
  var React19 = __toESM(require("react"));
3458
- var import_react_native18 = require("react-native");
3788
+ var import_react_native19 = require("react-native");
3459
3789
  var import_liquid_glass4 = require("@callstack/liquid-glass");
3460
3790
  var import_lucide_react_native3 = require("lucide-react-native");
3461
3791
 
3462
3792
  // src/components/chat/MultilineTextInput.tsx
3463
3793
  var React18 = __toESM(require("react"));
3464
- var import_react_native17 = require("react-native");
3794
+ var import_react_native18 = require("react-native");
3465
3795
  var import_bottom_sheet2 = require("@gorhom/bottom-sheet");
3466
3796
  var import_jsx_runtime15 = require("react/jsx-runtime");
3467
3797
  var MultilineTextInput = React18.forwardRef(function MultilineTextInput2({ useBottomSheetTextInput = false, placeholder, placeholderTextColor, style, ...props }, ref) {
@@ -3484,7 +3814,7 @@ var MultilineTextInput = React18.forwardRef(function MultilineTextInput2({ useBo
3484
3814
  style: [baseStyle, style],
3485
3815
  textAlignVertical: "top"
3486
3816
  };
3487
- return useBottomSheetTextInput ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_bottom_sheet2.BottomSheetTextInput, { ref, ...commonProps }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native17.TextInput, { ref, ...commonProps });
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 });
3488
3818
  });
3489
3819
 
3490
3820
  // src/components/icons/StudioIcons.tsx
@@ -3538,9 +3868,9 @@ function AspectRatioThumbnail({
3538
3868
  renderRemoveIcon
3539
3869
  }) {
3540
3870
  const [aspectRatio, setAspectRatio] = React19.useState(1);
3541
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_react_native18.View, { style: { height: THUMBNAIL_HEIGHT, aspectRatio, position: "relative" }, children: [
3542
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native18.View, { style: { flex: 1, borderRadius: 8, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3543
- import_react_native18.Image,
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,
3544
3874
  {
3545
3875
  source: { uri },
3546
3876
  style: { width: "100%", height: "100%" },
@@ -3553,7 +3883,7 @@ function AspectRatioThumbnail({
3553
3883
  }
3554
3884
  ) }),
3555
3885
  onRemove ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3556
- import_react_native18.Pressable,
3886
+ import_react_native19.Pressable,
3557
3887
  {
3558
3888
  style: {
3559
3889
  position: "absolute",
@@ -3600,17 +3930,17 @@ function ChatComposer({
3600
3930
  const hasText = text.trim().length > 0;
3601
3931
  const composerMinHeight = hasAttachments ? THUMBNAIL_HEIGHT + 44 + 24 : 44;
3602
3932
  const isButtonDisabled = sending || disabled || sendDisabled;
3603
- const maxInputHeight = React19.useMemo(() => import_react_native18.Dimensions.get("window").height * 0.5, []);
3604
- const shakeAnim = React19.useRef(new import_react_native18.Animated.Value(0)).current;
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;
3605
3935
  const [sendPressed, setSendPressed] = React19.useState(false);
3606
3936
  const triggerShake = React19.useCallback(() => {
3607
3937
  shakeAnim.setValue(0);
3608
- import_react_native18.Animated.sequence([
3609
- import_react_native18.Animated.timing(shakeAnim, { toValue: 10, duration: 50, useNativeDriver: true }),
3610
- import_react_native18.Animated.timing(shakeAnim, { toValue: -10, duration: 50, useNativeDriver: true }),
3611
- import_react_native18.Animated.timing(shakeAnim, { toValue: 10, duration: 50, useNativeDriver: true }),
3612
- import_react_native18.Animated.timing(shakeAnim, { toValue: -10, duration: 50, useNativeDriver: true }),
3613
- import_react_native18.Animated.timing(shakeAnim, { toValue: 0, duration: 50, useNativeDriver: true })
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 })
3614
3944
  ]).start();
3615
3945
  }, [shakeAnim]);
3616
3946
  const handleSend = React19.useCallback(async () => {
@@ -3627,12 +3957,12 @@ function ChatComposer({
3627
3957
  const placeholderTextColor = theme.scheme === "dark" ? "#A1A1AA" : "#71717A";
3628
3958
  const sendBg = withAlpha(theme.colors.primary, isButtonDisabled ? 0.6 : sendPressed ? 0.9 : 1);
3629
3959
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3630
- import_react_native18.View,
3960
+ import_react_native19.View,
3631
3961
  {
3632
3962
  style: [{ paddingHorizontal: 16, paddingBottom: 12, paddingTop: 8 }, style],
3633
3963
  onLayout: (e) => onLayout == null ? void 0 : onLayout({ height: e.nativeEvent.layout.height }),
3634
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_react_native18.View, { style: { flexDirection: "row", alignItems: "flex-end", gap: 8 }, children: [
3635
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native18.Animated.View, { style: { flex: 1, transform: [{ translateX: shakeAnim }] }, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
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)(
3636
3966
  import_liquid_glass4.LiquidGlassView,
3637
3967
  {
3638
3968
  style: [
@@ -3645,7 +3975,7 @@ function ChatComposer({
3645
3975
  effect: "clear",
3646
3976
  children: [
3647
3977
  hasAttachments ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
3648
- import_react_native18.ScrollView,
3978
+ import_react_native19.ScrollView,
3649
3979
  {
3650
3980
  horizontal: true,
3651
3981
  showsHorizontalScrollIndicator: false,
@@ -3662,7 +3992,7 @@ function ChatComposer({
3662
3992
  `attachment-${index}`
3663
3993
  )),
3664
3994
  onAddAttachment ? renderAddAttachment ? renderAddAttachment() : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3665
- import_react_native18.Pressable,
3995
+ import_react_native19.Pressable,
3666
3996
  {
3667
3997
  style: {
3668
3998
  height: THUMBNAIL_HEIGHT,
@@ -3713,7 +4043,7 @@ function ChatComposer({
3713
4043
  interactive: true,
3714
4044
  effect: "clear",
3715
4045
  children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3716
- import_react_native18.View,
4046
+ import_react_native19.View,
3717
4047
  {
3718
4048
  style: {
3719
4049
  width: 44,
@@ -3723,7 +4053,7 @@ function ChatComposer({
3723
4053
  backgroundColor: sendBg
3724
4054
  },
3725
4055
  children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3726
- import_react_native18.Pressable,
4056
+ import_react_native19.Pressable,
3727
4057
  {
3728
4058
  accessibilityRole: "button",
3729
4059
  accessibilityLabel: "Send",
@@ -3732,7 +4062,7 @@ function ChatComposer({
3732
4062
  onPressIn: () => setSendPressed(true),
3733
4063
  onPressOut: () => setSendPressed(false),
3734
4064
  style: { flex: 1, alignItems: "center", justifyContent: "center" },
3735
- children: sending ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native18.ActivityIndicator, {}) : renderSendIcon ? renderSendIcon() : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconChevronRight, { size: 20, colorToken: "onPrimary" })
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" })
3736
4066
  }
3737
4067
  )
3738
4068
  }
@@ -3746,10 +4076,10 @@ function ChatComposer({
3746
4076
 
3747
4077
  // src/components/comments/CommentRow.tsx
3748
4078
  var React20 = __toESM(require("react"));
3749
- var import_react_native20 = require("react-native");
4079
+ var import_react_native21 = require("react-native");
3750
4080
 
3751
4081
  // src/components/primitives/Avatar.tsx
3752
- var import_react_native19 = require("react-native");
4082
+ var import_react_native20 = require("react-native");
3753
4083
  var import_jsx_runtime18 = require("react/jsx-runtime");
3754
4084
  function initialsFrom(name) {
3755
4085
  var _a, _b;
@@ -3769,7 +4099,7 @@ function Avatar({
3769
4099
  const radius = size / 2;
3770
4100
  const fallbackBg = fallbackBackgroundColor ?? theme.colors.neutral;
3771
4101
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3772
- import_react_native19.View,
4102
+ import_react_native20.View,
3773
4103
  {
3774
4104
  style: [
3775
4105
  {
@@ -3784,7 +4114,7 @@ function Avatar({
3784
4114
  style
3785
4115
  ],
3786
4116
  children: uri ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3787
- import_react_native19.Image,
4117
+ import_react_native20.Image,
3788
4118
  {
3789
4119
  source: { uri },
3790
4120
  style: [{ width: size, height: size }, imageStyle],
@@ -3835,7 +4165,7 @@ function CommentRow({ comment, showDivider }) {
3835
4165
  };
3836
4166
  }, [comment.authorId]);
3837
4167
  return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
3838
- import_react_native20.View,
4168
+ import_react_native21.View,
3839
4169
  {
3840
4170
  style: {
3841
4171
  flexDirection: "row",
@@ -3846,8 +4176,8 @@ function CommentRow({ comment, showDivider }) {
3846
4176
  },
3847
4177
  children: [
3848
4178
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Avatar, { size: 32, uri: authorAvatar, name: authorName ?? comment.authorId, style: { marginTop: 6 } }),
3849
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_react_native20.View, { style: { flex: 1, minWidth: 0, gap: 4 }, children: [
3850
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_react_native20.View, { style: { flexDirection: "row", alignItems: "center", gap: theme.spacing.sm }, children: [
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: [
3851
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" }),
3852
4182
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Text, { style: { fontSize: 12, lineHeight: 16, color: theme.colors.textMuted }, children: formatTimeAgo(comment.createdAt) })
3853
4183
  ] }),
@@ -3972,7 +4302,18 @@ function useAppComments(appId) {
3972
4302
  try {
3973
4303
  const newComment = await appCommentsRepository.create(appId, { body: trimmed, commentType: "general" });
3974
4304
  setComments((prev) => sortByCreatedAtAsc([...prev, newComment]));
4305
+ await trackSubmitComment({
4306
+ appId,
4307
+ commentLength: trimmed.length,
4308
+ success: true
4309
+ });
3975
4310
  } catch (e) {
4311
+ await trackSubmitComment({
4312
+ appId,
4313
+ commentLength: trimmed.length,
4314
+ success: false,
4315
+ error: e
4316
+ });
3976
4317
  setError(e instanceof Error ? e : new Error(String(e)));
3977
4318
  throw e;
3978
4319
  } finally {
@@ -4015,13 +4356,13 @@ function useAppDetails(appId) {
4015
4356
 
4016
4357
  // src/components/comments/useIosKeyboardSnapFix.ts
4017
4358
  var React23 = __toESM(require("react"));
4018
- var import_react_native21 = require("react-native");
4359
+ var import_react_native22 = require("react-native");
4019
4360
  function useIosKeyboardSnapFix(sheetRef, options) {
4020
4361
  const [keyboardVisible, setKeyboardVisible] = React23.useState(false);
4021
4362
  React23.useEffect(() => {
4022
- if (import_react_native21.Platform.OS !== "ios") return;
4023
- const show = import_react_native21.Keyboard.addListener("keyboardWillShow", () => setKeyboardVisible(true));
4024
- const hide = import_react_native21.Keyboard.addListener("keyboardWillHide", () => {
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", () => {
4025
4366
  var _a;
4026
4367
  setKeyboardVisible(false);
4027
4368
  const target = (options == null ? void 0 : options.targetIndex) ?? 1;
@@ -4097,17 +4438,17 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
4097
4438
  onChange: handleChange,
4098
4439
  backgroundStyle: {
4099
4440
  backgroundColor: theme.scheme === "dark" ? "#0B080F" : "#FFFFFF",
4100
- borderTopLeftRadius: import_react_native22.Platform.OS === "ios" ? 39 : 16,
4101
- borderTopRightRadius: import_react_native22.Platform.OS === "ios" ? 39 : 16
4441
+ borderTopLeftRadius: import_react_native23.Platform.OS === "ios" ? 39 : 16,
4442
+ borderTopRightRadius: import_react_native23.Platform.OS === "ios" ? 39 : 16
4102
4443
  },
4103
4444
  handleIndicatorStyle: { backgroundColor: theme.colors.handleIndicator },
4104
4445
  keyboardBehavior: "interactive",
4105
4446
  keyboardBlurBehavior: "restore",
4106
4447
  android_keyboardInputMode: "adjustResize",
4107
4448
  topInset: insets.top,
4108
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_native22.View, { style: { flex: 1 }, children: [
4449
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_native23.View, { style: { flex: 1 }, children: [
4109
4450
  /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
4110
- import_react_native22.View,
4451
+ import_react_native23.View,
4111
4452
  {
4112
4453
  style: {
4113
4454
  flexDirection: "row",
@@ -4143,7 +4484,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
4143
4484
  interactive: true,
4144
4485
  effect: "clear",
4145
4486
  children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4146
- import_react_native22.View,
4487
+ import_react_native23.View,
4147
4488
  {
4148
4489
  style: {
4149
4490
  width: 32,
@@ -4154,7 +4495,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
4154
4495
  justifyContent: "center"
4155
4496
  },
4156
4497
  children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4157
- import_react_native22.Pressable,
4498
+ import_react_native23.Pressable,
4158
4499
  {
4159
4500
  disabled: !appId,
4160
4501
  onPress: () => void handlePlay(),
@@ -4189,13 +4530,13 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
4189
4530
  },
4190
4531
  keyboardShouldPersistTaps: "handled",
4191
4532
  children: [
4192
- loading && comments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native22.View, { style: { flex: 1, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native22.ActivityIndicator, {}) }) : comments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native22.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)),
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)),
4193
4534
  error ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Text, { variant: "captionMuted", style: { marginTop: theme.spacing.lg }, children: "Failed to load comments." }) : null
4194
4535
  ]
4195
4536
  }
4196
4537
  ),
4197
4538
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4198
- import_react_native22.View,
4539
+ import_react_native23.View,
4199
4540
  {
4200
4541
  style: {
4201
4542
  position: "absolute",
@@ -4204,7 +4545,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
4204
4545
  bottom: 0,
4205
4546
  paddingHorizontal: theme.spacing.lg,
4206
4547
  paddingTop: theme.spacing.sm,
4207
- paddingBottom: import_react_native22.Platform.OS === "ios" ? keyboardVisible ? theme.spacing.lg : insets.bottom : insets.bottom + 10,
4548
+ paddingBottom: import_react_native23.Platform.OS === "ios" ? keyboardVisible ? theme.spacing.lg : insets.bottom : insets.bottom + 10,
4208
4549
  borderTopWidth: 1,
4209
4550
  borderTopColor: withAlpha(theme.colors.border, 0.1),
4210
4551
  backgroundColor: withAlpha(theme.colors.background, 0.8)
@@ -4218,7 +4559,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
4218
4559
  useBottomSheetTextInput: true,
4219
4560
  onSend: async (text) => {
4220
4561
  await create(text);
4221
- import_react_native22.Keyboard.dismiss();
4562
+ import_react_native23.Keyboard.dismiss();
4222
4563
  }
4223
4564
  }
4224
4565
  )
@@ -4231,16 +4572,16 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
4231
4572
 
4232
4573
  // src/studio/ui/PreviewPanel.tsx
4233
4574
  var React35 = __toESM(require("react"));
4234
- var import_react_native43 = require("react-native");
4575
+ var import_react_native44 = require("react-native");
4235
4576
 
4236
4577
  // src/components/preview/PreviewPage.tsx
4237
- var import_react_native23 = require("react-native");
4578
+ var import_react_native24 = require("react-native");
4238
4579
  var import_bottom_sheet4 = require("@gorhom/bottom-sheet");
4239
4580
  var import_jsx_runtime21 = require("react/jsx-runtime");
4240
4581
  function PreviewPage({ header, children, contentStyle }) {
4241
4582
  const theme = useTheme();
4242
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_native23.View, { style: { flex: 1 }, children: [
4243
- header ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native23.View, { children: header }) : null,
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,
4244
4585
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4245
4586
  import_bottom_sheet4.BottomSheetScrollView,
4246
4587
  {
@@ -4260,15 +4601,15 @@ function PreviewPage({ header, children, contentStyle }) {
4260
4601
  }
4261
4602
 
4262
4603
  // src/studio/ui/preview-panel/PreviewPanelHeader.tsx
4263
- var import_react_native26 = require("react-native");
4604
+ var import_react_native27 = require("react-native");
4264
4605
 
4265
4606
  // src/components/studio-sheet/StudioSheetHeader.tsx
4266
- var import_react_native24 = require("react-native");
4607
+ var import_react_native25 = require("react-native");
4267
4608
  var import_jsx_runtime22 = require("react/jsx-runtime");
4268
4609
  function StudioSheetHeader({ left, center, right, style }) {
4269
4610
  const theme = useTheme();
4270
4611
  return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
4271
- import_react_native24.View,
4612
+ import_react_native25.View,
4272
4613
  {
4273
4614
  style: [
4274
4615
  {
@@ -4281,9 +4622,9 @@ function StudioSheetHeader({ left, center, right, style }) {
4281
4622
  style
4282
4623
  ],
4283
4624
  children: [
4284
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native24.View, { style: { flexDirection: "row", alignItems: "center" }, children: left }),
4285
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native24.View, { style: { flex: 1, alignItems: "center" }, children: center }),
4286
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native24.View, { style: { flexDirection: "row", alignItems: "center" }, children: right })
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 })
4287
4628
  ]
4288
4629
  }
4289
4630
  );
@@ -4291,7 +4632,7 @@ function StudioSheetHeader({ left, center, right, style }) {
4291
4632
 
4292
4633
  // src/components/studio-sheet/StudioSheetHeaderIconButton.tsx
4293
4634
  var React25 = __toESM(require("react"));
4294
- var import_react_native25 = require("react-native");
4635
+ var import_react_native26 = require("react-native");
4295
4636
  var import_liquid_glass6 = require("@callstack/liquid-glass");
4296
4637
  var import_jsx_runtime23 = require("react/jsx-runtime");
4297
4638
  function StudioSheetHeaderIconButton({
@@ -4311,14 +4652,14 @@ function StudioSheetHeaderIconButton({
4311
4652
  const glassInnerBg = intent === "danger" ? theme.colors.danger : theme.colors.primary;
4312
4653
  const resolvedOpacity = disabled ? 0.6 : pressed ? 0.9 : 1;
4313
4654
  const glassBg = withAlpha(glassInnerBg, resolvedOpacity);
4314
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_native25.View, { style, children: appearance === "glass" ? /* @__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)(
4315
4656
  ResettableLiquidGlassView,
4316
4657
  {
4317
4658
  style: [{ borderRadius: 100 }, !import_liquid_glass6.isLiquidGlassSupported && { backgroundColor: glassFallbackBg }],
4318
4659
  interactive: true,
4319
4660
  effect: "clear",
4320
4661
  children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4321
- import_react_native25.View,
4662
+ import_react_native26.View,
4322
4663
  {
4323
4664
  style: {
4324
4665
  width: size,
@@ -4329,7 +4670,7 @@ function StudioSheetHeaderIconButton({
4329
4670
  backgroundColor: glassBg
4330
4671
  },
4331
4672
  children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4332
- import_react_native25.Pressable,
4673
+ import_react_native26.Pressable,
4333
4674
  {
4334
4675
  accessibilityRole: "button",
4335
4676
  accessibilityLabel,
@@ -4348,7 +4689,7 @@ function StudioSheetHeaderIconButton({
4348
4689
  )
4349
4690
  }
4350
4691
  ) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4351
- import_react_native25.View,
4692
+ import_react_native26.View,
4352
4693
  {
4353
4694
  style: {
4354
4695
  width: size,
@@ -4360,7 +4701,7 @@ function StudioSheetHeaderIconButton({
4360
4701
  opacity: resolvedOpacity
4361
4702
  },
4362
4703
  children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4363
- import_react_native25.Pressable,
4704
+ import_react_native26.Pressable,
4364
4705
  {
4365
4706
  accessibilityRole: "button",
4366
4707
  accessibilityLabel,
@@ -4394,7 +4735,7 @@ function PreviewPanelHeader({
4394
4735
  {
4395
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,
4396
4737
  center: null,
4397
- right: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native26.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
4738
+ right: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react_native27.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
4398
4739
  isOwner ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4399
4740
  StudioSheetHeaderIconButton,
4400
4741
  {
@@ -4424,10 +4765,10 @@ function PreviewPanelHeader({
4424
4765
  }
4425
4766
 
4426
4767
  // src/components/preview/PreviewHeroCard.tsx
4427
- var import_react_native28 = require("react-native");
4768
+ var import_react_native29 = require("react-native");
4428
4769
 
4429
4770
  // src/components/primitives/Surface.tsx
4430
- var import_react_native27 = require("react-native");
4771
+ var import_react_native28 = require("react-native");
4431
4772
  var import_jsx_runtime25 = require("react/jsx-runtime");
4432
4773
  function backgroundFor(variant, theme) {
4433
4774
  const { colors } = theme;
@@ -4446,7 +4787,7 @@ function backgroundFor(variant, theme) {
4446
4787
  function Surface({ variant = "surface", border = false, style, ...props }) {
4447
4788
  const theme = useTheme();
4448
4789
  return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4449
- import_react_native27.View,
4790
+ import_react_native28.View,
4450
4791
  {
4451
4792
  ...props,
4452
4793
  style: [
@@ -4502,11 +4843,11 @@ function PreviewHeroCard({
4502
4843
  },
4503
4844
  style
4504
4845
  ],
4505
- children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react_native28.View, { style: { flex: 1 }, children: [
4506
- background ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_native28.View, { style: { position: "absolute", inset: 0 }, children: background }) : null,
4507
- image ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_native28.View, { style: { position: "absolute", inset: 0 }, children: image }) : null,
4508
- overlayTopLeft ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_native28.View, { style: { position: "absolute", top: theme.spacing.sm, left: theme.spacing.sm, zIndex: 2 }, children: overlayTopLeft }) : null,
4509
- overlayBottom ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_native28.View, { style: { flex: 1, justifyContent: "flex-end" }, children: overlayBottom }) : null
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
4510
4851
  ] })
4511
4852
  }
4512
4853
  );
@@ -4514,20 +4855,20 @@ function PreviewHeroCard({
4514
4855
 
4515
4856
  // src/components/preview/PreviewPlaceholder.tsx
4516
4857
  var React26 = __toESM(require("react"));
4517
- var import_react_native29 = require("react-native");
4858
+ var import_react_native30 = require("react-native");
4518
4859
  var import_expo_linear_gradient2 = require("expo-linear-gradient");
4519
4860
  var import_jsx_runtime28 = require("react/jsx-runtime");
4520
4861
  function PreviewPlaceholder({ visible, style }) {
4521
4862
  if (!visible) return null;
4522
- const opacityAnim = React26.useRef(new import_react_native29.Animated.Value(0)).current;
4863
+ const opacityAnim = React26.useRef(new import_react_native30.Animated.Value(0)).current;
4523
4864
  React26.useEffect(() => {
4524
4865
  if (!visible) return;
4525
- const animation = import_react_native29.Animated.loop(
4526
- import_react_native29.Animated.sequence([
4527
- import_react_native29.Animated.timing(opacityAnim, { toValue: 1, duration: 1500, useNativeDriver: true }),
4528
- import_react_native29.Animated.timing(opacityAnim, { toValue: 2, duration: 1500, useNativeDriver: true }),
4529
- import_react_native29.Animated.timing(opacityAnim, { toValue: 3, duration: 1500, useNativeDriver: true }),
4530
- import_react_native29.Animated.timing(opacityAnim, { toValue: 0, duration: 1500, useNativeDriver: true })
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 })
4531
4872
  ])
4532
4873
  );
4533
4874
  animation.start();
@@ -4538,7 +4879,7 @@ function PreviewPlaceholder({ visible, style }) {
4538
4879
  const opacity3 = opacityAnim.interpolate({ inputRange: [0, 1, 2, 3], outputRange: [0, 0, 1, 0] });
4539
4880
  const opacity4 = opacityAnim.interpolate({ inputRange: [0, 1, 2, 3], outputRange: [0, 0, 0, 1] });
4540
4881
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
4541
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_native29.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity1 }, style], children: /* @__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)(
4542
4883
  import_expo_linear_gradient2.LinearGradient,
4543
4884
  {
4544
4885
  colors: ["rgba(98, 0, 238, 0.45)", "rgba(168, 85, 247, 0.35)"],
@@ -4547,7 +4888,7 @@ function PreviewPlaceholder({ visible, style }) {
4547
4888
  style: { width: "100%", height: "100%" }
4548
4889
  }
4549
4890
  ) }),
4550
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_native29.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity2 }, style], children: /* @__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)(
4551
4892
  import_expo_linear_gradient2.LinearGradient,
4552
4893
  {
4553
4894
  colors: ["rgba(168, 85, 247, 0.45)", "rgba(139, 92, 246, 0.35)"],
@@ -4556,7 +4897,7 @@ function PreviewPlaceholder({ visible, style }) {
4556
4897
  style: { width: "100%", height: "100%" }
4557
4898
  }
4558
4899
  ) }),
4559
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_native29.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity3 }, style], children: /* @__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)(
4560
4901
  import_expo_linear_gradient2.LinearGradient,
4561
4902
  {
4562
4903
  colors: ["rgba(139, 92, 246, 0.45)", "rgba(126, 34, 206, 0.35)"],
@@ -4565,7 +4906,7 @@ function PreviewPlaceholder({ visible, style }) {
4565
4906
  style: { width: "100%", height: "100%" }
4566
4907
  }
4567
4908
  ) }),
4568
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_native29.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity4 }, style], children: /* @__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)(
4569
4910
  import_expo_linear_gradient2.LinearGradient,
4570
4911
  {
4571
4912
  colors: ["rgba(126, 34, 206, 0.45)", "rgba(98, 0, 238, 0.35)"],
@@ -4578,12 +4919,12 @@ function PreviewPlaceholder({ visible, style }) {
4578
4919
  }
4579
4920
 
4580
4921
  // src/components/preview/PreviewImage.tsx
4581
- var import_react_native30 = require("react-native");
4922
+ var import_react_native31 = require("react-native");
4582
4923
  var import_jsx_runtime29 = require("react/jsx-runtime");
4583
4924
  function PreviewImage({ uri, onLoad, style }) {
4584
4925
  if (!uri) return null;
4585
4926
  return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
4586
- import_react_native30.Image,
4927
+ import_react_native31.Image,
4587
4928
  {
4588
4929
  source: { uri },
4589
4930
  resizeMode: "cover",
@@ -4594,7 +4935,7 @@ function PreviewImage({ uri, onLoad, style }) {
4594
4935
  }
4595
4936
 
4596
4937
  // src/components/preview/StatsBar.tsx
4597
- var import_react_native31 = require("react-native");
4938
+ var import_react_native32 = require("react-native");
4598
4939
  var import_liquid_glass7 = require("@callstack/liquid-glass");
4599
4940
  var import_lucide_react_native5 = require("lucide-react-native");
4600
4941
 
@@ -4627,7 +4968,7 @@ function StatsBar({
4627
4968
  const theme = useTheme();
4628
4969
  const statsBgColor = theme.scheme === "dark" ? "rgba(24, 24, 27, 0.5)" : "rgba(255, 255, 255, 0.5)";
4629
4970
  return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
4630
- import_react_native31.View,
4971
+ import_react_native32.View,
4631
4972
  {
4632
4973
  style: [
4633
4974
  { position: "absolute", bottom: 12, width: "100%", paddingHorizontal: 12 },
@@ -4643,15 +4984,15 @@ function StatsBar({
4643
4984
  !import_liquid_glass7.isLiquidGlassSupported && { backgroundColor: statsBgColor }
4644
4985
  ],
4645
4986
  effect: "clear",
4646
- children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_react_native31.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: 16 }, children: [
4987
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_react_native32.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: 16 }, children: [
4647
4988
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
4648
- import_react_native31.Pressable,
4989
+ import_react_native32.Pressable,
4649
4990
  {
4650
4991
  disabled: !onPressLike,
4651
4992
  onPress: onPressLike,
4652
4993
  hitSlop: 8,
4653
4994
  style: { paddingVertical: 8 },
4654
- children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_react_native31.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
4995
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_react_native32.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
4655
4996
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
4656
4997
  import_lucide_react_native5.Heart,
4657
4998
  {
@@ -4661,7 +5002,7 @@ function StatsBar({
4661
5002
  fill: isLiked ? theme.colors.danger : "transparent"
4662
5003
  }
4663
5004
  ),
4664
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react_native31.View, { style: { width: 4 } }),
5005
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react_native32.View, { style: { width: 4 } }),
4665
5006
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
4666
5007
  Text,
4667
5008
  {
@@ -4677,22 +5018,22 @@ function StatsBar({
4677
5018
  }
4678
5019
  ),
4679
5020
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
4680
- import_react_native31.Pressable,
5021
+ import_react_native32.Pressable,
4681
5022
  {
4682
5023
  disabled: !onPressComments,
4683
5024
  onPress: onPressComments,
4684
5025
  hitSlop: 8,
4685
5026
  style: { paddingVertical: 8 },
4686
- children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_react_native31.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
5027
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_react_native32.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
4687
5028
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react_native5.MessageCircle, { size: 16, strokeWidth: 2.5, color: "#FFFFFF" }),
4688
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react_native31.View, { style: { width: 4 } }),
5029
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react_native32.View, { style: { width: 4 } }),
4689
5030
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Text, { variant: "caption", style: { color: "#FFFFFF", fontWeight: theme.typography.fontWeight.bold }, children: commentCount })
4690
5031
  ] })
4691
5032
  }
4692
5033
  ),
4693
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_react_native31.View, { style: { flexDirection: "row", alignItems: "center", paddingVertical: 8 }, children: [
4694
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react_native31.View, { style: { transform: [{ scaleY: -1 }] }, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(MergeIcon, { width: 14, height: 14, color: "#FFFFFF" }) }),
4695
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react_native31.View, { style: { width: 4 } }),
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 } }),
4696
5037
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Text, { variant: "caption", style: { color: "#FFFFFF", fontWeight: theme.typography.fontWeight.bold }, children: forkCount })
4697
5038
  ] })
4698
5039
  ] })
@@ -4703,7 +5044,7 @@ function StatsBar({
4703
5044
  }
4704
5045
 
4705
5046
  // src/components/preview/PreviewStatusBadge.tsx
4706
- var import_react_native32 = require("react-native");
5047
+ var import_react_native33 = require("react-native");
4707
5048
  var import_lucide_react_native6 = require("lucide-react-native");
4708
5049
 
4709
5050
  // src/data/apps/types.ts
@@ -4748,7 +5089,7 @@ function PreviewStatusBadge({ status }) {
4748
5089
  const IconComp = STATUS_ICON[status];
4749
5090
  const label = APP_STATUS_LABEL[status] ?? status;
4750
5091
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
4751
- import_react_native32.View,
5092
+ import_react_native33.View,
4752
5093
  {
4753
5094
  style: {
4754
5095
  flexDirection: "row",
@@ -4801,10 +5142,10 @@ function PreviewHeroSection({
4801
5142
  }
4802
5143
 
4803
5144
  // src/studio/ui/preview-panel/PreviewMetaSection.tsx
4804
- var import_react_native34 = require("react-native");
5145
+ var import_react_native35 = require("react-native");
4805
5146
 
4806
5147
  // src/components/preview/PreviewMetaRow.tsx
4807
- var import_react_native33 = require("react-native");
5148
+ var import_react_native34 = require("react-native");
4808
5149
  var import_jsx_runtime34 = require("react/jsx-runtime");
4809
5150
  function PreviewMetaRow({
4810
5151
  avatarUri,
@@ -4816,10 +5157,10 @@ function PreviewMetaRow({
4816
5157
  style
4817
5158
  }) {
4818
5159
  const theme = useTheme();
4819
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react_native33.View, { style: [{ alignSelf: "stretch" }, style], children: [
4820
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react_native33.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
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: [
4821
5162
  /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Avatar, { uri: avatarUri, name: creatorName, size: 24, style: { marginRight: theme.spacing.sm } }),
4822
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react_native33.View, { style: { flexDirection: "row", alignItems: "center", flex: 1, minWidth: 0, marginRight: theme.spacing.sm }, children: [
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: [
4823
5164
  /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
4824
5165
  Text,
4825
5166
  {
@@ -4834,9 +5175,9 @@ function PreviewMetaRow({
4834
5175
  children: title
4835
5176
  }
4836
5177
  ),
4837
- tag ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react_native33.View, { style: { marginLeft: theme.spacing.sm }, children: tag }) : null
5178
+ tag ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react_native34.View, { style: { marginLeft: theme.spacing.sm }, children: tag }) : null
4838
5179
  ] }),
4839
- rightMetric ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react_native33.View, { children: rightMetric }) : null
5180
+ rightMetric ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react_native34.View, { children: rightMetric }) : null
4840
5181
  ] }),
4841
5182
  subtitle ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
4842
5183
  Text,
@@ -4892,9 +5233,9 @@ function PreviewMetaSection({ app, isOwner, creator, downloadsCount }) {
4892
5233
  subtitle: app.description,
4893
5234
  avatarUri: (creator == null ? void 0 : creator.avatar) ?? null,
4894
5235
  creatorName: (creator == null ? void 0 : creator.name) ?? null,
4895
- tag: isOwner || app.forkedFromAppId ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react_native34.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,
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,
4896
5237
  rightMetric: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
4897
- import_react_native34.View,
5238
+ import_react_native35.View,
4898
5239
  {
4899
5240
  style: {
4900
5241
  flexDirection: "row",
@@ -4928,10 +5269,10 @@ function PreviewMetaSection({ app, isOwner, creator, downloadsCount }) {
4928
5269
  }
4929
5270
 
4930
5271
  // src/studio/ui/preview-panel/PreviewCustomizeSection.tsx
4931
- var import_react_native36 = require("react-native");
5272
+ var import_react_native37 = require("react-native");
4932
5273
 
4933
5274
  // src/studio/ui/preview-panel/PressableCardRow.tsx
4934
- var import_react_native35 = require("react-native");
5275
+ var import_react_native36 = require("react-native");
4935
5276
  var import_jsx_runtime36 = require("react/jsx-runtime");
4936
5277
  function PressableCardRow({
4937
5278
  accessibilityLabel,
@@ -4944,20 +5285,20 @@ function PressableCardRow({
4944
5285
  style
4945
5286
  }) {
4946
5287
  return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4947
- import_react_native35.Pressable,
5288
+ import_react_native36.Pressable,
4948
5289
  {
4949
5290
  accessibilityRole: "button",
4950
5291
  accessibilityLabel,
4951
5292
  disabled,
4952
5293
  onPress,
4953
5294
  style: ({ pressed }) => ({ opacity: disabled ? 0.6 : pressed ? 0.85 : 1 }),
4954
- children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Card, { padded: false, border: false, style, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_react_native35.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
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: [
4955
5296
  left,
4956
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_react_native35.View, { style: { flex: 1, minWidth: 0 }, children: [
5297
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_react_native36.View, { style: { flex: 1, minWidth: 0 }, children: [
4957
5298
  title,
4958
5299
  subtitle ? subtitle : null
4959
5300
  ] }),
4960
- right ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react_native35.View, { style: { marginLeft: 16 }, children: right }) : null
5301
+ right ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react_native36.View, { style: { marginLeft: 16 }, children: right }) : null
4961
5302
  ] }) })
4962
5303
  }
4963
5304
  );
@@ -4999,7 +5340,7 @@ function PreviewCustomizeSection({
4999
5340
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_jsx_runtime38.Fragment, { children: [
5000
5341
  /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(SectionTitle, { children: "Customize" }),
5001
5342
  showProcessing ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
5002
- import_react_native36.View,
5343
+ import_react_native37.View,
5003
5344
  {
5004
5345
  style: {
5005
5346
  flexDirection: "row",
@@ -5013,7 +5354,7 @@ function PreviewCustomizeSection({
5013
5354
  },
5014
5355
  children: [
5015
5356
  /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
5016
- import_react_native36.View,
5357
+ import_react_native37.View,
5017
5358
  {
5018
5359
  style: {
5019
5360
  width: 40,
@@ -5024,10 +5365,10 @@ function PreviewCustomizeSection({
5024
5365
  backgroundColor: withAlpha(theme.colors.warning, 0.1),
5025
5366
  marginRight: theme.spacing.lg
5026
5367
  },
5027
- children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_react_native36.ActivityIndicator, { color: theme.colors.warning, size: "small" })
5368
+ children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_react_native37.ActivityIndicator, { color: theme.colors.warning, size: "small" })
5028
5369
  }
5029
5370
  ),
5030
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_react_native36.View, { style: { flex: 1, minWidth: 0 }, children: [
5371
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_react_native37.View, { style: { flex: 1, minWidth: 0 }, children: [
5031
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" }),
5032
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) })
5033
5374
  ] })
@@ -5048,7 +5389,7 @@ function PreviewCustomizeSection({
5048
5389
  marginBottom: theme.spacing.sm
5049
5390
  },
5050
5391
  left: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
5051
- import_react_native36.View,
5392
+ import_react_native37.View,
5052
5393
  {
5053
5394
  style: {
5054
5395
  width: 40,
@@ -5081,7 +5422,7 @@ function PreviewCustomizeSection({
5081
5422
  marginBottom: theme.spacing.sm
5082
5423
  },
5083
5424
  left: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
5084
- import_react_native36.View,
5425
+ import_react_native37.View,
5085
5426
  {
5086
5427
  style: {
5087
5428
  width: 40,
@@ -5105,16 +5446,16 @@ function PreviewCustomizeSection({
5105
5446
 
5106
5447
  // src/studio/ui/preview-panel/PreviewCollaborateSection.tsx
5107
5448
  var React32 = __toESM(require("react"));
5108
- var import_react_native42 = require("react-native");
5449
+ var import_react_native43 = require("react-native");
5109
5450
  var import_lucide_react_native9 = require("lucide-react-native");
5110
5451
 
5111
5452
  // src/components/merge-requests/MergeRequestStatusCard.tsx
5112
5453
  var React28 = __toESM(require("react"));
5113
- var import_react_native38 = require("react-native");
5454
+ var import_react_native39 = require("react-native");
5114
5455
  var import_lucide_react_native7 = require("lucide-react-native");
5115
5456
 
5116
5457
  // src/components/primitives/MarkdownText.tsx
5117
- var import_react_native37 = require("react-native");
5458
+ var import_react_native38 = require("react-native");
5118
5459
  var import_react_native_markdown_display = __toESM(require("react-native-markdown-display"));
5119
5460
  var import_react2 = require("react");
5120
5461
  var import_jsx_runtime39 = require("react/jsx-runtime");
@@ -5158,7 +5499,7 @@ function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
5158
5499
  const codeTextColor = isDark ? "#FFFFFF" : theme.colors.text;
5159
5500
  const paragraphBottom = variant === "mergeRequest" ? 8 : 6;
5160
5501
  const baseLineHeight = variant === "mergeRequest" ? 22 : 20;
5161
- const screen = import_react_native37.Dimensions.get("window");
5502
+ const screen = import_react_native38.Dimensions.get("window");
5162
5503
  const tooltipPadding = theme.spacing.sm;
5163
5504
  const tooltipYOffset = theme.spacing.lg + 32;
5164
5505
  const minTooltipY = theme.spacing.xl;
@@ -5188,7 +5529,7 @@ function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
5188
5529
  setShowCopied(false);
5189
5530
  }, 1200);
5190
5531
  };
5191
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_react_native37.Pressable, { style, onPress: import_react_native37.Keyboard.dismiss, onLongPress: handleLongPress, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_react_native37.View, { style: { position: "relative" }, children: [
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: [
5192
5533
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
5193
5534
  import_react_native_markdown_display.default,
5194
5535
  {
@@ -5202,7 +5543,7 @@ function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
5202
5543
  paddingHorizontal: variant === "mergeRequest" ? 6 : 4,
5203
5544
  paddingVertical: variant === "mergeRequest" ? 2 : 0,
5204
5545
  borderRadius: variant === "mergeRequest" ? 6 : 4,
5205
- fontFamily: import_react_native37.Platform.OS === "ios" ? "Menlo" : "monospace",
5546
+ fontFamily: import_react_native38.Platform.OS === "ios" ? "Menlo" : "monospace",
5206
5547
  fontSize: 13
5207
5548
  },
5208
5549
  code_block: {
@@ -5223,8 +5564,8 @@ function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
5223
5564
  children: markdown
5224
5565
  }
5225
5566
  ),
5226
- showCopied && tooltipAnchor ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_react_native37.Modal, { transparent: true, visible: true, statusBarTranslucent: true, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_react_native37.View, { pointerEvents: "none", style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
5227
- import_react_native37.View,
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,
5228
5569
  {
5229
5570
  pointerEvents: "none",
5230
5571
  style: {
@@ -5238,7 +5579,7 @@ function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
5238
5579
  },
5239
5580
  onLayout: (event) => setTooltipWidth(event.nativeEvent.layout.width),
5240
5581
  children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
5241
- import_react_native37.Text,
5582
+ import_react_native38.Text,
5242
5583
  {
5243
5584
  style: {
5244
5585
  color: theme.colors.onSuccess,
@@ -5342,15 +5683,15 @@ function MergeRequestStatusCard({
5342
5683
  const createdIso = toIsoString(mergeRequest.createdAt ?? null);
5343
5684
  const headerTimeAgo = updatedIso ? formatTimeAgo(updatedIso) : "";
5344
5685
  const createdTimeAgo = createdIso ? formatTimeAgo(createdIso) : "";
5345
- const rotate = React28.useRef(new import_react_native38.Animated.Value(expanded ? 1 : 0)).current;
5686
+ const rotate = React28.useRef(new import_react_native39.Animated.Value(expanded ? 1 : 0)).current;
5346
5687
  React28.useEffect(() => {
5347
- import_react_native38.Animated.timing(rotate, {
5688
+ import_react_native39.Animated.timing(rotate, {
5348
5689
  toValue: expanded ? 1 : 0,
5349
5690
  duration: 200,
5350
5691
  useNativeDriver: true
5351
5692
  }).start();
5352
5693
  }, [expanded, rotate]);
5353
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_native38.Pressable, { onPress: () => setExpanded(!expanded), style: ({ pressed }) => [{ opacity: pressed ? 0.95 : 1 }], children: /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
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)(
5354
5695
  Card,
5355
5696
  {
5356
5697
  padded: false,
@@ -5363,10 +5704,10 @@ function MergeRequestStatusCard({
5363
5704
  style
5364
5705
  ],
5365
5706
  children: [
5366
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native38.View, { style: { flexDirection: "row", alignItems: "center", gap: theme.spacing.lg }, children: [
5367
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_native38.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 }) }),
5368
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native38.View, { style: { flex: 1, minWidth: 0 }, children: [
5369
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native38.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" }, children: [
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: [
5370
5711
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
5371
5712
  Text,
5372
5713
  {
@@ -5385,8 +5726,8 @@ function MergeRequestStatusCard({
5385
5726
  ] }),
5386
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" })
5387
5728
  ] }),
5388
- headerRight ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_native38.View, { children: headerRight }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
5389
- import_react_native38.Animated.View,
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,
5390
5731
  {
5391
5732
  style: {
5392
5733
  transform: [
@@ -5399,7 +5740,7 @@ function MergeRequestStatusCard({
5399
5740
  }
5400
5741
  )
5401
5742
  ] }),
5402
- expanded ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native38.View, { style: { marginTop: 16, marginLeft: 56 }, children: [
5743
+ expanded ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native39.View, { style: { marginTop: 16, marginLeft: 56 }, children: [
5403
5744
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
5404
5745
  Text,
5405
5746
  {
@@ -5435,16 +5776,16 @@ function MergeRequestStatusCard({
5435
5776
 
5436
5777
  // src/components/merge-requests/ReviewMergeRequestCarousel.tsx
5437
5778
  var React31 = __toESM(require("react"));
5438
- var import_react_native41 = require("react-native");
5779
+ var import_react_native42 = require("react-native");
5439
5780
 
5440
5781
  // src/components/merge-requests/ReviewMergeRequestCard.tsx
5441
5782
  var React30 = __toESM(require("react"));
5442
- var import_react_native40 = require("react-native");
5783
+ var import_react_native41 = require("react-native");
5443
5784
  var import_lucide_react_native8 = require("lucide-react-native");
5444
5785
 
5445
5786
  // src/components/merge-requests/ReviewMergeRequestActionButton.tsx
5446
5787
  var React29 = __toESM(require("react"));
5447
- var import_react_native39 = require("react-native");
5788
+ var import_react_native40 = require("react-native");
5448
5789
  var import_jsx_runtime41 = require("react/jsx-runtime");
5449
5790
  function ReviewMergeRequestActionButton({
5450
5791
  accessibilityLabel,
@@ -5461,7 +5802,7 @@ function ReviewMergeRequestActionButton({
5461
5802
  const paddingVertical = iconOnly ? 0 : 8;
5462
5803
  const opacity = disabled ? 0.5 : pressed ? 0.9 : 1;
5463
5804
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
5464
- import_react_native39.View,
5805
+ import_react_native40.View,
5465
5806
  {
5466
5807
  style: {
5467
5808
  width,
@@ -5476,7 +5817,7 @@ function ReviewMergeRequestActionButton({
5476
5817
  justifyContent: "center"
5477
5818
  },
5478
5819
  children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
5479
- import_react_native39.Pressable,
5820
+ import_react_native40.Pressable,
5480
5821
  {
5481
5822
  accessibilityRole: "button",
5482
5823
  accessibilityLabel,
@@ -5518,12 +5859,12 @@ function ReviewMergeRequestCard({
5518
5859
  const theme = useTheme();
5519
5860
  const status = React30.useMemo(() => getMergeRequestStatusDisplay(mr.status), [mr.status]);
5520
5861
  const canAct = mr.status === "open";
5521
- const rotate = React30.useRef(new import_react_native40.Animated.Value(isExpanded ? 1 : 0)).current;
5862
+ const rotate = React30.useRef(new import_react_native41.Animated.Value(isExpanded ? 1 : 0)).current;
5522
5863
  React30.useEffect(() => {
5523
- import_react_native40.Animated.timing(rotate, { toValue: isExpanded ? 1 : 0, duration: 200, useNativeDriver: true }).start();
5864
+ import_react_native41.Animated.timing(rotate, { toValue: isExpanded ? 1 : 0, duration: 200, useNativeDriver: true }).start();
5524
5865
  }, [isExpanded, rotate]);
5525
5866
  const position = total > 1 ? `${index + 1}/${total}` : "Merge request";
5526
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_react_native40.Pressable, { onPress: onToggle, style: ({ pressed }) => ({ opacity: pressed ? 0.95 : 1 }), children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
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)(
5527
5868
  Card,
5528
5869
  {
5529
5870
  padded: false,
@@ -5536,9 +5877,9 @@ function ReviewMergeRequestCard({
5536
5877
  }
5537
5878
  ],
5538
5879
  children: [
5539
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native40.View, { style: { flexDirection: "row", alignItems: "center", gap: 12 }, children: [
5880
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native41.View, { style: { flexDirection: "row", alignItems: "center", gap: 12 }, children: [
5540
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 }),
5541
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native40.View, { style: { flex: 1, minWidth: 0 }, children: [
5882
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native41.View, { style: { flex: 1, minWidth: 0 }, children: [
5542
5883
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
5543
5884
  Text,
5544
5885
  {
@@ -5554,7 +5895,7 @@ function ReviewMergeRequestCard({
5554
5895
  ] })
5555
5896
  ] }),
5556
5897
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
5557
- import_react_native40.Animated.View,
5898
+ import_react_native41.Animated.View,
5558
5899
  {
5559
5900
  style: {
5560
5901
  transform: [{ rotate: rotate.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "180deg"] }) }]
@@ -5563,7 +5904,7 @@ function ReviewMergeRequestCard({
5563
5904
  }
5564
5905
  )
5565
5906
  ] }),
5566
- isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native40.View, { style: { marginTop: 16 }, children: [
5907
+ isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native41.View, { style: { marginTop: 16 }, children: [
5567
5908
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
5568
5909
  Text,
5569
5910
  {
@@ -5581,9 +5922,9 @@ function ReviewMergeRequestCard({
5581
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..." }),
5582
5923
  mr.description ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(MarkdownText, { markdown: mr.description, variant: "mergeRequest" }) : null
5583
5924
  ] }) : null,
5584
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_react_native40.View, { style: { height: 1, backgroundColor: withAlpha(theme.colors.borderStrong, 0.5), marginTop: 12, marginBottom: 12 } }),
5585
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native40.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" }, children: [
5586
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native40.View, { style: { flexDirection: "row", gap: 8 }, children: [
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: [
5587
5928
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
5588
5929
  ReviewMergeRequestActionButton,
5589
5930
  {
@@ -5592,7 +5933,7 @@ function ReviewMergeRequestCard({
5592
5933
  disabled: !canAct || isAnyProcessing,
5593
5934
  onPress: onReject,
5594
5935
  iconOnly: !isExpanded,
5595
- children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native40.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
5936
+ children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native41.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
5596
5937
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_lucide_react_native8.X, { size: 18, color: "#FFFFFF" }),
5597
5938
  isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Text, { style: { fontSize: 13, color: "#FFFFFF", fontWeight: theme.typography.fontWeight.semibold }, children: "Reject" }) : null
5598
5939
  ] })
@@ -5606,10 +5947,10 @@ function ReviewMergeRequestCard({
5606
5947
  disabled: !canAct || isAnyProcessing,
5607
5948
  onPress: onApprove,
5608
5949
  iconOnly: !isExpanded,
5609
- children: isProcessing ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native40.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
5610
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_react_native40.ActivityIndicator, { size: "small", color: "#FFFFFF" }),
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" }),
5611
5952
  isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Text, { style: { fontSize: 13, color: "#FFFFFF", fontWeight: theme.typography.fontWeight.semibold }, children: "Processing" }) : null
5612
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native40.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
5953
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native41.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
5613
5954
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_lucide_react_native8.Check, { size: 18, color: "#FFFFFF" }),
5614
5955
  isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Text, { style: { fontSize: 13, color: "#FFFFFF", fontWeight: theme.typography.fontWeight.semibold }, children: "Approve" }) : null
5615
5956
  ] })
@@ -5624,7 +5965,7 @@ function ReviewMergeRequestCard({
5624
5965
  disabled: isBuilding || isTestingThis,
5625
5966
  onPress: onTest,
5626
5967
  iconOnly: !isExpanded,
5627
- children: isTestingThis ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_react_native40.ActivityIndicator, { size: "small", color: "#888" }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native40.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
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: [
5628
5969
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_lucide_react_native8.Play, { size: 14, color: theme.colors.text }),
5629
5970
  isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Text, { style: { fontSize: 13, color: theme.colors.text, fontWeight: theme.typography.fontWeight.semibold }, children: "Test" }) : null
5630
5971
  ] })
@@ -5650,32 +5991,32 @@ function ReviewMergeRequestCarousel({
5650
5991
  style
5651
5992
  }) {
5652
5993
  const theme = useTheme();
5653
- const { width } = (0, import_react_native41.useWindowDimensions)();
5994
+ const { width } = (0, import_react_native42.useWindowDimensions)();
5654
5995
  const [expanded, setExpanded] = React31.useState({});
5655
- const carouselScrollX = React31.useRef(new import_react_native41.Animated.Value(0)).current;
5996
+ const carouselScrollX = React31.useRef(new import_react_native42.Animated.Value(0)).current;
5656
5997
  const peekAmount = 24;
5657
5998
  const gap = 16;
5658
5999
  const cardWidth = React31.useMemo(() => Math.max(1, width - theme.spacing.lg * 2 - peekAmount), [peekAmount, theme.spacing.lg, width]);
5659
6000
  const snapInterval = cardWidth + gap;
5660
6001
  const dotColor = theme.scheme === "dark" ? "#FFFFFF" : "#000000";
5661
6002
  if (mergeRequests.length === 0) return null;
5662
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_react_native41.View, { style: [{ marginHorizontal: -theme.spacing.lg }, style], children: [
6003
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_react_native42.View, { style: [{ marginHorizontal: -theme.spacing.lg }, style], children: [
5663
6004
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
5664
- import_react_native41.FlatList,
6005
+ import_react_native42.FlatList,
5665
6006
  {
5666
6007
  horizontal: true,
5667
6008
  data: mergeRequests,
5668
6009
  keyExtractor: (mr) => mr.id,
5669
6010
  showsHorizontalScrollIndicator: false,
5670
6011
  contentContainerStyle: { paddingHorizontal: theme.spacing.lg, paddingVertical: theme.spacing.sm },
5671
- ItemSeparatorComponent: () => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native41.View, { style: { width: gap } }),
6012
+ ItemSeparatorComponent: () => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native42.View, { style: { width: gap } }),
5672
6013
  snapToAlignment: "start",
5673
6014
  decelerationRate: "fast",
5674
6015
  snapToInterval: snapInterval,
5675
6016
  disableIntervalMomentum: true,
5676
6017
  style: { paddingRight: peekAmount },
5677
- ListFooterComponent: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native41.View, { style: { width: peekAmount } }),
5678
- onScroll: import_react_native41.Animated.event([{ nativeEvent: { contentOffset: { x: carouselScrollX } } }], {
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 } } }], {
5679
6020
  useNativeDriver: false
5680
6021
  }),
5681
6022
  scrollEventThrottle: 16,
@@ -5686,7 +6027,7 @@ function ReviewMergeRequestCarousel({
5686
6027
  const isProcessing = Boolean(processingMrId && processingMrId === item.id);
5687
6028
  const isAnyProcessing = Boolean(processingMrId);
5688
6029
  const isTestingThis = Boolean(testingMrId && testingMrId === item.id);
5689
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native41.View, { style: { width: cardWidth }, children: /* @__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)(
5690
6031
  ReviewMergeRequestCard,
5691
6032
  {
5692
6033
  mr: item,
@@ -5707,7 +6048,7 @@ function ReviewMergeRequestCarousel({
5707
6048
  }
5708
6049
  }
5709
6050
  ),
5710
- mergeRequests.length >= 1 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native41.View, { style: { flexDirection: "row", justifyContent: "center", columnGap: 8, marginTop: theme.spacing.md }, children: mergeRequests.map((mr, index) => {
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) => {
5711
6052
  const inputRange = [(index - 1) * snapInterval, index * snapInterval, (index + 1) * snapInterval];
5712
6053
  const scale = carouselScrollX.interpolate({
5713
6054
  inputRange,
@@ -5720,7 +6061,7 @@ function ReviewMergeRequestCarousel({
5720
6061
  extrapolate: "clamp"
5721
6062
  });
5722
6063
  return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
5723
- import_react_native41.Animated.View,
6064
+ import_react_native42.Animated.View,
5724
6065
  {
5725
6066
  style: {
5726
6067
  width: 8,
@@ -5787,7 +6128,7 @@ function PreviewCollaborateSection({
5787
6128
  accessibilityLabel: "Submit merge request",
5788
6129
  disabled: submittingMr,
5789
6130
  onPress: () => {
5790
- import_react_native42.Alert.alert(
6131
+ import_react_native43.Alert.alert(
5791
6132
  "Submit Merge Request",
5792
6133
  "Are you sure you want to submit your changes to the original app?",
5793
6134
  [
@@ -5813,7 +6154,7 @@ function PreviewCollaborateSection({
5813
6154
  marginBottom: theme.spacing.sm
5814
6155
  },
5815
6156
  left: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
5816
- import_react_native42.View,
6157
+ import_react_native43.View,
5817
6158
  {
5818
6159
  style: {
5819
6160
  width: 40,
@@ -5824,7 +6165,7 @@ function PreviewCollaborateSection({
5824
6165
  backgroundColor: withAlpha("#03DAC6", 0.1),
5825
6166
  marginRight: theme.spacing.lg
5826
6167
  },
5827
- children: submittingMr ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native42.ActivityIndicator, { color: "#03DAC6", size: "small" }) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(MergeIcon, { width: 20, height: 20, color: "#03DAC6" })
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" })
5828
6169
  }
5829
6170
  ),
5830
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" }),
@@ -5838,7 +6179,7 @@ function PreviewCollaborateSection({
5838
6179
  accessibilityLabel: "Sync from original",
5839
6180
  disabled: isSyncing,
5840
6181
  onPress: () => {
5841
- import_react_native42.Alert.alert(
6182
+ import_react_native43.Alert.alert(
5842
6183
  "Sync from Original",
5843
6184
  "This will pull the latest upstream changes into your remix.",
5844
6185
  [
@@ -5850,12 +6191,12 @@ function PreviewCollaborateSection({
5850
6191
  setSyncingLocal(true);
5851
6192
  Promise.resolve(onSyncUpstream()).then((result) => {
5852
6193
  if ((result == null ? void 0 : result.status) === "up-to-date") {
5853
- import_react_native42.Alert.alert("Up to date", "Your remix already includes the latest upstream changes.");
6194
+ import_react_native43.Alert.alert("Up to date", "Your remix already includes the latest upstream changes.");
5854
6195
  } else {
5855
- import_react_native42.Alert.alert("Sync started", "Upstream changes are being merged into your remix.");
6196
+ import_react_native43.Alert.alert("Sync started", "Upstream changes are being merged into your remix.");
5856
6197
  }
5857
6198
  }).catch(() => {
5858
- import_react_native42.Alert.alert("Sync failed", "We could not start the sync. Please try again.");
6199
+ import_react_native43.Alert.alert("Sync failed", "We could not start the sync. Please try again.");
5859
6200
  }).finally(() => setSyncingLocal(false));
5860
6201
  }
5861
6202
  }
@@ -5871,7 +6212,7 @@ function PreviewCollaborateSection({
5871
6212
  marginBottom: theme.spacing.sm
5872
6213
  },
5873
6214
  left: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
5874
- import_react_native42.View,
6215
+ import_react_native43.View,
5875
6216
  {
5876
6217
  style: {
5877
6218
  width: 40,
@@ -5882,7 +6223,7 @@ function PreviewCollaborateSection({
5882
6223
  backgroundColor: withAlpha(theme.colors.primary, 0.12),
5883
6224
  marginRight: theme.spacing.lg
5884
6225
  },
5885
- children: isSyncing ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native42.ActivityIndicator, { color: theme.colors.primary, size: "small" }) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react_native9.RefreshCw, { size: 18, color: theme.colors.primary })
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 })
5886
6227
  }
5887
6228
  ),
5888
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" }),
@@ -5920,7 +6261,7 @@ function PreviewCollaborateSection({
5920
6261
  children: "History"
5921
6262
  }
5922
6263
  ),
5923
- outgoingMergeRequests.map((mr) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native42.View, { style: { marginBottom: theme.spacing.sm }, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(MergeRequestStatusCard, { mergeRequest: toMergeRequestSummary(mr) }) }, mr.id))
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))
5924
6265
  ] }) : null
5925
6266
  ] });
5926
6267
  }
@@ -6044,7 +6385,8 @@ function useAppStats({
6044
6385
  initialComments = 0,
6045
6386
  initialForks = 0,
6046
6387
  initialIsLiked = false,
6047
- onOpenComments
6388
+ onOpenComments,
6389
+ interactionSource = "unknown"
6048
6390
  }) {
6049
6391
  const [likeCount, setLikeCount] = React33.useState(initialLikes);
6050
6392
  const [commentCount, setCommentCount] = React33.useState(initialComments);
@@ -6088,23 +6430,31 @@ function useAppStats({
6088
6430
  if (newIsLiked) {
6089
6431
  const res = await appLikesRepository.create(appId, {});
6090
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 });
6091
6434
  } else {
6092
6435
  const res = await appLikesRepository.removeMine(appId);
6093
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 });
6094
6438
  }
6095
6439
  } catch (e) {
6096
6440
  setIsLiked(!newIsLiked);
6097
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
+ }
6098
6447
  }
6099
- }, [appId, isLiked, likeCount]);
6448
+ }, [appId, interactionSource, isLiked, likeCount]);
6100
6449
  const handleOpenComments = React33.useCallback(() => {
6101
6450
  if (!appId) return;
6102
6451
  try {
6103
6452
  void Haptics2.impactAsync(Haptics2.ImpactFeedbackStyle.Light);
6104
6453
  } catch {
6105
6454
  }
6455
+ void trackOpenComments({ appId, source: interactionSource });
6106
6456
  onOpenComments == null ? void 0 : onOpenComments();
6107
- }, [appId, onOpenComments]);
6457
+ }, [appId, interactionSource, onOpenComments]);
6108
6458
  return { likeCount, commentCount, forkCount, isLiked, setCommentCount, handleLike, handleOpenComments };
6109
6459
  }
6110
6460
 
@@ -6187,7 +6537,8 @@ function usePreviewPanelData(params) {
6187
6537
  initialForks: insights.forks,
6188
6538
  initialComments: commentCountOverride ?? insights.comments,
6189
6539
  initialIsLiked: Boolean(app == null ? void 0 : app.isLiked),
6190
- onOpenComments
6540
+ onOpenComments,
6541
+ interactionSource: "preview_panel"
6191
6542
  });
6192
6543
  const canSubmitMergeRequest = React34.useMemo(() => {
6193
6544
  if (!isOwner) return false;
@@ -6253,7 +6604,7 @@ ${shareUrl}` : `Check out this app on Remix
6253
6604
  ${shareUrl}`;
6254
6605
  try {
6255
6606
  const title = app.name ?? "Remix app";
6256
- const payload = import_react_native43.Platform.OS === "ios" ? {
6607
+ const payload = import_react_native44.Platform.OS === "ios" ? {
6257
6608
  title,
6258
6609
  message
6259
6610
  } : {
@@ -6261,9 +6612,18 @@ ${shareUrl}`;
6261
6612
  message,
6262
6613
  url: shareUrl
6263
6614
  };
6264
- await import_react_native43.Share.share(payload);
6615
+ await import_react_native44.Share.share(payload);
6616
+ await trackShareApp({
6617
+ appId: app.id,
6618
+ success: true
6619
+ });
6265
6620
  } catch (error) {
6266
6621
  log.warn("PreviewPanel share failed", error);
6622
+ await trackShareApp({
6623
+ appId: app.id,
6624
+ success: false,
6625
+ error
6626
+ });
6267
6627
  }
6268
6628
  }, [app]);
6269
6629
  const {
@@ -6295,9 +6655,9 @@ ${shareUrl}`;
6295
6655
  }
6296
6656
  );
6297
6657
  if (loading || !app) {
6298
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(PreviewPage, { header, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_react_native43.View, { style: { flex: 1, justifyContent: "center", alignItems: "center", padding: 24 }, children: [
6299
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_react_native43.ActivityIndicator, {}),
6300
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_react_native43.View, { style: { height: 12 } }),
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 } }),
6301
6661
  /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Text, { variant: "bodyMuted", children: "Loading app\u2026" })
6302
6662
  ] }) });
6303
6663
  }
@@ -6358,25 +6718,25 @@ ${shareUrl}`;
6358
6718
 
6359
6719
  // src/studio/ui/ChatPanel.tsx
6360
6720
  var React42 = __toESM(require("react"));
6361
- var import_react_native55 = require("react-native");
6721
+ var import_react_native56 = require("react-native");
6362
6722
 
6363
6723
  // src/components/chat/ChatPage.tsx
6364
6724
  var React39 = __toESM(require("react"));
6365
- var import_react_native48 = require("react-native");
6725
+ var import_react_native49 = require("react-native");
6366
6726
  var import_react_native_safe_area_context4 = require("react-native-safe-area-context");
6367
6727
 
6368
6728
  // src/components/chat/ChatMessageList.tsx
6369
6729
  var React38 = __toESM(require("react"));
6370
- var import_react_native47 = require("react-native");
6730
+ var import_react_native48 = require("react-native");
6371
6731
  var import_bottom_sheet5 = require("@gorhom/bottom-sheet");
6372
6732
 
6373
6733
  // src/components/chat/ChatMessageBubble.tsx
6374
6734
  var React36 = __toESM(require("react"));
6375
- var import_react_native45 = require("react-native");
6735
+ var import_react_native46 = require("react-native");
6376
6736
  var import_lucide_react_native10 = require("lucide-react-native");
6377
6737
 
6378
6738
  // src/components/primitives/Button.tsx
6379
- var import_react_native44 = require("react-native");
6739
+ var import_react_native45 = require("react-native");
6380
6740
  var import_jsx_runtime46 = require("react/jsx-runtime");
6381
6741
  function backgroundFor2(variant, theme, pressed, disabled) {
6382
6742
  const { colors } = theme;
@@ -6414,7 +6774,7 @@ function Button({
6414
6774
  const theme = useTheme();
6415
6775
  const isDisabled = disabled ?? void 0;
6416
6776
  return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
6417
- import_react_native44.Pressable,
6777
+ import_react_native45.Pressable,
6418
6778
  {
6419
6779
  ...props,
6420
6780
  disabled: isDisabled,
@@ -6472,7 +6832,7 @@ function ChatMessageBubbleInner({
6472
6832
  const handleRetryPress = React36.useCallback(() => {
6473
6833
  onRetryMessage == null ? void 0 : onRetryMessage(message.id);
6474
6834
  }, [message.id, onRetryMessage]);
6475
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native45.View, { style: [align, style], children: [
6835
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native46.View, { style: [align, style], children: [
6476
6836
  /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
6477
6837
  Surface,
6478
6838
  {
@@ -6488,14 +6848,14 @@ function ChatMessageBubbleInner({
6488
6848
  },
6489
6849
  cornerStyle
6490
6850
  ],
6491
- children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native45.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
6851
+ children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native46.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
6492
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,
6493
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,
6494
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native45.View, { style: { flexShrink: 1, minWidth: 0 }, children: renderContent ? renderContent(message) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(MarkdownText, { markdown: message.content, variant: "chat", bodyColor }) })
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 }) })
6495
6855
  ] })
6496
6856
  }
6497
6857
  ),
6498
- showRetry ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native45.View, { style: { marginTop: theme.spacing.xs, alignSelf: align.alignSelf }, children: /* @__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)(
6499
6859
  Button,
6500
6860
  {
6501
6861
  variant: "ghost",
@@ -6504,7 +6864,7 @@ function ChatMessageBubbleInner({
6504
6864
  disabled: retrying,
6505
6865
  style: { borderColor: theme.colors.danger },
6506
6866
  accessibilityLabel: "Retry send",
6507
- children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native45.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
6867
+ children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native46.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
6508
6868
  !retrying ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react_native10.RotateCcw, { size: 14, color: theme.colors.danger }) : null,
6509
6869
  /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
6510
6870
  Text,
@@ -6529,23 +6889,23 @@ ChatMessageBubble.displayName = "ChatMessageBubble";
6529
6889
 
6530
6890
  // src/components/chat/TypingIndicator.tsx
6531
6891
  var React37 = __toESM(require("react"));
6532
- var import_react_native46 = require("react-native");
6892
+ var import_react_native47 = require("react-native");
6533
6893
  var import_jsx_runtime48 = require("react/jsx-runtime");
6534
6894
  function TypingIndicator({ style }) {
6535
6895
  const theme = useTheme();
6536
6896
  const dotColor = theme.colors.textSubtle;
6537
6897
  const anims = React37.useMemo(
6538
- () => [new import_react_native46.Animated.Value(0.3), new import_react_native46.Animated.Value(0.3), new import_react_native46.Animated.Value(0.3)],
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)],
6539
6899
  []
6540
6900
  );
6541
6901
  React37.useEffect(() => {
6542
6902
  const loops = [];
6543
6903
  anims.forEach((a, idx) => {
6544
- const seq = import_react_native46.Animated.sequence([
6545
- import_react_native46.Animated.timing(a, { toValue: 1, duration: 420, useNativeDriver: true, delay: idx * 140 }),
6546
- import_react_native46.Animated.timing(a, { toValue: 0.3, duration: 420, useNativeDriver: true })
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 })
6547
6907
  ]);
6548
- const loop = import_react_native46.Animated.loop(seq);
6908
+ const loop = import_react_native47.Animated.loop(seq);
6549
6909
  loops.push(loop);
6550
6910
  loop.start();
6551
6911
  });
@@ -6553,8 +6913,8 @@ function TypingIndicator({ style }) {
6553
6913
  loops.forEach((l) => l.stop());
6554
6914
  };
6555
6915
  }, [anims]);
6556
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_react_native46.View, { style: [{ flexDirection: "row", alignItems: "center" }, style], children: anims.map((a, i) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
6557
- import_react_native46.Animated.View,
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,
6558
6918
  {
6559
6919
  style: {
6560
6920
  width: 8,
@@ -6563,7 +6923,7 @@ function TypingIndicator({ style }) {
6563
6923
  marginHorizontal: 3,
6564
6924
  backgroundColor: dotColor,
6565
6925
  opacity: a,
6566
- transform: [{ translateY: import_react_native46.Animated.multiply(import_react_native46.Animated.subtract(a, 0.3), 2) }]
6926
+ transform: [{ translateY: import_react_native47.Animated.multiply(import_react_native47.Animated.subtract(a, 0.3), 2) }]
6567
6927
  }
6568
6928
  },
6569
6929
  i
@@ -6647,11 +7007,11 @@ var ChatMessageList = React38.forwardRef(
6647
7007
  ],
6648
7008
  [contentStyle, theme.spacing.lg, theme.spacing.sm]
6649
7009
  );
6650
- const renderSeparator = React38.useCallback(() => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_react_native47.View, { style: { height: theme.spacing.sm } }), [theme.spacing.sm]);
7010
+ const renderSeparator = React38.useCallback(() => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_react_native48.View, { style: { height: theme.spacing.sm } }), [theme.spacing.sm]);
6651
7011
  const listHeader = React38.useMemo(
6652
- () => /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_react_native47.View, { children: [
6653
- 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,
6654
- bottomInset > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_react_native47.View, { style: { height: bottomInset } }) : null
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
6655
7015
  ] }),
6656
7016
  [bottomInset, showTypingIndicator, theme.spacing.lg, theme.spacing.sm]
6657
7017
  );
@@ -6712,7 +7072,7 @@ function ChatPage({
6712
7072
  const insets = (0, import_react_native_safe_area_context4.useSafeAreaInsets)();
6713
7073
  const [composerHeight, setComposerHeight] = React39.useState(0);
6714
7074
  const [composerTopHeight, setComposerTopHeight] = React39.useState(0);
6715
- const footerBottomPadding = import_react_native48.Platform.OS === "ios" ? insets.bottom - 24 : insets.bottom + 10;
7075
+ const footerBottomPadding = import_react_native49.Platform.OS === "ios" ? insets.bottom - 24 : insets.bottom + 10;
6716
7076
  const totalComposerHeight = composerHeight + composerTopHeight;
6717
7077
  const overlayBottom = totalComposerHeight + footerBottomPadding + theme.spacing.lg;
6718
7078
  const bottomInset = totalComposerHeight + footerBottomPadding + theme.spacing.xl;
@@ -6729,12 +7089,12 @@ function ChatPage({
6729
7089
  if (composerTop) return;
6730
7090
  setComposerTopHeight(0);
6731
7091
  }, [composerTop]);
6732
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_react_native48.View, { style: [{ flex: 1 }, style], children: [
6733
- header ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_react_native48.View, { children: header }) : null,
6734
- topBanner ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_react_native48.View, { style: { paddingHorizontal: theme.spacing.lg, paddingTop: theme.spacing.sm }, children: topBanner }) : null,
6735
- /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_react_native48.View, { style: { flex: 1 }, children: [
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: [
6736
7096
  /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
6737
- import_react_native48.View,
7097
+ import_react_native49.View,
6738
7098
  {
6739
7099
  style: { flex: 1 },
6740
7100
  children: [
@@ -6756,7 +7116,7 @@ function ChatPage({
6756
7116
  }
6757
7117
  ),
6758
7118
  /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
6759
- import_react_native48.View,
7119
+ import_react_native49.View,
6760
7120
  {
6761
7121
  style: {
6762
7122
  position: "absolute",
@@ -6769,7 +7129,7 @@ function ChatPage({
6769
7129
  },
6770
7130
  children: [
6771
7131
  composerTop ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
6772
- import_react_native48.View,
7132
+ import_react_native49.View,
6773
7133
  {
6774
7134
  style: { marginBottom: theme.spacing.sm },
6775
7135
  onLayout: (e) => setComposerTopHeight(e.nativeEvent.layout.height),
@@ -6793,7 +7153,7 @@ function ChatPage({
6793
7153
 
6794
7154
  // src/components/chat/ScrollToBottomButton.tsx
6795
7155
  var React40 = __toESM(require("react"));
6796
- var import_react_native49 = require("react-native");
7156
+ var import_react_native50 = require("react-native");
6797
7157
  var import_react_native_reanimated2 = __toESM(require("react-native-reanimated"));
6798
7158
  var import_jsx_runtime51 = require("react/jsx-runtime");
6799
7159
  function ScrollToBottomButton({ visible, onPress, children, style }) {
@@ -6824,7 +7184,7 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
6824
7184
  animStyle
6825
7185
  ],
6826
7186
  children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
6827
- import_react_native49.View,
7187
+ import_react_native50.View,
6828
7188
  {
6829
7189
  style: {
6830
7190
  width: 44,
@@ -6843,7 +7203,7 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
6843
7203
  opacity: pressed ? 0.85 : 1
6844
7204
  },
6845
7205
  children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
6846
- import_react_native49.Pressable,
7206
+ import_react_native50.Pressable,
6847
7207
  {
6848
7208
  onPress,
6849
7209
  onPressIn: () => setPressed(true),
@@ -6860,10 +7220,10 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
6860
7220
  }
6861
7221
 
6862
7222
  // src/components/chat/ChatHeader.tsx
6863
- var import_react_native50 = require("react-native");
7223
+ var import_react_native51 = require("react-native");
6864
7224
  var import_jsx_runtime52 = require("react/jsx-runtime");
6865
7225
  function ChatHeader({ left, right, center, style }) {
6866
- const flattenedStyle = import_react_native50.StyleSheet.flatten([
7226
+ const flattenedStyle = import_react_native51.StyleSheet.flatten([
6867
7227
  {
6868
7228
  paddingTop: 0
6869
7229
  },
@@ -6881,7 +7241,7 @@ function ChatHeader({ left, right, center, style }) {
6881
7241
  }
6882
7242
 
6883
7243
  // src/components/chat/ForkNoticeBanner.tsx
6884
- var import_react_native51 = require("react-native");
7244
+ var import_react_native52 = require("react-native");
6885
7245
  var import_jsx_runtime53 = require("react/jsx-runtime");
6886
7246
  function ForkNoticeBanner({ isOwner = true, title, description, style }) {
6887
7247
  const theme = useTheme();
@@ -6902,7 +7262,7 @@ function ForkNoticeBanner({ isOwner = true, title, description, style }) {
6902
7262
  },
6903
7263
  style
6904
7264
  ],
6905
- children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_react_native51.View, { style: { minWidth: 0 }, children: [
7265
+ children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_react_native52.View, { style: { minWidth: 0 }, children: [
6906
7266
  /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
6907
7267
  Text,
6908
7268
  {
@@ -6936,7 +7296,7 @@ function ForkNoticeBanner({ isOwner = true, title, description, style }) {
6936
7296
 
6937
7297
  // src/components/chat/ChatQueue.tsx
6938
7298
  var React41 = __toESM(require("react"));
6939
- var import_react_native52 = require("react-native");
7299
+ var import_react_native53 = require("react-native");
6940
7300
  var import_jsx_runtime54 = require("react/jsx-runtime");
6941
7301
  function ChatQueue({ items, onRemove }) {
6942
7302
  const theme = useTheme();
@@ -6970,7 +7330,7 @@ ${trimmedLine2}\u2026 `;
6970
7330
  }, [items]);
6971
7331
  if (items.length === 0) return null;
6972
7332
  return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
6973
- import_react_native52.View,
7333
+ import_react_native53.View,
6974
7334
  {
6975
7335
  style: {
6976
7336
  borderWidth: 1,
@@ -6982,7 +7342,7 @@ ${trimmedLine2}\u2026 `;
6982
7342
  },
6983
7343
  children: [
6984
7344
  /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Text, { variant: "caption", style: { marginBottom: theme.spacing.sm }, children: "Queue" }),
6985
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native52.View, { style: { gap: theme.spacing.sm }, children: items.map((item) => {
7345
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native53.View, { style: { gap: theme.spacing.sm }, children: items.map((item) => {
6986
7346
  const isExpanded = Boolean(expanded[item.id]);
6987
7347
  const showToggle = Boolean(canExpand[item.id]);
6988
7348
  const prompt = item.prompt ?? "";
@@ -6990,7 +7350,7 @@ ${trimmedLine2}\u2026 `;
6990
7350
  const displayPrompt = !isExpanded && showToggle && collapsedText[item.id] ? collapsedText[item.id] : prompt;
6991
7351
  const isRemoving = Boolean(removing[item.id]);
6992
7352
  return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
6993
- import_react_native52.View,
7353
+ import_react_native53.View,
6994
7354
  {
6995
7355
  style: {
6996
7356
  flexDirection: "row",
@@ -7002,7 +7362,7 @@ ${trimmedLine2}\u2026 `;
7002
7362
  backgroundColor: withAlpha(theme.colors.surface, theme.scheme === "dark" ? 0.8 : 0.9)
7003
7363
  },
7004
7364
  children: [
7005
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react_native52.View, { style: { flex: 1 }, children: [
7365
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react_native53.View, { style: { flex: 1 }, children: [
7006
7366
  !canExpand[item.id] ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
7007
7367
  Text,
7008
7368
  {
@@ -7042,7 +7402,7 @@ ${trimmedLine2}\u2026 `;
7042
7402
  }
7043
7403
  ),
7044
7404
  showToggle && isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
7045
- import_react_native52.Pressable,
7405
+ import_react_native53.Pressable,
7046
7406
  {
7047
7407
  onPress: () => setExpanded((prev) => ({ ...prev, [item.id]: false })),
7048
7408
  hitSlop: 6,
@@ -7052,7 +7412,7 @@ ${trimmedLine2}\u2026 `;
7052
7412
  ) : null
7053
7413
  ] }),
7054
7414
  /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
7055
- import_react_native52.Pressable,
7415
+ import_react_native53.Pressable,
7056
7416
  {
7057
7417
  onPress: () => {
7058
7418
  if (!onRemove || isRemoving) return;
@@ -7067,7 +7427,7 @@ ${trimmedLine2}\u2026 `;
7067
7427
  },
7068
7428
  hitSlop: 8,
7069
7429
  style: { alignSelf: "center" },
7070
- children: isRemoving ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native52.ActivityIndicator, { size: "small", color: theme.colors.text }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(IconClose, { size: 14, colorToken: "text" })
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" })
7071
7431
  }
7072
7432
  )
7073
7433
  ]
@@ -7081,7 +7441,7 @@ ${trimmedLine2}\u2026 `;
7081
7441
  }
7082
7442
 
7083
7443
  // src/components/chat/AgentProgressCard.tsx
7084
- var import_react_native53 = require("react-native");
7444
+ var import_react_native54 = require("react-native");
7085
7445
  var import_jsx_runtime55 = require("react/jsx-runtime");
7086
7446
  function titleForPhase(phase) {
7087
7447
  if (phase === "planning") return "Planning";
@@ -7107,7 +7467,7 @@ function AgentProgressCard({ progress }) {
7107
7467
  const subtitle = progress.latestMessage || `Agent is ${phaseLabel.toLowerCase()}...`;
7108
7468
  const todo = progress.todoSummary;
7109
7469
  return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
7110
- import_react_native53.View,
7470
+ import_react_native54.View,
7111
7471
  {
7112
7472
  style: {
7113
7473
  borderWidth: 1,
@@ -7118,7 +7478,7 @@ function AgentProgressCard({ progress }) {
7118
7478
  backgroundColor: withAlpha(theme.colors.surface, theme.scheme === "dark" ? 0.84 : 0.94)
7119
7479
  },
7120
7480
  children: [
7121
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_react_native53.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", marginBottom: 4 }, children: [
7481
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_react_native54.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", marginBottom: 4 }, children: [
7122
7482
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Text, { variant: "caption", children: statusLabel }),
7123
7483
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Text, { variant: "captionMuted", children: phaseLabel })
7124
7484
  ] }),
@@ -7127,7 +7487,7 @@ function AgentProgressCard({ progress }) {
7127
7487
  "Updated files: ",
7128
7488
  progress.changedFilesCount
7129
7489
  ] }) : null,
7130
- progress.recentFiles.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_react_native53.View, { style: { marginTop: 6 }, children: progress.recentFiles.map((path) => /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(Text, { variant: "captionMuted", numberOfLines: 1, children: [
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: [
7131
7491
  "\u2022 ",
7132
7492
  path
7133
7493
  ] }, path)) }) : null,
@@ -7145,7 +7505,7 @@ function AgentProgressCard({ progress }) {
7145
7505
  }
7146
7506
 
7147
7507
  // src/components/chat/BundleProgressCard.tsx
7148
- var import_react_native54 = require("react-native");
7508
+ var import_react_native55 = require("react-native");
7149
7509
  var import_jsx_runtime56 = require("react/jsx-runtime");
7150
7510
  function titleForStatus2(status) {
7151
7511
  if (status === "succeeded") return "Completed";
@@ -7159,7 +7519,7 @@ function BundleProgressCard({ progress }) {
7159
7519
  const fillColor = progress.status === "failed" ? theme.colors.danger : progress.status === "succeeded" ? theme.colors.success : theme.colors.warning;
7160
7520
  const detail = progress.errorMessage || progress.phaseLabel;
7161
7521
  return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
7162
- import_react_native54.View,
7522
+ import_react_native55.View,
7163
7523
  {
7164
7524
  accessible: true,
7165
7525
  accessibilityRole: "progressbar",
@@ -7174,7 +7534,7 @@ function BundleProgressCard({ progress }) {
7174
7534
  backgroundColor: withAlpha(theme.colors.surface, theme.scheme === "dark" ? 0.84 : 0.94)
7175
7535
  },
7176
7536
  children: [
7177
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_react_native54.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", marginBottom: 8 }, children: [
7537
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_react_native55.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", marginBottom: 8 }, children: [
7178
7538
  /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Text, { variant: "caption", children: statusLabel }),
7179
7539
  /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(Text, { variant: "captionMuted", children: [
7180
7540
  percent,
@@ -7182,7 +7542,7 @@ function BundleProgressCard({ progress }) {
7182
7542
  ] })
7183
7543
  ] }),
7184
7544
  /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
7185
- import_react_native54.View,
7545
+ import_react_native55.View,
7186
7546
  {
7187
7547
  style: {
7188
7548
  width: "100%",
@@ -7192,7 +7552,7 @@ function BundleProgressCard({ progress }) {
7192
7552
  overflow: "hidden"
7193
7553
  },
7194
7554
  children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
7195
- import_react_native54.View,
7555
+ import_react_native55.View,
7196
7556
  {
7197
7557
  style: {
7198
7558
  width: `${percent}%`,
@@ -7258,11 +7618,11 @@ function ChatPanel({
7258
7618
  const header = /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
7259
7619
  ChatHeader,
7260
7620
  {
7261
- left: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_react_native55.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
7621
+ left: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_react_native56.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
7262
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" }) }),
7263
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
7264
7624
  ] }),
7265
- right: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_react_native55.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
7625
+ right: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_react_native56.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
7266
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,
7267
7627
  /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(StudioSheetHeaderIconButton, { onPress: onClose, accessibilityLabel: "Close", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(IconClose, { size: 20, colorToken: "floatingContent" }) })
7268
7628
  ] }),
@@ -7278,18 +7638,18 @@ function ChatPanel({
7278
7638
  ) : null;
7279
7639
  const showMessagesLoading = Boolean(loading) && messages.length === 0 || forking;
7280
7640
  if (showMessagesLoading) {
7281
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_react_native55.View, { style: { flex: 1 }, children: [
7282
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_react_native55.View, { children: header }),
7283
- topBanner ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_react_native55.View, { style: { paddingHorizontal: 16, paddingTop: 8 }, children: topBanner }) : null,
7284
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_react_native55.View, { style: { flex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 24, paddingVertical: 12 }, children: [
7285
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_react_native55.ActivityIndicator, {}),
7286
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_react_native55.View, { style: { height: 12 } }),
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 } }),
7287
7647
  /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Text, { variant: "bodyMuted", children: forking ? "Creating your copy\u2026" : "Loading messages\u2026" })
7288
7648
  ] })
7289
7649
  ] });
7290
7650
  }
7291
7651
  const bundleProgress = (progress == null ? void 0 : progress.bundle) ?? null;
7292
- const queueTop = progress || queueItems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_react_native55.View, { style: { gap: theme.spacing.sm }, children: [
7652
+ const queueTop = progress || queueItems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_react_native56.View, { style: { gap: theme.spacing.sm }, children: [
7293
7653
  progress ? bundleProgress ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(BundleProgressCard, { progress: bundleProgress }) : /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(AgentProgressCard, { progress }) : null,
7294
7654
  queueItems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ChatQueue, { items: queueItems, onRemove: onRemoveQueueItem }) : null
7295
7655
  ] }) : null;
@@ -7333,10 +7693,10 @@ function ChatPanel({
7333
7693
 
7334
7694
  // src/components/dialogs/ConfirmMergeRequestDialog.tsx
7335
7695
  var React43 = __toESM(require("react"));
7336
- var import_react_native57 = require("react-native");
7696
+ var import_react_native58 = require("react-native");
7337
7697
 
7338
7698
  // src/components/primitives/Modal.tsx
7339
- var import_react_native56 = require("react-native");
7699
+ var import_react_native57 = require("react-native");
7340
7700
  var import_jsx_runtime58 = require("react/jsx-runtime");
7341
7701
  function Modal2({
7342
7702
  visible,
@@ -7347,15 +7707,15 @@ function Modal2({
7347
7707
  }) {
7348
7708
  const theme = useTheme();
7349
7709
  return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
7350
- import_react_native56.Modal,
7710
+ import_react_native57.Modal,
7351
7711
  {
7352
7712
  visible,
7353
7713
  transparent: true,
7354
7714
  animationType: "fade",
7355
7715
  onRequestClose,
7356
- children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_react_native56.View, { style: { flex: 1, backgroundColor: theme.colors.backdrop, justifyContent: "center", padding: theme.spacing.lg }, children: [
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: [
7357
7717
  /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
7358
- import_react_native56.Pressable,
7718
+ import_react_native57.Pressable,
7359
7719
  {
7360
7720
  accessibilityRole: "button",
7361
7721
  onPress: dismissOnBackdropPress ? onRequestClose : void 0,
@@ -7410,7 +7770,7 @@ function ConfirmMergeRequestDialog({
7410
7770
  backgroundColor: theme.colors.background
7411
7771
  },
7412
7772
  children: [
7413
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_react_native57.View, { children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
7773
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_react_native58.View, { children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
7414
7774
  Text,
7415
7775
  {
7416
7776
  style: {
@@ -7422,9 +7782,9 @@ function ConfirmMergeRequestDialog({
7422
7782
  children: "Are you sure you want to approve this merge request?"
7423
7783
  }
7424
7784
  ) }),
7425
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_react_native57.View, { style: { marginTop: 16 }, children: [
7785
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_react_native58.View, { style: { marginTop: 16 }, children: [
7426
7786
  /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
7427
- import_react_native57.View,
7787
+ import_react_native58.View,
7428
7788
  {
7429
7789
  style: [
7430
7790
  fullWidthButtonBase,
@@ -7434,7 +7794,7 @@ function ConfirmMergeRequestDialog({
7434
7794
  }
7435
7795
  ],
7436
7796
  children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
7437
- import_react_native57.Pressable,
7797
+ import_react_native58.Pressable,
7438
7798
  {
7439
7799
  accessibilityRole: "button",
7440
7800
  accessibilityLabel: "Approve Merge",
@@ -7446,9 +7806,9 @@ function ConfirmMergeRequestDialog({
7446
7806
  )
7447
7807
  }
7448
7808
  ),
7449
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_react_native57.View, { style: { height: 8 } }),
7809
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_react_native58.View, { style: { height: 8 } }),
7450
7810
  /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
7451
- import_react_native57.View,
7811
+ import_react_native58.View,
7452
7812
  {
7453
7813
  style: [
7454
7814
  fullWidthButtonBase,
@@ -7460,7 +7820,7 @@ function ConfirmMergeRequestDialog({
7460
7820
  }
7461
7821
  ],
7462
7822
  children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
7463
- import_react_native57.Pressable,
7823
+ import_react_native58.Pressable,
7464
7824
  {
7465
7825
  accessibilityRole: "button",
7466
7826
  accessibilityLabel: isBuilding ? "Preparing\u2026" : "Test edits first",
@@ -7472,9 +7832,9 @@ function ConfirmMergeRequestDialog({
7472
7832
  )
7473
7833
  }
7474
7834
  ),
7475
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_react_native57.View, { style: { height: 8 } }),
7835
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_react_native58.View, { style: { height: 8 } }),
7476
7836
  /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
7477
- import_react_native57.View,
7837
+ import_react_native58.View,
7478
7838
  {
7479
7839
  style: [
7480
7840
  fullWidthButtonBase,
@@ -7485,7 +7845,7 @@ function ConfirmMergeRequestDialog({
7485
7845
  }
7486
7846
  ],
7487
7847
  children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
7488
- import_react_native57.Pressable,
7848
+ import_react_native58.Pressable,
7489
7849
  {
7490
7850
  accessibilityRole: "button",
7491
7851
  accessibilityLabel: "Cancel",
@@ -7705,7 +8065,7 @@ function StudioOverlay({
7705
8065
  studioControlOptions
7706
8066
  }) {
7707
8067
  const theme = useTheme();
7708
- const { width } = (0, import_react_native58.useWindowDimensions)();
8068
+ const { width } = (0, import_react_native59.useWindowDimensions)();
7709
8069
  const [sheetOpen, setSheetOpen] = React45.useState(false);
7710
8070
  const sheetOpenRef = React45.useRef(sheetOpen);
7711
8071
  const [activePage, setActivePage] = React45.useState("preview");
@@ -7731,7 +8091,7 @@ function StudioOverlay({
7731
8091
  );
7732
8092
  const handleSheetOpenChange = React45.useCallback((open) => {
7733
8093
  setSheetOpen(open);
7734
- if (!open) import_react_native58.Keyboard.dismiss();
8094
+ if (!open) import_react_native59.Keyboard.dismiss();
7735
8095
  }, []);
7736
8096
  const closeSheet = React45.useCallback(() => {
7737
8097
  handleSheetOpenChange(false);
@@ -7742,8 +8102,8 @@ function StudioOverlay({
7742
8102
  openSheet();
7743
8103
  }, [openSheet]);
7744
8104
  const backToPreview = React45.useCallback(() => {
7745
- if (import_react_native58.Platform.OS !== "ios") {
7746
- import_react_native58.Keyboard.dismiss();
8105
+ if (import_react_native59.Platform.OS !== "ios") {
8106
+ import_react_native59.Keyboard.dismiss();
7747
8107
  setActivePage("preview");
7748
8108
  return;
7749
8109
  }
@@ -7755,9 +8115,9 @@ function StudioOverlay({
7755
8115
  clearTimeout(t);
7756
8116
  setActivePage("preview");
7757
8117
  };
7758
- const sub = import_react_native58.Keyboard.addListener("keyboardDidHide", finalize);
8118
+ const sub = import_react_native59.Keyboard.addListener("keyboardDidHide", finalize);
7759
8119
  const t = setTimeout(finalize, 350);
7760
- import_react_native58.Keyboard.dismiss();
8120
+ import_react_native59.Keyboard.dismiss();
7761
8121
  }, []);
7762
8122
  const startDraw = React45.useCallback(() => {
7763
8123
  setDrawing(true);
@@ -7878,7 +8238,7 @@ function StudioOverlay({
7878
8238
  onPress: toggleSheet,
7879
8239
  isLoading: (app == null ? void 0 : app.status) === "editing" || isBaseBundleDownloading,
7880
8240
  loadingBorderTone: isBaseBundleDownloading ? "warning" : "default",
7881
- children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(import_react_native58.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 }) })
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 }) })
7882
8242
  }
7883
8243
  ),
7884
8244
  /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
@@ -8504,6 +8864,7 @@ function ComergeStudio({
8504
8864
  appId,
8505
8865
  clientKey: clientKey2,
8506
8866
  appKey = "MicroMain",
8867
+ analyticsEnabled,
8507
8868
  onNavigateHome,
8508
8869
  style,
8509
8870
  showBubble = true,
@@ -8514,34 +8875,42 @@ function ComergeStudio({
8514
8875
  const [activeAppId, setActiveAppId] = React49.useState(appId);
8515
8876
  const [runtimeAppId, setRuntimeAppId] = React49.useState(appId);
8516
8877
  const [pendingRuntimeTargetAppId, setPendingRuntimeTargetAppId] = React49.useState(null);
8517
- const platform = React49.useMemo(() => import_react_native59.Platform.OS === "ios" ? "ios" : "android", []);
8878
+ const platform = React49.useMemo(() => import_react_native60.Platform.OS === "ios" ? "ios" : "android", []);
8518
8879
  React49.useEffect(() => {
8519
8880
  setActiveAppId(appId);
8520
8881
  setRuntimeAppId(appId);
8521
8882
  setPendingRuntimeTargetAppId(null);
8522
8883
  }, [appId]);
8523
8884
  const captureTargetRef = React49.useRef(null);
8524
- return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(StudioBootstrap, { clientKey: clientKey2, fallback: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_react_native59.View, { style: { flex: 1 } }), 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)(
8525
- ComergeStudioInner,
8885
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
8886
+ StudioBootstrap,
8526
8887
  {
8527
- userId,
8528
- activeAppId,
8529
- setActiveAppId,
8530
- runtimeAppId,
8531
- setRuntimeAppId,
8532
- pendingRuntimeTargetAppId,
8533
- setPendingRuntimeTargetAppId,
8534
- appKey,
8535
- platform,
8536
- onNavigateHome,
8537
- captureTargetRef,
8538
- style,
8539
- showBubble,
8540
- enableAgentProgress,
8541
- studioControlOptions,
8542
- embeddedBaseBundles
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
+ ) }) })
8543
8912
  }
8544
- ) }) }) });
8913
+ );
8545
8914
  }
8546
8915
  function ComergeStudioInner({
8547
8916
  userId,
@@ -8725,7 +9094,7 @@ function ComergeStudioInner({
8725
9094
  }
8726
9095
  return editQueue.items;
8727
9096
  }, [editQueue.items, lastEditQueueInfo, suppressQueueUntilResponse]);
8728
- return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_react_native59.View, { style: [{ flex: 1 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(import_react_native59.View, { ref: captureTargetRef, style: { flex: 1 }, collapsable: false, children: [
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: [
8729
9098
  /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
8730
9099
  RuntimeRenderer,
8731
9100
  {