@comergehq/studio 0.1.6 → 0.1.8

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
@@ -36,8 +36,8 @@ __export(index_exports, {
36
36
  module.exports = __toCommonJS(index_exports);
37
37
 
38
38
  // src/studio/ComergeStudio.tsx
39
- var React38 = __toESM(require("react"));
40
- var import_react_native52 = require("react-native");
39
+ var React39 = __toESM(require("react"));
40
+ var import_react_native53 = require("react-native");
41
41
  var import_bottom_sheet6 = require("@gorhom/bottom-sheet");
42
42
 
43
43
  // src/studio/bootstrap/StudioBootstrap.tsx
@@ -393,7 +393,7 @@ function StudioBootstrap({ children, fallback, renderError, apiKey }) {
393
393
  }
394
394
 
395
395
  // src/studio/hooks/useApp.ts
396
- var React2 = __toESM(require("react"));
396
+ var React3 = __toESM(require("react"));
397
397
 
398
398
  // src/core/services/http/index.ts
399
399
  var import_axios2 = __toESM(require("axios"));
@@ -692,13 +692,40 @@ var AppsRepositoryImpl = class extends BaseRepository {
692
692
  };
693
693
  var appsRepository = new AppsRepositoryImpl(appsRemoteDataSource);
694
694
 
695
+ // src/studio/hooks/useForegroundSignal.ts
696
+ var React2 = __toESM(require("react"));
697
+ var import_react_native4 = require("react-native");
698
+ function useForegroundSignal(enabled = true) {
699
+ const [signal, setSignal] = React2.useState(0);
700
+ const lastStateRef = React2.useRef(import_react_native4.AppState.currentState);
701
+ React2.useEffect(() => {
702
+ if (!enabled) return;
703
+ const sub = import_react_native4.AppState.addEventListener("change", (nextState) => {
704
+ var _a, _b;
705
+ const prevState = lastStateRef.current;
706
+ lastStateRef.current = nextState;
707
+ const didResume = (prevState === "background" || prevState === "inactive") && nextState === "active";
708
+ if (!didResume) return;
709
+ try {
710
+ const supabase = getSupabaseClient();
711
+ (_b = (_a = supabase == null ? void 0 : supabase.realtime) == null ? void 0 : _a.connect) == null ? void 0 : _b.call(_a);
712
+ } catch {
713
+ }
714
+ setSignal((s) => s + 1);
715
+ });
716
+ return () => sub.remove();
717
+ }, [enabled]);
718
+ return signal;
719
+ }
720
+
695
721
  // src/studio/hooks/useApp.ts
696
722
  function useApp(appId, options) {
697
723
  const enabled = (options == null ? void 0 : options.enabled) ?? true;
698
- const [app, setApp] = React2.useState(null);
699
- const [loading, setLoading] = React2.useState(false);
700
- const [error, setError] = React2.useState(null);
701
- const mergeApp = React2.useCallback((prev, next) => {
724
+ const [app, setApp] = React3.useState(null);
725
+ const [loading, setLoading] = React3.useState(false);
726
+ const [error, setError] = React3.useState(null);
727
+ const foregroundSignal = useForegroundSignal(enabled && Boolean(appId));
728
+ const mergeApp = React3.useCallback((prev, next) => {
702
729
  const merged = {
703
730
  ...prev ?? {},
704
731
  ...next,
@@ -707,7 +734,7 @@ function useApp(appId, options) {
707
734
  };
708
735
  return merged;
709
736
  }, []);
710
- const fetchOnce = React2.useCallback(async () => {
737
+ const fetchOnce = React3.useCallback(async () => {
711
738
  if (!enabled) return;
712
739
  if (!appId) return;
713
740
  setLoading(true);
@@ -722,34 +749,37 @@ function useApp(appId, options) {
722
749
  setLoading(false);
723
750
  }
724
751
  }, [appId, enabled]);
725
- React2.useEffect(() => {
752
+ React3.useEffect(() => {
726
753
  if (!enabled) return;
727
754
  void fetchOnce();
728
755
  }, [enabled, fetchOnce]);
729
- React2.useEffect(() => {
756
+ React3.useEffect(() => {
730
757
  if (!enabled) return;
731
758
  if (!appId) return;
732
759
  const unsubscribe = appsRepository.subscribeApp(appId, {
733
760
  onInsert: (a) => {
734
- console.log("[useApp] onInsert", a);
735
761
  setApp((prev) => mergeApp(prev, a));
736
762
  },
737
763
  onUpdate: (a) => {
738
- console.log("[useApp] onUpdate", a);
739
764
  setApp((prev) => mergeApp(prev, a));
740
765
  },
741
766
  onDelete: () => {
742
- console.log("[useApp] onDelete");
743
767
  setApp(null);
744
768
  }
745
769
  });
746
770
  return unsubscribe;
747
- }, [appId, enabled, mergeApp]);
771
+ }, [appId, enabled, mergeApp, foregroundSignal]);
772
+ React3.useEffect(() => {
773
+ if (!enabled) return;
774
+ if (!appId) return;
775
+ if (foregroundSignal <= 0) return;
776
+ void fetchOnce();
777
+ }, [appId, enabled, fetchOnce, foregroundSignal]);
748
778
  return { app, loading, error, refetch: fetchOnce };
749
779
  }
750
780
 
751
781
  // src/studio/hooks/useThreadMessages.ts
752
- var React3 = __toESM(require("react"));
782
+ var React4 = __toESM(require("react"));
753
783
 
754
784
  // src/data/messages/remote.ts
755
785
  var MessagesRemoteDataSourceImpl = class extends BaseRemote {
@@ -850,44 +880,59 @@ function mapMessageToChatMessage(m) {
850
880
  };
851
881
  }
852
882
  function useThreadMessages(threadId) {
853
- const [raw, setRaw] = React3.useState([]);
854
- const [loading, setLoading] = React3.useState(false);
855
- const [error, setError] = React3.useState(null);
856
- const refetch = React3.useCallback(async () => {
883
+ const [raw, setRaw] = React4.useState([]);
884
+ const [loading, setLoading] = React4.useState(false);
885
+ const [error, setError] = React4.useState(null);
886
+ const activeRequestIdRef = React4.useRef(0);
887
+ const foregroundSignal = useForegroundSignal(Boolean(threadId));
888
+ const upsertSorted = React4.useCallback((prev, m) => {
889
+ const next = prev.some((x) => x.id === m.id) ? prev.map((x) => x.id === m.id ? m : x) : [...prev, m];
890
+ next.sort((a, b) => String(a.createdAt).localeCompare(String(b.createdAt)));
891
+ return next;
892
+ }, []);
893
+ const refetch = React4.useCallback(async () => {
857
894
  if (!threadId) {
858
895
  setRaw([]);
859
896
  return;
860
897
  }
898
+ const requestId = ++activeRequestIdRef.current;
861
899
  setLoading(true);
862
900
  setError(null);
863
901
  try {
864
902
  const list = await messagesRepository.list(threadId);
865
- setRaw(list);
903
+ if (activeRequestIdRef.current !== requestId) return;
904
+ setRaw([...list].sort((a, b) => String(a.createdAt).localeCompare(String(b.createdAt))));
866
905
  } catch (e) {
906
+ if (activeRequestIdRef.current !== requestId) return;
867
907
  setError(e instanceof Error ? e : new Error(String(e)));
868
908
  setRaw([]);
869
909
  } finally {
870
- setLoading(false);
910
+ if (activeRequestIdRef.current === requestId) setLoading(false);
871
911
  }
872
912
  }, [threadId]);
873
- React3.useEffect(() => {
913
+ React4.useEffect(() => {
874
914
  void refetch();
875
915
  }, [refetch]);
876
- React3.useEffect(() => {
916
+ React4.useEffect(() => {
877
917
  if (!threadId) return;
878
918
  const unsubscribe = messagesRepository.subscribeThread(threadId, {
879
- onInsert: (m) => setRaw((prev) => [...prev, m]),
880
- onUpdate: (m) => setRaw((prev) => prev.map((x) => x.id === m.id ? m : x)),
919
+ onInsert: (m) => setRaw((prev) => upsertSorted(prev, m)),
920
+ onUpdate: (m) => setRaw((prev) => upsertSorted(prev, m)),
881
921
  onDelete: (m) => setRaw((prev) => prev.filter((x) => x.id !== m.id))
882
922
  });
883
923
  return unsubscribe;
884
- }, [threadId]);
885
- const messages = React3.useMemo(() => raw.map(mapMessageToChatMessage), [raw]);
924
+ }, [threadId, upsertSorted, foregroundSignal]);
925
+ React4.useEffect(() => {
926
+ if (!threadId) return;
927
+ if (foregroundSignal <= 0) return;
928
+ void refetch();
929
+ }, [foregroundSignal, refetch, threadId]);
930
+ const messages = React4.useMemo(() => raw.map(mapMessageToChatMessage), [raw]);
886
931
  return { raw, messages, loading, error, refetch };
887
932
  }
888
933
 
889
934
  // src/studio/hooks/useBundleManager.ts
890
- var React4 = __toESM(require("react"));
935
+ var React5 = __toESM(require("react"));
891
936
  var FileSystem = __toESM(require("expo-file-system/legacy"));
892
937
 
893
938
  // src/data/apps/bundles/remote.ts
@@ -1060,19 +1105,19 @@ function useBundleManager({
1060
1105
  platform,
1061
1106
  canRequestLatest = true
1062
1107
  }) {
1063
- const [bundlePath, setBundlePath] = React4.useState(null);
1064
- const [renderToken, setRenderToken] = React4.useState(0);
1065
- const [loading, setLoading] = React4.useState(false);
1066
- const [statusLabel, setStatusLabel] = React4.useState(null);
1067
- const [error, setError] = React4.useState(null);
1068
- const [isTesting, setIsTesting] = React4.useState(false);
1069
- const baseRef = React4.useRef(base);
1108
+ const [bundlePath, setBundlePath] = React5.useState(null);
1109
+ const [renderToken, setRenderToken] = React5.useState(0);
1110
+ const [loading, setLoading] = React5.useState(false);
1111
+ const [statusLabel, setStatusLabel] = React5.useState(null);
1112
+ const [error, setError] = React5.useState(null);
1113
+ const [isTesting, setIsTesting] = React5.useState(false);
1114
+ const baseRef = React5.useRef(base);
1070
1115
  baseRef.current = base;
1071
- const baseOpIdRef = React4.useRef(0);
1072
- const testOpIdRef = React4.useRef(0);
1073
- const activeLoadModeRef = React4.useRef(null);
1074
- const canRequestLatestRef = React4.useRef(canRequestLatest);
1075
- React4.useEffect(() => {
1116
+ const baseOpIdRef = React5.useRef(0);
1117
+ const testOpIdRef = React5.useRef(0);
1118
+ const activeLoadModeRef = React5.useRef(null);
1119
+ const canRequestLatestRef = React5.useRef(canRequestLatest);
1120
+ React5.useEffect(() => {
1076
1121
  canRequestLatestRef.current = canRequestLatest;
1077
1122
  if (!canRequestLatest) {
1078
1123
  baseOpIdRef.current += 1;
@@ -1083,11 +1128,11 @@ function useBundleManager({
1083
1128
  }
1084
1129
  }
1085
1130
  }, [canRequestLatest]);
1086
- const lastBaseBundlePathRef = React4.useRef(null);
1087
- const lastBaseFingerprintRef = React4.useRef(null);
1088
- const initialHydratedBaseFromDiskRef = React4.useRef(false);
1089
- const hasCompletedFirstNetworkBaseLoadRef = React4.useRef(false);
1090
- const hydrateBaseFromDisk = React4.useCallback(
1131
+ const lastBaseBundlePathRef = React5.useRef(null);
1132
+ const lastBaseFingerprintRef = React5.useRef(null);
1133
+ const initialHydratedBaseFromDiskRef = React5.useRef(false);
1134
+ const hasCompletedFirstNetworkBaseLoadRef = React5.useRef(false);
1135
+ const hydrateBaseFromDisk = React5.useCallback(
1091
1136
  async (appId, reason) => {
1092
1137
  try {
1093
1138
  const dir = bundlesCacheDir();
@@ -1112,13 +1157,13 @@ function useBundleManager({
1112
1157
  },
1113
1158
  [platform]
1114
1159
  );
1115
- React4.useEffect(() => {
1160
+ React5.useEffect(() => {
1116
1161
  if (!base.appId) return;
1117
1162
  initialHydratedBaseFromDiskRef.current = false;
1118
1163
  hasCompletedFirstNetworkBaseLoadRef.current = false;
1119
1164
  void hydrateBaseFromDisk(base.appId, "initial");
1120
1165
  }, [base.appId, platform, hydrateBaseFromDisk]);
1121
- const activateCachedBase = React4.useCallback(
1166
+ const activateCachedBase = React5.useCallback(
1122
1167
  async (appId) => {
1123
1168
  setIsTesting(false);
1124
1169
  setStatusLabel(null);
@@ -1132,7 +1177,7 @@ function useBundleManager({
1132
1177
  },
1133
1178
  [hydrateBaseFromDisk]
1134
1179
  );
1135
- const load = React4.useCallback(async (src, mode) => {
1180
+ const load = React5.useCallback(async (src, mode) => {
1136
1181
  if (!src.appId) return;
1137
1182
  const canRequestLatest2 = canRequestLatestRef.current;
1138
1183
  if (mode === "base" && !canRequestLatest2) {
@@ -1187,13 +1232,13 @@ function useBundleManager({
1187
1232
  if (activeLoadModeRef.current === mode) activeLoadModeRef.current = null;
1188
1233
  }
1189
1234
  }, [activateCachedBase, platform]);
1190
- const loadBase = React4.useCallback(async () => {
1235
+ const loadBase = React5.useCallback(async () => {
1191
1236
  await load(baseRef.current, "base");
1192
1237
  }, [load]);
1193
- const loadTest = React4.useCallback(async (src) => {
1238
+ const loadTest = React5.useCallback(async (src) => {
1194
1239
  await load(src, "test");
1195
1240
  }, [load]);
1196
- const restoreBase = React4.useCallback(async () => {
1241
+ const restoreBase = React5.useCallback(async () => {
1197
1242
  const src = baseRef.current;
1198
1243
  if (!src.appId) return;
1199
1244
  await activateCachedBase(src.appId);
@@ -1201,7 +1246,7 @@ function useBundleManager({
1201
1246
  await load(src, "base");
1202
1247
  }
1203
1248
  }, [activateCachedBase, load]);
1204
- React4.useEffect(() => {
1249
+ React5.useEffect(() => {
1205
1250
  if (!canRequestLatest) return;
1206
1251
  void loadBase();
1207
1252
  }, [base.appId, base.commitId, platform, canRequestLatest, loadBase]);
@@ -1209,7 +1254,7 @@ function useBundleManager({
1209
1254
  }
1210
1255
 
1211
1256
  // src/studio/hooks/useMergeRequests.ts
1212
- var React5 = __toESM(require("react"));
1257
+ var React6 = __toESM(require("react"));
1213
1258
 
1214
1259
  // src/data/merge-requests/remote.ts
1215
1260
  var MergeRequestsRemoteDataSourceImpl = class extends BaseRemote {
@@ -1355,12 +1400,12 @@ function toUiStatus(status) {
1355
1400
  }
1356
1401
  function useMergeRequests(params) {
1357
1402
  const { appId } = params;
1358
- const [incoming, setIncoming] = React5.useState([]);
1359
- const [outgoing, setOutgoing] = React5.useState([]);
1360
- const [loading, setLoading] = React5.useState(false);
1361
- const [error, setError] = React5.useState(null);
1362
- const [creatorStatsById, setCreatorStatsById] = React5.useState({});
1363
- const pollUntilMerged = React5.useCallback(async (mrId) => {
1403
+ const [incoming, setIncoming] = React6.useState([]);
1404
+ const [outgoing, setOutgoing] = React6.useState([]);
1405
+ const [loading, setLoading] = React6.useState(false);
1406
+ const [error, setError] = React6.useState(null);
1407
+ const [creatorStatsById, setCreatorStatsById] = React6.useState({});
1408
+ const pollUntilMerged = React6.useCallback(async (mrId) => {
1364
1409
  const startedAt = Date.now();
1365
1410
  const timeoutMs = 2 * 60 * 1e3;
1366
1411
  for (; ; ) {
@@ -1370,7 +1415,7 @@ function useMergeRequests(params) {
1370
1415
  await new Promise((r) => setTimeout(r, 1500));
1371
1416
  }
1372
1417
  }, []);
1373
- const refresh = React5.useCallback(async () => {
1418
+ const refresh = React6.useCallback(async () => {
1374
1419
  if (!appId) {
1375
1420
  setIncoming([]);
1376
1421
  setOutgoing([]);
@@ -1409,27 +1454,27 @@ function useMergeRequests(params) {
1409
1454
  setLoading(false);
1410
1455
  }
1411
1456
  }, [appId]);
1412
- React5.useEffect(() => {
1457
+ React6.useEffect(() => {
1413
1458
  void refresh();
1414
1459
  }, [refresh]);
1415
- const openMergeRequest = React5.useCallback(async (sourceAppId) => {
1460
+ const openMergeRequest = React6.useCallback(async (sourceAppId) => {
1416
1461
  const mr = await mergeRequestsRepository.open({ sourceAppId });
1417
1462
  await refresh();
1418
1463
  return mr;
1419
1464
  }, [refresh]);
1420
- const approve = React5.useCallback(async (mrId) => {
1465
+ const approve = React6.useCallback(async (mrId) => {
1421
1466
  const mr = await mergeRequestsRepository.update(mrId, { status: "approved" });
1422
1467
  await refresh();
1423
1468
  const merged = await pollUntilMerged(mrId);
1424
1469
  await refresh();
1425
1470
  return merged ?? mr;
1426
1471
  }, [pollUntilMerged, refresh]);
1427
- const reject = React5.useCallback(async (mrId) => {
1472
+ const reject = React6.useCallback(async (mrId) => {
1428
1473
  const mr = await mergeRequestsRepository.update(mrId, { status: "rejected" });
1429
1474
  await refresh();
1430
1475
  return mr;
1431
1476
  }, [refresh]);
1432
- const toSummary = React5.useCallback((mr) => {
1477
+ const toSummary = React6.useCallback((mr) => {
1433
1478
  const stats = creatorStatsById[mr.createdBy];
1434
1479
  return {
1435
1480
  id: mr.id,
@@ -1445,7 +1490,7 @@ function useMergeRequests(params) {
1445
1490
  updatedAt: mr.updatedAt
1446
1491
  };
1447
1492
  }, [creatorStatsById]);
1448
- const byId = React5.useMemo(() => {
1493
+ const byId = React6.useMemo(() => {
1449
1494
  const all = [...incoming, ...outgoing];
1450
1495
  const map = {};
1451
1496
  for (const mr of all) map[mr.id] = mr;
@@ -1463,7 +1508,7 @@ function useMergeRequests(params) {
1463
1508
  }
1464
1509
 
1465
1510
  // src/studio/hooks/useAttachmentUpload.ts
1466
- var React6 = __toESM(require("react"));
1511
+ var React7 = __toESM(require("react"));
1467
1512
 
1468
1513
  // src/data/attachment/remote.ts
1469
1514
  var AttachmentRemoteDataSourceImpl = class extends BaseRemote {
@@ -1504,9 +1549,9 @@ var attachmentRepository = new AttachmentRepositoryImpl(
1504
1549
 
1505
1550
  // src/studio/hooks/useAttachmentUpload.ts
1506
1551
  function useAttachmentUpload() {
1507
- const [uploading, setUploading] = React6.useState(false);
1508
- const [error, setError] = React6.useState(null);
1509
- const uploadBase64Images = React6.useCallback(async ({ threadId, appId, dataUrls }) => {
1552
+ const [uploading, setUploading] = React7.useState(false);
1553
+ const [error, setError] = React7.useState(null);
1554
+ const uploadBase64Images = React7.useCallback(async ({ threadId, appId, dataUrls }) => {
1510
1555
  if (!threadId || !appId) return [];
1511
1556
  if (!dataUrls || dataUrls.length === 0) return [];
1512
1557
  setUploading(true);
@@ -1540,7 +1585,7 @@ function useAttachmentUpload() {
1540
1585
  }
1541
1586
 
1542
1587
  // src/studio/hooks/useStudioActions.ts
1543
- var React7 = __toESM(require("react"));
1588
+ var React8 = __toESM(require("react"));
1544
1589
 
1545
1590
  // src/data/agent/remote.ts
1546
1591
  var AgentRemoteDataSourceImpl = class extends BaseRemote {
@@ -1579,12 +1624,12 @@ function useStudioActions({
1579
1624
  onForkedApp,
1580
1625
  uploadAttachments
1581
1626
  }) {
1582
- const [forking, setForking] = React7.useState(false);
1583
- const [sending, setSending] = React7.useState(false);
1584
- const [error, setError] = React7.useState(null);
1627
+ const [forking, setForking] = React8.useState(false);
1628
+ const [sending, setSending] = React8.useState(false);
1629
+ const [error, setError] = React8.useState(null);
1585
1630
  const isOwner = Boolean(userId && (app == null ? void 0 : app.createdBy) && userId === app.createdBy);
1586
1631
  const shouldForkOnEdit = Boolean(userId && app && app.createdBy !== userId);
1587
- const sendEdit = React7.useCallback(
1632
+ const sendEdit = React8.useCallback(
1588
1633
  async ({ prompt, attachments }) => {
1589
1634
  if (!userId || !app) return;
1590
1635
  if (!prompt.trim()) return;
@@ -1647,14 +1692,14 @@ function hasNoOutcomeAfterLastHuman(messages) {
1647
1692
  }
1648
1693
 
1649
1694
  // src/studio/ui/RuntimeRenderer.tsx
1650
- var import_react_native4 = require("react-native");
1695
+ var import_react_native5 = require("react-native");
1651
1696
  var import_runtime = require("@comergehq/runtime");
1652
1697
  var import_jsx_runtime3 = require("react/jsx-runtime");
1653
1698
  function RuntimeRenderer({ appKey, bundlePath, renderToken, style }) {
1654
1699
  if (!bundlePath) {
1655
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.View, { style: [{ flex: 1, justifyContent: "center", alignItems: "center", padding: 24 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { variant: "bodyMuted", children: "Preparing app\u2026" }) });
1700
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native5.View, { style: [{ flex: 1, justifyContent: "center", alignItems: "center", padding: 24 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { variant: "bodyMuted", children: "Preparing app\u2026" }) });
1656
1701
  }
1657
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.View, { style: [{ flex: 1 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1702
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native5.View, { style: [{ flex: 1 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1658
1703
  import_runtime.ComergeRuntimeRenderer,
1659
1704
  {
1660
1705
  appKey,
@@ -1666,17 +1711,17 @@ function RuntimeRenderer({ appKey, bundlePath, renderToken, style }) {
1666
1711
  }
1667
1712
 
1668
1713
  // src/studio/ui/StudioOverlay.tsx
1669
- var React37 = __toESM(require("react"));
1670
- var import_react_native51 = require("react-native");
1714
+ var React38 = __toESM(require("react"));
1715
+ var import_react_native52 = require("react-native");
1671
1716
 
1672
1717
  // src/components/studio-sheet/StudioBottomSheet.tsx
1673
- var React8 = __toESM(require("react"));
1674
- var import_react_native6 = require("react-native");
1718
+ var React9 = __toESM(require("react"));
1719
+ var import_react_native7 = require("react-native");
1675
1720
  var import_bottom_sheet = __toESM(require("@gorhom/bottom-sheet"));
1676
1721
  var import_react_native_safe_area_context = require("react-native-safe-area-context");
1677
1722
 
1678
1723
  // src/components/studio-sheet/StudioSheetBackground.tsx
1679
- var import_react_native5 = require("react-native");
1724
+ var import_react_native6 = require("react-native");
1680
1725
  var import_liquid_glass = require("@callstack/liquid-glass");
1681
1726
  var import_jsx_runtime4 = require("react/jsx-runtime");
1682
1727
  function StudioSheetBackground({
@@ -1684,7 +1729,7 @@ function StudioSheetBackground({
1684
1729
  renderBackground
1685
1730
  }) {
1686
1731
  const theme = useTheme();
1687
- const radius = import_react_native5.Platform.OS === "ios" ? 39 : 16;
1732
+ const radius = import_react_native6.Platform.OS === "ios" ? 39 : 16;
1688
1733
  const fallbackBgColor = theme.scheme === "dark" ? "rgba(11, 8, 15, 0.85)" : "rgba(255, 255, 255, 0.85)";
1689
1734
  const secondaryBgBaseColor = theme.scheme === "dark" ? "rgb(24, 24, 27)" : "rgb(173, 173, 173)";
1690
1735
  const containerStyle = {
@@ -1705,7 +1750,7 @@ function StudioSheetBackground({
1705
1750
  }
1706
1751
  ),
1707
1752
  import_liquid_glass.isLiquidGlassSupported && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1708
- import_react_native5.View,
1753
+ import_react_native6.View,
1709
1754
  {
1710
1755
  style: [
1711
1756
  containerStyle,
@@ -1738,19 +1783,43 @@ function StudioBottomSheet({
1738
1783
  }) {
1739
1784
  const theme = useTheme();
1740
1785
  const insets = (0, import_react_native_safe_area_context.useSafeAreaInsets)();
1741
- const internalSheetRef = React8.useRef(null);
1786
+ const internalSheetRef = React9.useRef(null);
1742
1787
  const resolvedSheetRef = sheetRef ?? internalSheetRef;
1743
- React8.useEffect(() => {
1744
- if (import_react_native6.Platform.OS !== "ios") return;
1745
- const sub = import_react_native6.Keyboard.addListener("keyboardDidHide", () => {
1788
+ const currentIndexRef = React9.useRef(open ? snapPoints.length - 1 : -1);
1789
+ const lastAppStateRef = React9.useRef(import_react_native7.AppState.currentState);
1790
+ React9.useEffect(() => {
1791
+ const sub = import_react_native7.AppState.addEventListener("change", (state) => {
1792
+ const prev = lastAppStateRef.current;
1793
+ lastAppStateRef.current = state;
1794
+ if (state === "background" || state === "inactive") {
1795
+ import_react_native7.Keyboard.dismiss();
1796
+ return;
1797
+ }
1798
+ if (state !== "active") return;
1799
+ const sheet = resolvedSheetRef.current;
1800
+ if (!sheet) return;
1801
+ const idx = currentIndexRef.current;
1802
+ if (open && idx >= 0) {
1803
+ import_react_native7.Keyboard.dismiss();
1804
+ requestAnimationFrame(() => sheet.snapToIndex(idx));
1805
+ setTimeout(() => sheet.snapToIndex(idx), 120);
1806
+ }
1807
+ });
1808
+ return () => sub.remove();
1809
+ }, [open, resolvedSheetRef]);
1810
+ React9.useEffect(() => {
1811
+ if (import_react_native7.Platform.OS !== "ios") return;
1812
+ const sub = import_react_native7.Keyboard.addListener("keyboardDidHide", () => {
1746
1813
  const sheet = resolvedSheetRef.current;
1747
1814
  if (!sheet || !open) return;
1748
1815
  const targetIndex = snapPoints.length - 1;
1749
- setTimeout(() => sheet.snapToIndex(targetIndex), 10);
1816
+ if (currentIndexRef.current === targetIndex) {
1817
+ setTimeout(() => sheet.snapToIndex(targetIndex), 10);
1818
+ }
1750
1819
  });
1751
1820
  return () => sub.remove();
1752
1821
  }, [open, resolvedSheetRef, snapPoints.length]);
1753
- React8.useEffect(() => {
1822
+ React9.useEffect(() => {
1754
1823
  const sheet = resolvedSheetRef.current;
1755
1824
  if (!sheet) return;
1756
1825
  if (open) {
@@ -1759,8 +1828,9 @@ function StudioBottomSheet({
1759
1828
  sheet.close();
1760
1829
  }
1761
1830
  }, [open, resolvedSheetRef, snapPoints.length]);
1762
- const handleChange = React8.useCallback(
1831
+ const handleChange = React9.useCallback(
1763
1832
  (index) => {
1833
+ currentIndexRef.current = index;
1764
1834
  onOpenChange == null ? void 0 : onOpenChange(index >= 0);
1765
1835
  },
1766
1836
  [onOpenChange]
@@ -1772,7 +1842,7 @@ function StudioBottomSheet({
1772
1842
  index: open ? snapPoints.length - 1 : -1,
1773
1843
  snapPoints,
1774
1844
  enablePanDownToClose: true,
1775
- keyboardBehavior: import_react_native6.Platform.OS === "ios" ? "interactive" : "extend",
1845
+ keyboardBehavior: "interactive",
1776
1846
  keyboardBlurBehavior: "restore",
1777
1847
  android_keyboardInputMode: "adjustResize",
1778
1848
  backgroundComponent: (props) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(StudioSheetBackground, { ...props, renderBackground: background == null ? void 0 : background.renderBackground }),
@@ -1781,19 +1851,19 @@ function StudioBottomSheet({
1781
1851
  handleIndicatorStyle: { backgroundColor: theme.colors.handleIndicator },
1782
1852
  onChange: handleChange,
1783
1853
  ...bottomSheetProps,
1784
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native6.View, { style: { flex: 1, overflow: "hidden" }, children })
1854
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native7.View, { style: { flex: 1, overflow: "hidden" }, children })
1785
1855
  }
1786
1856
  );
1787
1857
  }
1788
1858
 
1789
1859
  // src/components/studio-sheet/StudioSheetPager.tsx
1790
- var React9 = __toESM(require("react"));
1791
- var import_react_native7 = require("react-native");
1860
+ var React10 = __toESM(require("react"));
1861
+ var import_react_native8 = require("react-native");
1792
1862
  var import_jsx_runtime6 = require("react/jsx-runtime");
1793
1863
  function StudioSheetPager({ activePage, width, preview, chat, style }) {
1794
- const anim = React9.useRef(new import_react_native7.Animated.Value(activePage === "chat" ? 1 : 0)).current;
1795
- React9.useEffect(() => {
1796
- import_react_native7.Animated.spring(anim, {
1864
+ const anim = React10.useRef(new import_react_native8.Animated.Value(activePage === "chat" ? 1 : 0)).current;
1865
+ React10.useEffect(() => {
1866
+ import_react_native8.Animated.spring(anim, {
1797
1867
  toValue: activePage === "chat" ? 1 : 0,
1798
1868
  useNativeDriver: true,
1799
1869
  tension: 65,
@@ -1802,9 +1872,9 @@ function StudioSheetPager({ activePage, width, preview, chat, style }) {
1802
1872
  }, [activePage, anim]);
1803
1873
  const previewTranslateX = anim.interpolate({ inputRange: [0, 1], outputRange: [0, -width] });
1804
1874
  const chatTranslateX = anim.interpolate({ inputRange: [0, 1], outputRange: [width, 0] });
1805
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react_native7.Animated.View, { style: [{ flex: 1 }, style], children: [
1875
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react_native8.Animated.View, { style: [{ flex: 1 }, style], children: [
1806
1876
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1807
- import_react_native7.Animated.View,
1877
+ import_react_native8.Animated.View,
1808
1878
  {
1809
1879
  style: [
1810
1880
  {
@@ -1821,7 +1891,7 @@ function StudioSheetPager({ activePage, width, preview, chat, style }) {
1821
1891
  }
1822
1892
  ),
1823
1893
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1824
- import_react_native7.Animated.View,
1894
+ import_react_native8.Animated.View,
1825
1895
  {
1826
1896
  style: [
1827
1897
  {
@@ -1842,7 +1912,7 @@ function StudioSheetPager({ activePage, width, preview, chat, style }) {
1842
1912
 
1843
1913
  // src/components/floating-draggable-button/FloatingDraggableButton.tsx
1844
1914
  var import_react = require("react");
1845
- var import_react_native8 = require("react-native");
1915
+ var import_react_native9 = require("react-native");
1846
1916
  var Haptics = __toESM(require("expo-haptics"));
1847
1917
  var import_react_native_reanimated = __toESM(require("react-native-reanimated"));
1848
1918
  var import_liquid_glass2 = require("@callstack/liquid-glass");
@@ -1901,7 +1971,7 @@ function FloatingDraggableButton({
1901
1971
  backgroundColor
1902
1972
  }) {
1903
1973
  const theme = useTheme();
1904
- const { width, height } = (0, import_react_native8.useWindowDimensions)();
1974
+ const { width, height } = (0, import_react_native9.useWindowDimensions)();
1905
1975
  const isDanger = variant === "danger";
1906
1976
  const onPressRef = (0, import_react.useRef)(onPress);
1907
1977
  (0, import_react.useEffect)(() => {
@@ -2004,7 +2074,7 @@ function FloatingDraggableButton({
2004
2074
  }
2005
2075
  }, [forceShowTrigger, visible, animateIn]);
2006
2076
  const panResponder = (0, import_react.useRef)(
2007
- import_react_native8.PanResponder.create({
2077
+ import_react_native9.PanResponder.create({
2008
2078
  onStartShouldSetPanResponder: () => true,
2009
2079
  onMoveShouldSetPanResponder: () => true,
2010
2080
  onPanResponderGrant: () => {
@@ -2067,24 +2137,24 @@ function FloatingDraggableButton({
2067
2137
  interactive: true,
2068
2138
  effect: "clear",
2069
2139
  children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2070
- import_react_native8.Pressable,
2140
+ import_react_native9.Pressable,
2071
2141
  {
2072
2142
  onPress: () => {
2073
2143
  if (!disabled) animateOut();
2074
2144
  },
2075
2145
  style: styles.buttonInner,
2076
2146
  android_ripple: { color: "rgba(255, 255, 255, 0.3)", borderless: true },
2077
- children: children ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native8.View, {})
2147
+ children: children ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native9.View, {})
2078
2148
  }
2079
2149
  )
2080
2150
  }
2081
2151
  ) }),
2082
- badgeCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native8.View, { style: [styles.badge, { backgroundColor: theme.colors.danger }], children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native8.Text, { style: [styles.badgeText, { color: theme.colors.onDanger }], children: badgeCount > 99 ? "99+" : badgeCount }) })
2152
+ badgeCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native9.View, { style: [styles.badge, { backgroundColor: theme.colors.danger }], children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native9.Text, { style: [styles.badgeText, { color: theme.colors.onDanger }], children: badgeCount > 99 ? "99+" : badgeCount }) })
2083
2153
  ]
2084
2154
  }
2085
2155
  );
2086
2156
  }
2087
- var styles = import_react_native8.StyleSheet.create({
2157
+ var styles = import_react_native9.StyleSheet.create({
2088
2158
  floatingButton: {
2089
2159
  position: "absolute",
2090
2160
  justifyContent: "center",
@@ -2120,8 +2190,8 @@ var styles = import_react_native8.StyleSheet.create({
2120
2190
  });
2121
2191
 
2122
2192
  // src/components/overlays/EdgeGlowFrame.tsx
2123
- var React10 = __toESM(require("react"));
2124
- var import_react_native9 = require("react-native");
2193
+ var React11 = __toESM(require("react"));
2194
+ var import_react_native10 = require("react-native");
2125
2195
  var import_expo_linear_gradient = require("expo-linear-gradient");
2126
2196
 
2127
2197
  // src/components/utils/color.ts
@@ -2163,9 +2233,9 @@ function EdgeGlowFrame({
2163
2233
  }) {
2164
2234
  const theme = useTheme();
2165
2235
  const alpha = Math.max(0, Math.min(1, intensity));
2166
- const anim = React10.useRef(new import_react_native9.Animated.Value(visible ? 1 : 0)).current;
2167
- React10.useEffect(() => {
2168
- import_react_native9.Animated.timing(anim, {
2236
+ const anim = React11.useRef(new import_react_native10.Animated.Value(visible ? 1 : 0)).current;
2237
+ React11.useEffect(() => {
2238
+ import_react_native10.Animated.timing(anim, {
2169
2239
  toValue: visible ? 1 : 0,
2170
2240
  duration: 300,
2171
2241
  useNativeDriver: true
@@ -2174,8 +2244,8 @@ function EdgeGlowFrame({
2174
2244
  const c = baseColor(role, theme);
2175
2245
  const strong = withAlpha(c, 0.6 * alpha);
2176
2246
  const soft = withAlpha(c, 0.22 * alpha);
2177
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.Animated.View, { pointerEvents: "none", style: [{ position: "absolute", inset: 0, opacity: anim }, style], children: [
2178
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native9.View, { style: { position: "absolute", top: 0, left: 0, right: 0, height: thickness }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2247
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native10.Animated.View, { pointerEvents: "none", style: [{ position: "absolute", inset: 0, opacity: anim }, style], children: [
2248
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native10.View, { style: { position: "absolute", top: 0, left: 0, right: 0, height: thickness }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2179
2249
  import_expo_linear_gradient.LinearGradient,
2180
2250
  {
2181
2251
  colors: [strong, soft, "transparent"],
@@ -2184,7 +2254,7 @@ function EdgeGlowFrame({
2184
2254
  style: { width: "100%", height: "100%" }
2185
2255
  }
2186
2256
  ) }),
2187
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native9.View, { style: { position: "absolute", bottom: 0, left: 0, right: 0, height: thickness }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2257
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native10.View, { style: { position: "absolute", bottom: 0, left: 0, right: 0, height: thickness }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2188
2258
  import_expo_linear_gradient.LinearGradient,
2189
2259
  {
2190
2260
  colors: ["transparent", soft, strong],
@@ -2193,7 +2263,7 @@ function EdgeGlowFrame({
2193
2263
  style: { width: "100%", height: "100%" }
2194
2264
  }
2195
2265
  ) }),
2196
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native9.View, { style: { position: "absolute", top: 0, bottom: 0, left: 0, width: thickness }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2266
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native10.View, { style: { position: "absolute", top: 0, bottom: 0, left: 0, width: thickness }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2197
2267
  import_expo_linear_gradient.LinearGradient,
2198
2268
  {
2199
2269
  colors: [strong, soft, "transparent"],
@@ -2202,7 +2272,7 @@ function EdgeGlowFrame({
2202
2272
  style: { width: "100%", height: "100%" }
2203
2273
  }
2204
2274
  ) }),
2205
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native9.View, { style: { position: "absolute", top: 0, bottom: 0, right: 0, width: thickness }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2275
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native10.View, { style: { position: "absolute", top: 0, bottom: 0, right: 0, width: thickness }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2206
2276
  import_expo_linear_gradient.LinearGradient,
2207
2277
  {
2208
2278
  colors: ["transparent", soft, strong],
@@ -2215,13 +2285,13 @@ function EdgeGlowFrame({
2215
2285
  }
2216
2286
 
2217
2287
  // src/components/draw/DrawModeOverlay.tsx
2218
- var React13 = __toESM(require("react"));
2219
- var import_react_native13 = require("react-native");
2288
+ var React14 = __toESM(require("react"));
2289
+ var import_react_native14 = require("react-native");
2220
2290
  var import_react_native_view_shot = require("react-native-view-shot");
2221
2291
 
2222
2292
  // src/components/draw/DrawSurface.tsx
2223
- var React11 = __toESM(require("react"));
2224
- var import_react_native10 = require("react-native");
2293
+ var React12 = __toESM(require("react"));
2294
+ var import_react_native11 = require("react-native");
2225
2295
  var import_react_native_svg = __toESM(require("react-native-svg"));
2226
2296
 
2227
2297
  // src/components/draw/strokes.ts
@@ -2252,25 +2322,25 @@ function DrawSurface({
2252
2322
  style,
2253
2323
  minDistance = 1
2254
2324
  }) {
2255
- const [renderTick, setRenderTick] = React11.useState(0);
2256
- const currentPointsRef = React11.useRef([]);
2257
- const rafRef = React11.useRef(null);
2258
- const triggerRender = React11.useCallback(() => {
2325
+ const [renderTick, setRenderTick] = React12.useState(0);
2326
+ const currentPointsRef = React12.useRef([]);
2327
+ const rafRef = React12.useRef(null);
2328
+ const triggerRender = React12.useCallback(() => {
2259
2329
  if (rafRef.current !== null) return;
2260
2330
  rafRef.current = requestAnimationFrame(() => {
2261
2331
  rafRef.current = null;
2262
2332
  setRenderTick((n) => n + 1);
2263
2333
  });
2264
2334
  }, []);
2265
- React11.useEffect(() => () => {
2335
+ React12.useEffect(() => () => {
2266
2336
  if (rafRef.current !== null) cancelAnimationFrame(rafRef.current);
2267
2337
  }, []);
2268
- const onStart = React11.useCallback((e) => {
2338
+ const onStart = React12.useCallback((e) => {
2269
2339
  const { locationX, locationY } = e.nativeEvent;
2270
2340
  currentPointsRef.current = [{ x: locationX, y: locationY }];
2271
2341
  triggerRender();
2272
2342
  }, [triggerRender]);
2273
- const onMove = React11.useCallback((e, _g) => {
2343
+ const onMove = React12.useCallback((e, _g) => {
2274
2344
  const { locationX, locationY } = e.nativeEvent;
2275
2345
  const pts = currentPointsRef.current;
2276
2346
  if (pts.length > 0) {
@@ -2283,7 +2353,7 @@ function DrawSurface({
2283
2353
  currentPointsRef.current = [...pts, { x: locationX, y: locationY }];
2284
2354
  triggerRender();
2285
2355
  }, [minDistance, triggerRender]);
2286
- const onEnd = React11.useCallback(() => {
2356
+ const onEnd = React12.useCallback(() => {
2287
2357
  const points = currentPointsRef.current;
2288
2358
  if (points.length > 0) {
2289
2359
  onAddStroke({ points, color, width: strokeWidth });
@@ -2291,8 +2361,8 @@ function DrawSurface({
2291
2361
  currentPointsRef.current = [];
2292
2362
  triggerRender();
2293
2363
  }, [color, onAddStroke, strokeWidth, triggerRender]);
2294
- const panResponder = React11.useMemo(
2295
- () => import_react_native10.PanResponder.create({
2364
+ const panResponder = React12.useMemo(
2365
+ () => import_react_native11.PanResponder.create({
2296
2366
  onStartShouldSetPanResponder: () => true,
2297
2367
  onMoveShouldSetPanResponder: () => true,
2298
2368
  onPanResponderGrant: onStart,
@@ -2304,7 +2374,7 @@ function DrawSurface({
2304
2374
  );
2305
2375
  const currentPath = pointsToSmoothPath(currentPointsRef.current);
2306
2376
  void renderTick;
2307
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native10.View, { style: [import_react_native10.StyleSheet.absoluteFill, styles2.container, style], ...panResponder.panHandlers, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native_svg.default, { style: import_react_native10.StyleSheet.absoluteFill, width: "100%", height: "100%", children: [
2377
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native11.View, { style: [import_react_native11.StyleSheet.absoluteFill, styles2.container, style], ...panResponder.panHandlers, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native_svg.default, { style: import_react_native11.StyleSheet.absoluteFill, width: "100%", height: "100%", children: [
2308
2378
  strokes.map((s, idx) => {
2309
2379
  const d = pointsToSmoothPath(s.points);
2310
2380
  if (!d) return null;
@@ -2334,15 +2404,15 @@ function DrawSurface({
2334
2404
  ) : null
2335
2405
  ] }) });
2336
2406
  }
2337
- var styles2 = import_react_native10.StyleSheet.create({
2407
+ var styles2 = import_react_native11.StyleSheet.create({
2338
2408
  container: {
2339
2409
  zIndex: 5
2340
2410
  }
2341
2411
  });
2342
2412
 
2343
2413
  // src/components/draw/DrawToolbar.tsx
2344
- var React12 = __toESM(require("react"));
2345
- var import_react_native12 = require("react-native");
2414
+ var React13 = __toESM(require("react"));
2415
+ var import_react_native13 = require("react-native");
2346
2416
  var import_react_native_safe_area_context2 = require("react-native-safe-area-context");
2347
2417
  var import_lucide_react_native = require("lucide-react-native");
2348
2418
 
@@ -2361,7 +2431,7 @@ async function impact(style) {
2361
2431
  }
2362
2432
 
2363
2433
  // src/components/draw/DrawColorPicker.tsx
2364
- var import_react_native11 = require("react-native");
2434
+ var import_react_native12 = require("react-native");
2365
2435
  var import_jsx_runtime10 = require("react/jsx-runtime");
2366
2436
  function DrawColorPicker({
2367
2437
  colors,
@@ -2396,10 +2466,10 @@ function DrawColorPicker({
2396
2466
  return { ...base, ...selectedStyle, ...whiteStyle };
2397
2467
  };
2398
2468
  if (!expanded) {
2399
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native11.Pressable, { onPress: onToggle, style: [swatchStyle(selected, true), style] });
2469
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native12.Pressable, { onPress: onToggle, style: [swatchStyle(selected, true), style] });
2400
2470
  }
2401
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native11.View, { style: [{ flexDirection: "row", alignItems: "center", gap: 8 }, style], children: colors.map((c, idx) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2402
- import_react_native11.Pressable,
2471
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native12.View, { style: [{ flexDirection: "row", alignItems: "center", gap: 8 }, style], children: colors.map((c, idx) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2472
+ import_react_native12.Pressable,
2403
2473
  {
2404
2474
  onPress: () => {
2405
2475
  onSelect(c);
@@ -2430,14 +2500,14 @@ function DrawToolbar({
2430
2500
  style
2431
2501
  }) {
2432
2502
  const insets = (0, import_react_native_safe_area_context2.useSafeAreaInsets)();
2433
- const { width: screenWidth, height: screenHeight } = (0, import_react_native12.useWindowDimensions)();
2434
- const [expanded, setExpanded] = React12.useState(false);
2435
- const pos = React12.useRef(new import_react_native12.Animated.ValueXY({ x: screenWidth / 2 - 110, y: -140 })).current;
2436
- const start = React12.useRef({ x: 0, y: 0 });
2437
- const currentPos = React12.useRef({ x: 0, y: 0 });
2438
- React12.useEffect(() => {
2503
+ const { width: screenWidth, height: screenHeight } = (0, import_react_native13.useWindowDimensions)();
2504
+ const [expanded, setExpanded] = React13.useState(false);
2505
+ const pos = React13.useRef(new import_react_native13.Animated.ValueXY({ x: screenWidth / 2 - 110, y: -140 })).current;
2506
+ const start = React13.useRef({ x: 0, y: 0 });
2507
+ const currentPos = React13.useRef({ x: 0, y: 0 });
2508
+ React13.useEffect(() => {
2439
2509
  if (hidden) return;
2440
- import_react_native12.Animated.spring(pos.y, {
2510
+ import_react_native13.Animated.spring(pos.y, {
2441
2511
  toValue: insets.top + 60,
2442
2512
  useNativeDriver: true,
2443
2513
  damping: 12,
@@ -2445,7 +2515,7 @@ function DrawToolbar({
2445
2515
  mass: 0.8
2446
2516
  }).start();
2447
2517
  }, [hidden, insets.top, pos.y]);
2448
- React12.useEffect(() => {
2518
+ React13.useEffect(() => {
2449
2519
  const id = pos.addListener((v) => {
2450
2520
  currentPos.current = { x: v.x ?? 0, y: v.y ?? 0 };
2451
2521
  });
@@ -2453,7 +2523,7 @@ function DrawToolbar({
2453
2523
  pos.removeListener(id);
2454
2524
  };
2455
2525
  }, [pos]);
2456
- const clamp2 = React12.useCallback(
2526
+ const clamp2 = React13.useCallback(
2457
2527
  (x, y) => {
2458
2528
  const minX = 10;
2459
2529
  const maxX = Math.max(10, screenWidth - 230);
@@ -2463,8 +2533,8 @@ function DrawToolbar({
2463
2533
  },
2464
2534
  [insets.top, screenHeight, screenWidth]
2465
2535
  );
2466
- const panResponder = React12.useMemo(
2467
- () => import_react_native12.PanResponder.create({
2536
+ const panResponder = React13.useMemo(
2537
+ () => import_react_native13.PanResponder.create({
2468
2538
  onStartShouldSetPanResponder: () => false,
2469
2539
  onMoveShouldSetPanResponder: (_e, g) => Math.abs(g.dx) > 5 || Math.abs(g.dy) > 5,
2470
2540
  onPanResponderGrant: () => {
@@ -2476,7 +2546,7 @@ function DrawToolbar({
2476
2546
  },
2477
2547
  onPanResponderRelease: () => {
2478
2548
  const next = clamp2(currentPos.current.x, currentPos.current.y);
2479
- import_react_native12.Animated.spring(pos, { toValue: next, useNativeDriver: true }).start();
2549
+ import_react_native13.Animated.spring(pos, { toValue: next, useNativeDriver: true }).start();
2480
2550
  }
2481
2551
  }),
2482
2552
  [clamp2, pos]
@@ -2491,9 +2561,9 @@ function DrawToolbar({
2491
2561
  children
2492
2562
  }) {
2493
2563
  const isDisabled = Boolean(disabled) || Boolean(capturingDisabled);
2494
- const [pressed, setPressed] = React12.useState(false);
2564
+ const [pressed, setPressed] = React13.useState(false);
2495
2565
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2496
- import_react_native12.View,
2566
+ import_react_native13.View,
2497
2567
  {
2498
2568
  style: {
2499
2569
  width: 28,
@@ -2505,7 +2575,7 @@ function DrawToolbar({
2505
2575
  opacity: isDisabled ? 0.5 : pressed ? 0.85 : 1
2506
2576
  },
2507
2577
  children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2508
- import_react_native12.Pressable,
2578
+ import_react_native13.Pressable,
2509
2579
  {
2510
2580
  accessibilityRole: "button",
2511
2581
  accessibilityLabel,
@@ -2522,7 +2592,7 @@ function DrawToolbar({
2522
2592
  );
2523
2593
  }
2524
2594
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2525
- import_react_native12.Animated.View,
2595
+ import_react_native13.Animated.View,
2526
2596
  {
2527
2597
  style: [
2528
2598
  {
@@ -2539,7 +2609,7 @@ function DrawToolbar({
2539
2609
  ],
2540
2610
  ...panResponder.panHandlers,
2541
2611
  children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2542
- import_react_native12.View,
2612
+ import_react_native13.View,
2543
2613
  {
2544
2614
  style: {
2545
2615
  backgroundColor: "#F43F5E",
@@ -2547,7 +2617,7 @@ function DrawToolbar({
2547
2617
  padding: 12,
2548
2618
  minWidth: 220
2549
2619
  },
2550
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native12.View, { style: { flexDirection: "row", alignItems: "center", gap: 8 }, children: [
2620
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native13.View, { style: { flexDirection: "row", alignItems: "center", gap: 8 }, children: [
2551
2621
  renderDragHandle ? renderDragHandle() : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react_native.GripVertical, { size: 20, color: "rgba(255, 255, 255, 0.6)" }),
2552
2622
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2553
2623
  DrawColorPicker,
@@ -2565,7 +2635,7 @@ function DrawToolbar({
2565
2635
  }
2566
2636
  }
2567
2637
  ),
2568
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native12.View, { style: { width: 1, height: 20, backgroundColor: "rgba(255, 255, 255, 0.3)", marginHorizontal: 4 } }),
2638
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native13.View, { style: { width: 1, height: 20, backgroundColor: "rgba(255, 255, 255, 0.3)", marginHorizontal: 4 } }),
2569
2639
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2570
2640
  CircleActionButton,
2571
2641
  {
@@ -2603,7 +2673,7 @@ function DrawToolbar({
2603
2673
  void impact("medium");
2604
2674
  onDone();
2605
2675
  },
2606
- children: capturing ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native12.ActivityIndicator, { color: "#FFFFFF", size: "small" }) : renderDoneIcon ? renderDoneIcon() : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react_native.Check, { size: 16, color: "#FFFFFF" })
2676
+ children: capturing ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native13.ActivityIndicator, { color: "#FFFFFF", size: "small" }) : renderDoneIcon ? renderDoneIcon() : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react_native.Check, { size: 16, color: "#FFFFFF" })
2607
2677
  }
2608
2678
  )
2609
2679
  ] })
@@ -2629,7 +2699,7 @@ function DrawModeOverlay({
2629
2699
  renderDragHandle
2630
2700
  }) {
2631
2701
  const theme = useTheme();
2632
- const defaultPalette = React13.useMemo(
2702
+ const defaultPalette = React14.useMemo(
2633
2703
  () => [
2634
2704
  "#EF4444",
2635
2705
  // Red
@@ -2647,11 +2717,11 @@ function DrawModeOverlay({
2647
2717
  []
2648
2718
  );
2649
2719
  const colors = palette && palette.length > 0 ? palette : defaultPalette;
2650
- const [selectedColor, setSelectedColor] = React13.useState(colors[0] ?? "#EF4444");
2651
- const [strokes, setStrokes] = React13.useState([]);
2652
- const [capturing, setCapturing] = React13.useState(false);
2653
- const [hideUi, setHideUi] = React13.useState(false);
2654
- React13.useEffect(() => {
2720
+ const [selectedColor, setSelectedColor] = React14.useState(colors[0] ?? "#EF4444");
2721
+ const [strokes, setStrokes] = React14.useState([]);
2722
+ const [capturing, setCapturing] = React14.useState(false);
2723
+ const [hideUi, setHideUi] = React14.useState(false);
2724
+ React14.useEffect(() => {
2655
2725
  if (!visible) return;
2656
2726
  setStrokes([]);
2657
2727
  setSelectedColor(colors[0] ?? "#EF4444");
@@ -2659,14 +2729,14 @@ function DrawModeOverlay({
2659
2729
  setHideUi(false);
2660
2730
  }, [colors, visible]);
2661
2731
  const canUndo = strokes.length > 0;
2662
- const handleUndo = React13.useCallback(() => {
2732
+ const handleUndo = React14.useCallback(() => {
2663
2733
  setStrokes((prev) => prev.slice(0, -1));
2664
2734
  }, []);
2665
- const handleCancel = React13.useCallback(() => {
2735
+ const handleCancel = React14.useCallback(() => {
2666
2736
  setStrokes([]);
2667
2737
  onCancel();
2668
2738
  }, [onCancel]);
2669
- const handleDone = React13.useCallback(async () => {
2739
+ const handleDone = React14.useCallback(async () => {
2670
2740
  if (!captureTargetRef.current || capturing) return;
2671
2741
  try {
2672
2742
  setCapturing(true);
@@ -2688,7 +2758,7 @@ function DrawModeOverlay({
2688
2758
  }
2689
2759
  }, [captureTargetRef, capturing, onCapture]);
2690
2760
  if (!visible) return null;
2691
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native13.View, { style: [import_react_native13.StyleSheet.absoluteFill, styles3.root, style], pointerEvents: "box-none", children: [
2761
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native14.View, { style: [import_react_native14.StyleSheet.absoluteFill, styles3.root, style], pointerEvents: "box-none", children: [
2692
2762
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(EdgeGlowFrame, { visible: !hideUi, role: "danger", thickness: 50, intensity: 1 }),
2693
2763
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2694
2764
  DrawSurface,
@@ -2719,32 +2789,32 @@ function DrawModeOverlay({
2719
2789
  )
2720
2790
  ] });
2721
2791
  }
2722
- var styles3 = import_react_native13.StyleSheet.create({
2792
+ var styles3 = import_react_native14.StyleSheet.create({
2723
2793
  root: {
2724
2794
  zIndex: 9999
2725
2795
  }
2726
2796
  });
2727
2797
 
2728
2798
  // src/components/comments/AppCommentsSheet.tsx
2729
- var React20 = __toESM(require("react"));
2730
- var import_react_native19 = require("react-native");
2799
+ var React21 = __toESM(require("react"));
2800
+ var import_react_native20 = require("react-native");
2731
2801
  var import_bottom_sheet3 = require("@gorhom/bottom-sheet");
2732
2802
  var import_react_native_safe_area_context3 = require("react-native-safe-area-context");
2733
2803
  var import_liquid_glass4 = require("@callstack/liquid-glass");
2734
2804
  var import_lucide_react_native4 = require("lucide-react-native");
2735
2805
 
2736
2806
  // src/components/chat/ChatComposer.tsx
2737
- var React15 = __toESM(require("react"));
2738
- var import_react_native15 = require("react-native");
2807
+ var React16 = __toESM(require("react"));
2808
+ var import_react_native16 = require("react-native");
2739
2809
  var import_liquid_glass3 = require("@callstack/liquid-glass");
2740
2810
  var import_lucide_react_native3 = require("lucide-react-native");
2741
2811
 
2742
2812
  // src/components/chat/MultilineTextInput.tsx
2743
- var React14 = __toESM(require("react"));
2744
- var import_react_native14 = require("react-native");
2813
+ var React15 = __toESM(require("react"));
2814
+ var import_react_native15 = require("react-native");
2745
2815
  var import_bottom_sheet2 = require("@gorhom/bottom-sheet");
2746
2816
  var import_jsx_runtime13 = require("react/jsx-runtime");
2747
- var MultilineTextInput = React14.forwardRef(function MultilineTextInput2({ useBottomSheetTextInput = false, placeholder, placeholderTextColor, style, ...props }, ref) {
2817
+ var MultilineTextInput = React15.forwardRef(function MultilineTextInput2({ useBottomSheetTextInput = false, placeholder, placeholderTextColor, style, ...props }, ref) {
2748
2818
  const theme = useTheme();
2749
2819
  const baseStyle = {
2750
2820
  minHeight: 44,
@@ -2764,7 +2834,7 @@ var MultilineTextInput = React14.forwardRef(function MultilineTextInput2({ useBo
2764
2834
  style: [baseStyle, style],
2765
2835
  textAlignVertical: "top"
2766
2836
  };
2767
- return useBottomSheetTextInput ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_bottom_sheet2.BottomSheetTextInput, { ref, ...commonProps }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native14.TextInput, { ref, ...commonProps });
2837
+ return useBottomSheetTextInput ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_bottom_sheet2.BottomSheetTextInput, { ref, ...commonProps }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native15.TextInput, { ref, ...commonProps });
2768
2838
  });
2769
2839
 
2770
2840
  // src/components/icons/StudioIcons.tsx
@@ -2816,10 +2886,10 @@ function AspectRatioThumbnail({
2816
2886
  onRemove,
2817
2887
  renderRemoveIcon
2818
2888
  }) {
2819
- const [aspectRatio, setAspectRatio] = React15.useState(1);
2820
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react_native15.View, { style: { height: THUMBNAIL_HEIGHT, aspectRatio, position: "relative" }, children: [
2821
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native15.View, { style: { flex: 1, borderRadius: 8, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2822
- import_react_native15.Image,
2889
+ const [aspectRatio, setAspectRatio] = React16.useState(1);
2890
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react_native16.View, { style: { height: THUMBNAIL_HEIGHT, aspectRatio, position: "relative" }, children: [
2891
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native16.View, { style: { flex: 1, borderRadius: 8, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2892
+ import_react_native16.Image,
2823
2893
  {
2824
2894
  source: { uri },
2825
2895
  style: { width: "100%", height: "100%" },
@@ -2832,7 +2902,7 @@ function AspectRatioThumbnail({
2832
2902
  }
2833
2903
  ) }),
2834
2904
  onRemove ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2835
- import_react_native15.Pressable,
2905
+ import_react_native16.Pressable,
2836
2906
  {
2837
2907
  style: {
2838
2908
  position: "absolute",
@@ -2858,6 +2928,7 @@ function ChatComposer({
2858
2928
  onChangeValue,
2859
2929
  placeholder = "Describe the idea you want to build",
2860
2930
  disabled = false,
2931
+ sendDisabled = false,
2861
2932
  sending = false,
2862
2933
  autoFocus = false,
2863
2934
  onSend,
@@ -2872,19 +2943,19 @@ function ChatComposer({
2872
2943
  style
2873
2944
  }) {
2874
2945
  const theme = useTheme();
2875
- const [internal, setInternal] = React15.useState("");
2946
+ const [internal, setInternal] = React16.useState("");
2876
2947
  const text = value ?? internal;
2877
2948
  const setText = onChangeValue ?? setInternal;
2878
2949
  const hasAttachments = attachments.length > 0;
2879
2950
  const hasText = text.trim().length > 0;
2880
2951
  const composerMinHeight = hasAttachments ? THUMBNAIL_HEIGHT + 44 + 24 : 44;
2881
- const isButtonDisabled = sending || disabled;
2882
- const maxInputHeight = React15.useMemo(() => import_react_native15.Dimensions.get("window").height * 0.5, []);
2883
- const shakeAnim = React15.useRef(new import_react_native15.Animated.Value(0)).current;
2884
- const [sendPressed, setSendPressed] = React15.useState(false);
2885
- const inputRef = React15.useRef(null);
2886
- const prevAutoFocusRef = React15.useRef(false);
2887
- React15.useEffect(() => {
2952
+ const isButtonDisabled = sending || disabled || sendDisabled;
2953
+ const maxInputHeight = React16.useMemo(() => import_react_native16.Dimensions.get("window").height * 0.5, []);
2954
+ const shakeAnim = React16.useRef(new import_react_native16.Animated.Value(0)).current;
2955
+ const [sendPressed, setSendPressed] = React16.useState(false);
2956
+ const inputRef = React16.useRef(null);
2957
+ const prevAutoFocusRef = React16.useRef(false);
2958
+ React16.useEffect(() => {
2888
2959
  const shouldFocus = autoFocus && !prevAutoFocusRef.current && !disabled && !sending;
2889
2960
  prevAutoFocusRef.current = autoFocus;
2890
2961
  if (!shouldFocus) return;
@@ -2894,17 +2965,17 @@ function ChatComposer({
2894
2965
  }, 75);
2895
2966
  return () => clearTimeout(t);
2896
2967
  }, [autoFocus, disabled, sending]);
2897
- const triggerShake = React15.useCallback(() => {
2968
+ const triggerShake = React16.useCallback(() => {
2898
2969
  shakeAnim.setValue(0);
2899
- import_react_native15.Animated.sequence([
2900
- import_react_native15.Animated.timing(shakeAnim, { toValue: 10, duration: 50, useNativeDriver: true }),
2901
- import_react_native15.Animated.timing(shakeAnim, { toValue: -10, duration: 50, useNativeDriver: true }),
2902
- import_react_native15.Animated.timing(shakeAnim, { toValue: 10, duration: 50, useNativeDriver: true }),
2903
- import_react_native15.Animated.timing(shakeAnim, { toValue: -10, duration: 50, useNativeDriver: true }),
2904
- import_react_native15.Animated.timing(shakeAnim, { toValue: 0, duration: 50, useNativeDriver: true })
2970
+ import_react_native16.Animated.sequence([
2971
+ import_react_native16.Animated.timing(shakeAnim, { toValue: 10, duration: 50, useNativeDriver: true }),
2972
+ import_react_native16.Animated.timing(shakeAnim, { toValue: -10, duration: 50, useNativeDriver: true }),
2973
+ import_react_native16.Animated.timing(shakeAnim, { toValue: 10, duration: 50, useNativeDriver: true }),
2974
+ import_react_native16.Animated.timing(shakeAnim, { toValue: -10, duration: 50, useNativeDriver: true }),
2975
+ import_react_native16.Animated.timing(shakeAnim, { toValue: 0, duration: 50, useNativeDriver: true })
2905
2976
  ]).start();
2906
2977
  }, [shakeAnim]);
2907
- const handleSend = React15.useCallback(async () => {
2978
+ const handleSend = React16.useCallback(async () => {
2908
2979
  if (isButtonDisabled) return;
2909
2980
  if (!hasText) {
2910
2981
  triggerShake();
@@ -2917,12 +2988,12 @@ function ChatComposer({
2917
2988
  const textareaBgColor = theme.scheme === "dark" ? "#18181B" : "#F6F6F6";
2918
2989
  const placeholderTextColor = theme.scheme === "dark" ? "#A1A1AA" : "#71717A";
2919
2990
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2920
- import_react_native15.View,
2991
+ import_react_native16.View,
2921
2992
  {
2922
2993
  style: [{ paddingHorizontal: 16, paddingBottom: 12, paddingTop: 8 }, style],
2923
2994
  onLayout: (e) => onLayout == null ? void 0 : onLayout({ height: e.nativeEvent.layout.height }),
2924
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react_native15.View, { style: { flexDirection: "row", alignItems: "flex-end", gap: 8 }, children: [
2925
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native15.Animated.View, { style: { flex: 1, transform: [{ translateX: shakeAnim }] }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2995
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react_native16.View, { style: { flexDirection: "row", alignItems: "flex-end", gap: 8 }, children: [
2996
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native16.Animated.View, { style: { flex: 1, transform: [{ translateX: shakeAnim }] }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2926
2997
  import_liquid_glass3.LiquidGlassView,
2927
2998
  {
2928
2999
  style: [
@@ -2935,7 +3006,7 @@ function ChatComposer({
2935
3006
  effect: "clear",
2936
3007
  children: [
2937
3008
  hasAttachments ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2938
- import_react_native15.ScrollView,
3009
+ import_react_native16.ScrollView,
2939
3010
  {
2940
3011
  horizontal: true,
2941
3012
  showsHorizontalScrollIndicator: false,
@@ -2952,7 +3023,7 @@ function ChatComposer({
2952
3023
  `attachment-${index}`
2953
3024
  )),
2954
3025
  onAddAttachment ? renderAddAttachment ? renderAddAttachment() : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2955
- import_react_native15.Pressable,
3026
+ import_react_native16.Pressable,
2956
3027
  {
2957
3028
  style: {
2958
3029
  height: THUMBNAIL_HEIGHT,
@@ -3004,7 +3075,7 @@ function ChatComposer({
3004
3075
  interactive: true,
3005
3076
  effect: "clear",
3006
3077
  children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3007
- import_react_native15.View,
3078
+ import_react_native16.View,
3008
3079
  {
3009
3080
  style: {
3010
3081
  width: 44,
@@ -3015,7 +3086,7 @@ function ChatComposer({
3015
3086
  opacity: isButtonDisabled ? 0.6 : sendPressed ? 0.9 : 1
3016
3087
  },
3017
3088
  children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3018
- import_react_native15.Pressable,
3089
+ import_react_native16.Pressable,
3019
3090
  {
3020
3091
  accessibilityRole: "button",
3021
3092
  accessibilityLabel: "Send",
@@ -3024,7 +3095,7 @@ function ChatComposer({
3024
3095
  onPressIn: () => setSendPressed(true),
3025
3096
  onPressOut: () => setSendPressed(false),
3026
3097
  style: { flex: 1, alignItems: "center", justifyContent: "center" },
3027
- children: sending ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native15.ActivityIndicator, {}) : renderSendIcon ? renderSendIcon() : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(IconChevronRight, { size: 20, colorToken: "onPrimary" })
3098
+ children: sending ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native16.ActivityIndicator, {}) : renderSendIcon ? renderSendIcon() : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(IconChevronRight, { size: 20, colorToken: "onPrimary" })
3028
3099
  }
3029
3100
  )
3030
3101
  }
@@ -3037,11 +3108,11 @@ function ChatComposer({
3037
3108
  }
3038
3109
 
3039
3110
  // src/components/comments/CommentRow.tsx
3040
- var React16 = __toESM(require("react"));
3041
- var import_react_native17 = require("react-native");
3111
+ var React17 = __toESM(require("react"));
3112
+ var import_react_native18 = require("react-native");
3042
3113
 
3043
3114
  // src/components/primitives/Avatar.tsx
3044
- var import_react_native16 = require("react-native");
3115
+ var import_react_native17 = require("react-native");
3045
3116
  var import_jsx_runtime16 = require("react/jsx-runtime");
3046
3117
  function initialsFrom(name) {
3047
3118
  var _a, _b;
@@ -3061,7 +3132,7 @@ function Avatar({
3061
3132
  const radius = size / 2;
3062
3133
  const fallbackBg = fallbackBackgroundColor ?? theme.colors.neutral;
3063
3134
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3064
- import_react_native16.View,
3135
+ import_react_native17.View,
3065
3136
  {
3066
3137
  style: [
3067
3138
  {
@@ -3076,7 +3147,7 @@ function Avatar({
3076
3147
  style
3077
3148
  ],
3078
3149
  children: uri ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3079
- import_react_native16.Image,
3150
+ import_react_native17.Image,
3080
3151
  {
3081
3152
  source: { uri },
3082
3153
  style: [{ width: size, height: size }, imageStyle],
@@ -3109,9 +3180,9 @@ function formatTimeAgo(iso) {
3109
3180
  var import_jsx_runtime17 = require("react/jsx-runtime");
3110
3181
  function CommentRow({ comment, showDivider }) {
3111
3182
  const theme = useTheme();
3112
- const [authorName, setAuthorName] = React16.useState(null);
3113
- const [authorAvatar, setAuthorAvatar] = React16.useState(null);
3114
- React16.useEffect(() => {
3183
+ const [authorName, setAuthorName] = React17.useState(null);
3184
+ const [authorAvatar, setAuthorAvatar] = React17.useState(null);
3185
+ React17.useEffect(() => {
3115
3186
  let cancelled = false;
3116
3187
  (async () => {
3117
3188
  try {
@@ -3127,7 +3198,7 @@ function CommentRow({ comment, showDivider }) {
3127
3198
  };
3128
3199
  }, [comment.authorId]);
3129
3200
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
3130
- import_react_native17.View,
3201
+ import_react_native18.View,
3131
3202
  {
3132
3203
  style: {
3133
3204
  flexDirection: "row",
@@ -3138,8 +3209,8 @@ function CommentRow({ comment, showDivider }) {
3138
3209
  },
3139
3210
  children: [
3140
3211
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Avatar, { size: 32, uri: authorAvatar, name: authorName ?? comment.authorId, style: { marginTop: 6 } }),
3141
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_react_native17.View, { style: { flex: 1, minWidth: 0, gap: 4 }, children: [
3142
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_react_native17.View, { style: { flexDirection: "row", alignItems: "center", gap: theme.spacing.sm }, children: [
3212
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_react_native18.View, { style: { flex: 1, minWidth: 0, gap: 4 }, children: [
3213
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_react_native18.View, { style: { flexDirection: "row", alignItems: "center", gap: theme.spacing.sm }, children: [
3143
3214
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { style: { fontSize: 14, lineHeight: 18, fontWeight: theme.typography.fontWeight.bold, color: theme.colors.text }, children: authorName ?? "Unknown User" }),
3144
3215
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { style: { fontSize: 12, lineHeight: 16, color: theme.colors.textMuted }, children: formatTimeAgo(comment.createdAt) })
3145
3216
  ] }),
@@ -3151,7 +3222,7 @@ function CommentRow({ comment, showDivider }) {
3151
3222
  }
3152
3223
 
3153
3224
  // src/components/comments/useAppComments.ts
3154
- var React17 = __toESM(require("react"));
3225
+ var React18 = __toESM(require("react"));
3155
3226
 
3156
3227
  // src/data/comments/remote.ts
3157
3228
  var AppCommentsRemoteDataSourceImpl = class extends BaseRemote {
@@ -3223,18 +3294,18 @@ var appCommentsRepository = new AppCommentsRepositoryImpl(appCommentsRemoteDataS
3223
3294
 
3224
3295
  // src/components/comments/useAppComments.ts
3225
3296
  function useAppComments(appId) {
3226
- const [comments, setComments] = React17.useState([]);
3227
- const [loading, setLoading] = React17.useState(false);
3228
- const [sending, setSending] = React17.useState(false);
3229
- const [error, setError] = React17.useState(null);
3230
- const sortByCreatedAtAsc = React17.useCallback((items) => {
3297
+ const [comments, setComments] = React18.useState([]);
3298
+ const [loading, setLoading] = React18.useState(false);
3299
+ const [sending, setSending] = React18.useState(false);
3300
+ const [error, setError] = React18.useState(null);
3301
+ const sortByCreatedAtAsc = React18.useCallback((items) => {
3231
3302
  return [...items].sort((a, b) => {
3232
3303
  const at = a.createdAt ? new Date(a.createdAt).getTime() : 0;
3233
3304
  const bt = b.createdAt ? new Date(b.createdAt).getTime() : 0;
3234
3305
  return at - bt;
3235
3306
  });
3236
3307
  }, []);
3237
- const refresh = React17.useCallback(async () => {
3308
+ const refresh = React18.useCallback(async () => {
3238
3309
  if (!appId) {
3239
3310
  setComments([]);
3240
3311
  return;
@@ -3251,10 +3322,10 @@ function useAppComments(appId) {
3251
3322
  setLoading(false);
3252
3323
  }
3253
3324
  }, [appId, sortByCreatedAtAsc]);
3254
- React17.useEffect(() => {
3325
+ React18.useEffect(() => {
3255
3326
  void refresh();
3256
3327
  }, [refresh]);
3257
- const create = React17.useCallback(
3328
+ const create = React18.useCallback(
3258
3329
  async (text) => {
3259
3330
  if (!appId) return;
3260
3331
  const trimmed = text.trim();
@@ -3277,11 +3348,11 @@ function useAppComments(appId) {
3277
3348
  }
3278
3349
 
3279
3350
  // src/components/comments/useAppDetails.ts
3280
- var React18 = __toESM(require("react"));
3351
+ var React19 = __toESM(require("react"));
3281
3352
  function useAppDetails(appId) {
3282
- const [app, setApp] = React18.useState(null);
3283
- const [loading, setLoading] = React18.useState(false);
3284
- React18.useEffect(() => {
3353
+ const [app, setApp] = React19.useState(null);
3354
+ const [loading, setLoading] = React19.useState(false);
3355
+ React19.useEffect(() => {
3285
3356
  if (!appId) {
3286
3357
  setApp(null);
3287
3358
  return;
@@ -3306,25 +3377,30 @@ function useAppDetails(appId) {
3306
3377
  }
3307
3378
 
3308
3379
  // src/components/comments/useIosKeyboardSnapFix.ts
3309
- var React19 = __toESM(require("react"));
3310
- var import_react_native18 = require("react-native");
3311
- function useIosKeyboardSnapFix(sheetRef) {
3312
- const [keyboardVisible, setKeyboardVisible] = React19.useState(false);
3313
- React19.useEffect(() => {
3314
- if (import_react_native18.Platform.OS !== "ios") return;
3315
- const show = import_react_native18.Keyboard.addListener("keyboardWillShow", () => setKeyboardVisible(true));
3316
- const hide = import_react_native18.Keyboard.addListener("keyboardWillHide", () => {
3380
+ var React20 = __toESM(require("react"));
3381
+ var import_react_native19 = require("react-native");
3382
+ function useIosKeyboardSnapFix(sheetRef, options) {
3383
+ const [keyboardVisible, setKeyboardVisible] = React20.useState(false);
3384
+ React20.useEffect(() => {
3385
+ if (import_react_native19.Platform.OS !== "ios") return;
3386
+ const show = import_react_native19.Keyboard.addListener("keyboardWillShow", () => setKeyboardVisible(true));
3387
+ const hide = import_react_native19.Keyboard.addListener("keyboardWillHide", () => {
3388
+ var _a;
3317
3389
  setKeyboardVisible(false);
3318
- setTimeout(() => {
3319
- var _a, _b;
3320
- return (_b = (_a = sheetRef.current) == null ? void 0 : _a.snapToIndex) == null ? void 0 : _b.call(_a, 1);
3321
- }, 10);
3390
+ const target = (options == null ? void 0 : options.targetIndex) ?? 1;
3391
+ const current = ((_a = options == null ? void 0 : options.getCurrentIndex) == null ? void 0 : _a.call(options)) ?? null;
3392
+ if (current === target) {
3393
+ setTimeout(() => {
3394
+ var _a2, _b;
3395
+ return (_b = (_a2 = sheetRef.current) == null ? void 0 : _a2.snapToIndex) == null ? void 0 : _b.call(_a2, target);
3396
+ }, 10);
3397
+ }
3322
3398
  });
3323
3399
  return () => {
3324
3400
  show.remove();
3325
3401
  hide.remove();
3326
3402
  };
3327
- }, [sheetRef]);
3403
+ }, [options == null ? void 0 : options.getCurrentIndex, options == null ? void 0 : options.targetIndex, sheetRef]);
3328
3404
  return { keyboardVisible };
3329
3405
  }
3330
3406
 
@@ -3333,12 +3409,16 @@ var import_jsx_runtime18 = require("react/jsx-runtime");
3333
3409
  function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
3334
3410
  const theme = useTheme();
3335
3411
  const insets = (0, import_react_native_safe_area_context3.useSafeAreaInsets)();
3336
- const sheetRef = React20.useRef(null);
3337
- const snapPoints = React20.useMemo(() => ["50%", "90%"], []);
3412
+ const sheetRef = React21.useRef(null);
3413
+ const snapPoints = React21.useMemo(() => ["50%", "90%"], []);
3414
+ const currentIndexRef = React21.useRef(1);
3338
3415
  const { comments, loading, sending, error, create, refresh } = useAppComments(appId);
3339
3416
  const { app, loading: loadingApp } = useAppDetails(appId);
3340
- const { keyboardVisible } = useIosKeyboardSnapFix(sheetRef);
3341
- React20.useEffect(() => {
3417
+ const { keyboardVisible } = useIosKeyboardSnapFix(sheetRef, {
3418
+ getCurrentIndex: () => currentIndexRef.current,
3419
+ targetIndex: 1
3420
+ });
3421
+ React21.useEffect(() => {
3342
3422
  var _a, _b;
3343
3423
  if (appId) {
3344
3424
  (_a = sheetRef.current) == null ? void 0 : _a.present();
@@ -3347,21 +3427,22 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
3347
3427
  (_b = sheetRef.current) == null ? void 0 : _b.dismiss();
3348
3428
  }
3349
3429
  }, [appId, refresh]);
3350
- React20.useEffect(() => {
3430
+ React21.useEffect(() => {
3351
3431
  if (!appId) return;
3352
3432
  onCountChange == null ? void 0 : onCountChange(comments.length);
3353
3433
  }, [appId, comments.length, onCountChange]);
3354
- const renderBackdrop = React20.useCallback(
3434
+ const renderBackdrop = React21.useCallback(
3355
3435
  (props) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_bottom_sheet3.BottomSheetBackdrop, { ...props, disappearsOnIndex: -1, appearsOnIndex: 0, opacity: 0.5 }),
3356
3436
  []
3357
3437
  );
3358
- const handleChange = React20.useCallback(
3438
+ const handleChange = React21.useCallback(
3359
3439
  (index) => {
3440
+ currentIndexRef.current = index;
3360
3441
  if (index === -1) onClose();
3361
3442
  },
3362
3443
  [onClose]
3363
3444
  );
3364
- const handlePlay = React20.useCallback(async () => {
3445
+ const handlePlay = React21.useCallback(async () => {
3365
3446
  var _a;
3366
3447
  if (!appId) return;
3367
3448
  (_a = sheetRef.current) == null ? void 0 : _a.dismiss();
@@ -3379,17 +3460,17 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
3379
3460
  onChange: handleChange,
3380
3461
  backgroundStyle: {
3381
3462
  backgroundColor: theme.scheme === "dark" ? "#0B080F" : "#FFFFFF",
3382
- borderTopLeftRadius: import_react_native19.Platform.OS === "ios" ? 39 : 16,
3383
- borderTopRightRadius: import_react_native19.Platform.OS === "ios" ? 39 : 16
3463
+ borderTopLeftRadius: import_react_native20.Platform.OS === "ios" ? 39 : 16,
3464
+ borderTopRightRadius: import_react_native20.Platform.OS === "ios" ? 39 : 16
3384
3465
  },
3385
3466
  handleIndicatorStyle: { backgroundColor: theme.colors.handleIndicator },
3386
3467
  keyboardBehavior: "interactive",
3387
3468
  keyboardBlurBehavior: "restore",
3388
3469
  android_keyboardInputMode: "adjustResize",
3389
3470
  topInset: insets.top,
3390
- children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native19.View, { style: { flex: 1 }, children: [
3471
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native20.View, { style: { flex: 1 }, children: [
3391
3472
  /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
3392
- import_react_native19.View,
3473
+ import_react_native20.View,
3393
3474
  {
3394
3475
  style: {
3395
3476
  flexDirection: "row",
@@ -3425,7 +3506,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
3425
3506
  interactive: true,
3426
3507
  effect: "clear",
3427
3508
  children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3428
- import_react_native19.View,
3509
+ import_react_native20.View,
3429
3510
  {
3430
3511
  style: {
3431
3512
  width: 32,
@@ -3437,7 +3518,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
3437
3518
  opacity: appId ? 1 : 0.5
3438
3519
  },
3439
3520
  children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3440
- import_react_native19.Pressable,
3521
+ import_react_native20.Pressable,
3441
3522
  {
3442
3523
  disabled: !appId,
3443
3524
  onPress: () => void handlePlay(),
@@ -3472,13 +3553,13 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
3472
3553
  },
3473
3554
  keyboardShouldPersistTaps: "handled",
3474
3555
  children: [
3475
- loading && comments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native19.View, { style: { flex: 1, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native19.ActivityIndicator, {}) }) : comments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native19.View, { style: { flex: 1, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Text, { variant: "bodyMuted", style: { textAlign: "center" }, children: "No comments yet" }) }) : comments.map((c, idx) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(CommentRow, { comment: c, showDivider: idx < comments.length - 1 }, c.id)),
3556
+ loading && comments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native20.View, { style: { flex: 1, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native20.ActivityIndicator, {}) }) : comments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native20.View, { style: { flex: 1, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Text, { variant: "bodyMuted", style: { textAlign: "center" }, children: "No comments yet" }) }) : comments.map((c, idx) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(CommentRow, { comment: c, showDivider: idx < comments.length - 1 }, c.id)),
3476
3557
  error ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Text, { variant: "captionMuted", style: { marginTop: theme.spacing.lg }, children: "Failed to load comments." }) : null
3477
3558
  ]
3478
3559
  }
3479
3560
  ),
3480
3561
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3481
- import_react_native19.View,
3562
+ import_react_native20.View,
3482
3563
  {
3483
3564
  style: {
3484
3565
  position: "absolute",
@@ -3487,7 +3568,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
3487
3568
  bottom: 0,
3488
3569
  paddingHorizontal: theme.spacing.lg,
3489
3570
  paddingTop: theme.spacing.sm,
3490
- paddingBottom: import_react_native19.Platform.OS === "ios" ? keyboardVisible ? theme.spacing.lg : insets.bottom : insets.bottom + 10,
3571
+ paddingBottom: import_react_native20.Platform.OS === "ios" ? keyboardVisible ? theme.spacing.lg : insets.bottom : insets.bottom + 10,
3491
3572
  borderTopWidth: 1,
3492
3573
  borderTopColor: withAlpha(theme.colors.border, 0.1),
3493
3574
  backgroundColor: withAlpha(theme.colors.background, 0.8)
@@ -3501,7 +3582,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
3501
3582
  useBottomSheetTextInput: true,
3502
3583
  onSend: async (text) => {
3503
3584
  await create(text);
3504
- import_react_native19.Keyboard.dismiss();
3585
+ import_react_native20.Keyboard.dismiss();
3505
3586
  }
3506
3587
  }
3507
3588
  )
@@ -3513,16 +3594,16 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
3513
3594
  }
3514
3595
 
3515
3596
  // src/studio/ui/PreviewPanel.tsx
3516
- var import_react_native40 = require("react-native");
3597
+ var import_react_native41 = require("react-native");
3517
3598
 
3518
3599
  // src/components/preview/PreviewPage.tsx
3519
- var import_react_native20 = require("react-native");
3600
+ var import_react_native21 = require("react-native");
3520
3601
  var import_bottom_sheet4 = require("@gorhom/bottom-sheet");
3521
3602
  var import_jsx_runtime19 = require("react/jsx-runtime");
3522
3603
  function PreviewPage({ header, children, contentStyle }) {
3523
3604
  const theme = useTheme();
3524
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_react_native20.View, { style: { flex: 1 }, children: [
3525
- header ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native20.View, { children: header }) : null,
3605
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_react_native21.View, { style: { flex: 1 }, children: [
3606
+ header ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native21.View, { children: header }) : null,
3526
3607
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3527
3608
  import_bottom_sheet4.BottomSheetScrollView,
3528
3609
  {
@@ -3542,15 +3623,15 @@ function PreviewPage({ header, children, contentStyle }) {
3542
3623
  }
3543
3624
 
3544
3625
  // src/studio/ui/preview-panel/PreviewPanelHeader.tsx
3545
- var import_react_native23 = require("react-native");
3626
+ var import_react_native24 = require("react-native");
3546
3627
 
3547
3628
  // src/components/studio-sheet/StudioSheetHeader.tsx
3548
- var import_react_native21 = require("react-native");
3629
+ var import_react_native22 = require("react-native");
3549
3630
  var import_jsx_runtime20 = require("react/jsx-runtime");
3550
3631
  function StudioSheetHeader({ left, center, right, style }) {
3551
3632
  const theme = useTheme();
3552
3633
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
3553
- import_react_native21.View,
3634
+ import_react_native22.View,
3554
3635
  {
3555
3636
  style: [
3556
3637
  {
@@ -3563,17 +3644,17 @@ function StudioSheetHeader({ left, center, right, style }) {
3563
3644
  style
3564
3645
  ],
3565
3646
  children: [
3566
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native21.View, { style: { flexDirection: "row", alignItems: "center" }, children: left }),
3567
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native21.View, { style: { flex: 1, alignItems: "center" }, children: center }),
3568
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native21.View, { style: { flexDirection: "row", alignItems: "center" }, children: right })
3647
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native22.View, { style: { flexDirection: "row", alignItems: "center" }, children: left }),
3648
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native22.View, { style: { flex: 1, alignItems: "center" }, children: center }),
3649
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native22.View, { style: { flexDirection: "row", alignItems: "center" }, children: right })
3569
3650
  ]
3570
3651
  }
3571
3652
  );
3572
3653
  }
3573
3654
 
3574
3655
  // src/components/studio-sheet/StudioSheetHeaderIconButton.tsx
3575
- var React21 = __toESM(require("react"));
3576
- var import_react_native22 = require("react-native");
3656
+ var React22 = __toESM(require("react"));
3657
+ var import_react_native23 = require("react-native");
3577
3658
  var import_liquid_glass5 = require("@callstack/liquid-glass");
3578
3659
  var import_jsx_runtime21 = require("react/jsx-runtime");
3579
3660
  function StudioSheetHeaderIconButton({
@@ -3587,19 +3668,19 @@ function StudioSheetHeaderIconButton({
3587
3668
  }) {
3588
3669
  const theme = useTheme();
3589
3670
  const size = 44;
3590
- const [pressed, setPressed] = React21.useState(false);
3671
+ const [pressed, setPressed] = React22.useState(false);
3591
3672
  const solidBg = intent === "danger" ? theme.colors.danger : intent === "primary" ? theme.colors.primary : theme.colors.neutral;
3592
3673
  const glassFallbackBg = theme.scheme === "dark" ? "#18181B" : "#F6F6F6";
3593
3674
  const glassInnerBg = intent === "danger" ? theme.colors.danger : theme.colors.primary;
3594
3675
  const resolvedOpacity = disabled ? 0.6 : pressed ? 0.9 : 1;
3595
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native22.View, { style, children: appearance === "glass" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3676
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native23.View, { style, children: appearance === "glass" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3596
3677
  import_liquid_glass5.LiquidGlassView,
3597
3678
  {
3598
3679
  style: [{ borderRadius: 100 }, !import_liquid_glass5.isLiquidGlassSupported && { backgroundColor: glassFallbackBg }],
3599
3680
  interactive: true,
3600
3681
  effect: "clear",
3601
3682
  children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3602
- import_react_native22.View,
3683
+ import_react_native23.View,
3603
3684
  {
3604
3685
  style: {
3605
3686
  width: size,
@@ -3611,7 +3692,7 @@ function StudioSheetHeaderIconButton({
3611
3692
  opacity: resolvedOpacity
3612
3693
  },
3613
3694
  children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3614
- import_react_native22.Pressable,
3695
+ import_react_native23.Pressable,
3615
3696
  {
3616
3697
  accessibilityRole: "button",
3617
3698
  accessibilityLabel,
@@ -3630,7 +3711,7 @@ function StudioSheetHeaderIconButton({
3630
3711
  )
3631
3712
  }
3632
3713
  ) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3633
- import_react_native22.View,
3714
+ import_react_native23.View,
3634
3715
  {
3635
3716
  style: {
3636
3717
  width: size,
@@ -3642,7 +3723,7 @@ function StudioSheetHeaderIconButton({
3642
3723
  opacity: resolvedOpacity
3643
3724
  },
3644
3725
  children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3645
- import_react_native22.Pressable,
3726
+ import_react_native23.Pressable,
3646
3727
  {
3647
3728
  accessibilityRole: "button",
3648
3729
  accessibilityLabel,
@@ -3669,7 +3750,7 @@ function PreviewPanelHeader({ isOwner, onClose, onNavigateHome, onGoToChat }) {
3669
3750
  {
3670
3751
  left: onNavigateHome ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StudioSheetHeaderIconButton, { onPress: onNavigateHome, accessibilityLabel: "Home", appearance: "glass", intent: "primary", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(IconHome, { size: 20, colorToken: "onPrimary" }) }) : null,
3671
3752
  center: null,
3672
- right: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native23.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
3753
+ right: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native24.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
3673
3754
  isOwner ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3674
3755
  StudioSheetHeaderIconButton,
3675
3756
  {
@@ -3688,10 +3769,10 @@ function PreviewPanelHeader({ isOwner, onClose, onNavigateHome, onGoToChat }) {
3688
3769
  }
3689
3770
 
3690
3771
  // src/components/preview/PreviewHeroCard.tsx
3691
- var import_react_native25 = require("react-native");
3772
+ var import_react_native26 = require("react-native");
3692
3773
 
3693
3774
  // src/components/primitives/Surface.tsx
3694
- var import_react_native24 = require("react-native");
3775
+ var import_react_native25 = require("react-native");
3695
3776
  var import_jsx_runtime23 = require("react/jsx-runtime");
3696
3777
  function backgroundFor(variant, theme) {
3697
3778
  const { colors } = theme;
@@ -3710,7 +3791,7 @@ function backgroundFor(variant, theme) {
3710
3791
  function Surface({ variant = "surface", border = false, style, ...props }) {
3711
3792
  const theme = useTheme();
3712
3793
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3713
- import_react_native24.View,
3794
+ import_react_native25.View,
3714
3795
  {
3715
3796
  ...props,
3716
3797
  style: [
@@ -3766,32 +3847,32 @@ function PreviewHeroCard({
3766
3847
  },
3767
3848
  style
3768
3849
  ],
3769
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native25.View, { style: { flex: 1 }, children: [
3770
- background ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native25.View, { style: { position: "absolute", inset: 0 }, children: background }) : null,
3771
- image ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native25.View, { style: { position: "absolute", inset: 0 }, children: image }) : null,
3772
- overlayTopLeft ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native25.View, { style: { position: "absolute", top: theme.spacing.sm, left: theme.spacing.sm, zIndex: 2 }, children: overlayTopLeft }) : null,
3773
- overlayBottom ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native25.View, { style: { flex: 1, justifyContent: "flex-end" }, children: overlayBottom }) : null
3850
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native26.View, { style: { flex: 1 }, children: [
3851
+ background ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native26.View, { style: { position: "absolute", inset: 0 }, children: background }) : null,
3852
+ image ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native26.View, { style: { position: "absolute", inset: 0 }, children: image }) : null,
3853
+ overlayTopLeft ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native26.View, { style: { position: "absolute", top: theme.spacing.sm, left: theme.spacing.sm, zIndex: 2 }, children: overlayTopLeft }) : null,
3854
+ overlayBottom ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native26.View, { style: { flex: 1, justifyContent: "flex-end" }, children: overlayBottom }) : null
3774
3855
  ] })
3775
3856
  }
3776
3857
  );
3777
3858
  }
3778
3859
 
3779
3860
  // src/components/preview/PreviewPlaceholder.tsx
3780
- var React22 = __toESM(require("react"));
3781
- var import_react_native26 = require("react-native");
3861
+ var React23 = __toESM(require("react"));
3862
+ var import_react_native27 = require("react-native");
3782
3863
  var import_expo_linear_gradient2 = require("expo-linear-gradient");
3783
3864
  var import_jsx_runtime26 = require("react/jsx-runtime");
3784
3865
  function PreviewPlaceholder({ visible, style }) {
3785
3866
  if (!visible) return null;
3786
- const opacityAnim = React22.useRef(new import_react_native26.Animated.Value(0)).current;
3787
- React22.useEffect(() => {
3867
+ const opacityAnim = React23.useRef(new import_react_native27.Animated.Value(0)).current;
3868
+ React23.useEffect(() => {
3788
3869
  if (!visible) return;
3789
- const animation = import_react_native26.Animated.loop(
3790
- import_react_native26.Animated.sequence([
3791
- import_react_native26.Animated.timing(opacityAnim, { toValue: 1, duration: 1500, useNativeDriver: true }),
3792
- import_react_native26.Animated.timing(opacityAnim, { toValue: 2, duration: 1500, useNativeDriver: true }),
3793
- import_react_native26.Animated.timing(opacityAnim, { toValue: 3, duration: 1500, useNativeDriver: true }),
3794
- import_react_native26.Animated.timing(opacityAnim, { toValue: 0, duration: 1500, useNativeDriver: true })
3870
+ const animation = import_react_native27.Animated.loop(
3871
+ import_react_native27.Animated.sequence([
3872
+ import_react_native27.Animated.timing(opacityAnim, { toValue: 1, duration: 1500, useNativeDriver: true }),
3873
+ import_react_native27.Animated.timing(opacityAnim, { toValue: 2, duration: 1500, useNativeDriver: true }),
3874
+ import_react_native27.Animated.timing(opacityAnim, { toValue: 3, duration: 1500, useNativeDriver: true }),
3875
+ import_react_native27.Animated.timing(opacityAnim, { toValue: 0, duration: 1500, useNativeDriver: true })
3795
3876
  ])
3796
3877
  );
3797
3878
  animation.start();
@@ -3802,7 +3883,7 @@ function PreviewPlaceholder({ visible, style }) {
3802
3883
  const opacity3 = opacityAnim.interpolate({ inputRange: [0, 1, 2, 3], outputRange: [0, 0, 1, 0] });
3803
3884
  const opacity4 = opacityAnim.interpolate({ inputRange: [0, 1, 2, 3], outputRange: [0, 0, 0, 1] });
3804
3885
  return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
3805
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native26.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity1 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3886
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native27.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity1 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3806
3887
  import_expo_linear_gradient2.LinearGradient,
3807
3888
  {
3808
3889
  colors: ["rgba(98, 0, 238, 0.45)", "rgba(168, 85, 247, 0.35)"],
@@ -3811,7 +3892,7 @@ function PreviewPlaceholder({ visible, style }) {
3811
3892
  style: { width: "100%", height: "100%" }
3812
3893
  }
3813
3894
  ) }),
3814
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native26.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity2 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3895
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native27.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity2 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3815
3896
  import_expo_linear_gradient2.LinearGradient,
3816
3897
  {
3817
3898
  colors: ["rgba(168, 85, 247, 0.45)", "rgba(139, 92, 246, 0.35)"],
@@ -3820,7 +3901,7 @@ function PreviewPlaceholder({ visible, style }) {
3820
3901
  style: { width: "100%", height: "100%" }
3821
3902
  }
3822
3903
  ) }),
3823
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native26.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity3 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3904
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native27.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity3 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3824
3905
  import_expo_linear_gradient2.LinearGradient,
3825
3906
  {
3826
3907
  colors: ["rgba(139, 92, 246, 0.45)", "rgba(126, 34, 206, 0.35)"],
@@ -3829,7 +3910,7 @@ function PreviewPlaceholder({ visible, style }) {
3829
3910
  style: { width: "100%", height: "100%" }
3830
3911
  }
3831
3912
  ) }),
3832
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native26.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity4 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3913
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native27.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity4 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3833
3914
  import_expo_linear_gradient2.LinearGradient,
3834
3915
  {
3835
3916
  colors: ["rgba(126, 34, 206, 0.45)", "rgba(98, 0, 238, 0.35)"],
@@ -3842,12 +3923,12 @@ function PreviewPlaceholder({ visible, style }) {
3842
3923
  }
3843
3924
 
3844
3925
  // src/components/preview/PreviewImage.tsx
3845
- var import_react_native27 = require("react-native");
3926
+ var import_react_native28 = require("react-native");
3846
3927
  var import_jsx_runtime27 = require("react/jsx-runtime");
3847
3928
  function PreviewImage({ uri, onLoad, style }) {
3848
3929
  if (!uri) return null;
3849
3930
  return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3850
- import_react_native27.Image,
3931
+ import_react_native28.Image,
3851
3932
  {
3852
3933
  source: { uri },
3853
3934
  resizeMode: "cover",
@@ -3858,7 +3939,7 @@ function PreviewImage({ uri, onLoad, style }) {
3858
3939
  }
3859
3940
 
3860
3941
  // src/components/preview/StatsBar.tsx
3861
- var import_react_native28 = require("react-native");
3942
+ var import_react_native29 = require("react-native");
3862
3943
  var import_liquid_glass6 = require("@callstack/liquid-glass");
3863
3944
  var import_lucide_react_native5 = require("lucide-react-native");
3864
3945
 
@@ -3891,7 +3972,7 @@ function StatsBar({
3891
3972
  const theme = useTheme();
3892
3973
  const statsBgColor = theme.scheme === "dark" ? "rgba(24, 24, 27, 0.5)" : "rgba(255, 255, 255, 0.5)";
3893
3974
  return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
3894
- import_react_native28.View,
3975
+ import_react_native29.View,
3895
3976
  {
3896
3977
  style: [
3897
3978
  { position: "absolute", bottom: 12, width: "100%", paddingHorizontal: 12 },
@@ -3907,15 +3988,15 @@ function StatsBar({
3907
3988
  !import_liquid_glass6.isLiquidGlassSupported && { backgroundColor: statsBgColor }
3908
3989
  ],
3909
3990
  effect: "clear",
3910
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_react_native28.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: 16 }, children: [
3991
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_react_native29.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: 16 }, children: [
3911
3992
  /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
3912
- import_react_native28.Pressable,
3993
+ import_react_native29.Pressable,
3913
3994
  {
3914
3995
  disabled: !onPressLike,
3915
3996
  onPress: onPressLike,
3916
3997
  hitSlop: 8,
3917
3998
  style: { paddingVertical: 8 },
3918
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_react_native28.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
3999
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_react_native29.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
3919
4000
  /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
3920
4001
  import_lucide_react_native5.Heart,
3921
4002
  {
@@ -3925,7 +4006,7 @@ function StatsBar({
3925
4006
  fill: isLiked ? theme.colors.danger : "transparent"
3926
4007
  }
3927
4008
  ),
3928
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react_native28.View, { style: { width: 4 } }),
4009
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react_native29.View, { style: { width: 4 } }),
3929
4010
  /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
3930
4011
  Text,
3931
4012
  {
@@ -3941,22 +4022,22 @@ function StatsBar({
3941
4022
  }
3942
4023
  ),
3943
4024
  /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
3944
- import_react_native28.Pressable,
4025
+ import_react_native29.Pressable,
3945
4026
  {
3946
4027
  disabled: !onPressComments,
3947
4028
  onPress: onPressComments,
3948
4029
  hitSlop: 8,
3949
4030
  style: { paddingVertical: 8 },
3950
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_react_native28.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
4031
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_react_native29.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
3951
4032
  /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react_native5.MessageCircle, { size: 16, strokeWidth: 2.5, color: "#FFFFFF" }),
3952
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react_native28.View, { style: { width: 4 } }),
4033
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react_native29.View, { style: { width: 4 } }),
3953
4034
  /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Text, { variant: "caption", style: { color: "#FFFFFF", fontWeight: theme.typography.fontWeight.bold }, children: commentCount })
3954
4035
  ] })
3955
4036
  }
3956
4037
  ),
3957
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_react_native28.View, { style: { flexDirection: "row", alignItems: "center", paddingVertical: 8 }, children: [
3958
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react_native28.View, { style: { transform: [{ scaleY: -1 }] }, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(MergeIcon, { width: 14, height: 14, color: "#FFFFFF" }) }),
3959
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react_native28.View, { style: { width: 4 } }),
4038
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_react_native29.View, { style: { flexDirection: "row", alignItems: "center", paddingVertical: 8 }, children: [
4039
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react_native29.View, { style: { transform: [{ scaleY: -1 }] }, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(MergeIcon, { width: 14, height: 14, color: "#FFFFFF" }) }),
4040
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react_native29.View, { style: { width: 4 } }),
3960
4041
  /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Text, { variant: "caption", style: { color: "#FFFFFF", fontWeight: theme.typography.fontWeight.bold }, children: forkCount })
3961
4042
  ] })
3962
4043
  ] })
@@ -3967,7 +4048,7 @@ function StatsBar({
3967
4048
  }
3968
4049
 
3969
4050
  // src/components/preview/PreviewStatusBadge.tsx
3970
- var import_react_native29 = require("react-native");
4051
+ var import_react_native30 = require("react-native");
3971
4052
  var import_lucide_react_native6 = require("lucide-react-native");
3972
4053
 
3973
4054
  // src/data/apps/types.ts
@@ -4012,7 +4093,7 @@ function PreviewStatusBadge({ status }) {
4012
4093
  const IconComp = STATUS_ICON[status];
4013
4094
  const label = APP_STATUS_LABEL[status] ?? status;
4014
4095
  return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
4015
- import_react_native29.View,
4096
+ import_react_native30.View,
4016
4097
  {
4017
4098
  style: {
4018
4099
  flexDirection: "row",
@@ -4065,10 +4146,10 @@ function PreviewHeroSection({
4065
4146
  }
4066
4147
 
4067
4148
  // src/studio/ui/preview-panel/PreviewMetaSection.tsx
4068
- var import_react_native31 = require("react-native");
4149
+ var import_react_native32 = require("react-native");
4069
4150
 
4070
4151
  // src/components/preview/PreviewMetaRow.tsx
4071
- var import_react_native30 = require("react-native");
4152
+ var import_react_native31 = require("react-native");
4072
4153
  var import_jsx_runtime32 = require("react/jsx-runtime");
4073
4154
  function PreviewMetaRow({
4074
4155
  avatarUri,
@@ -4080,10 +4161,10 @@ function PreviewMetaRow({
4080
4161
  style
4081
4162
  }) {
4082
4163
  const theme = useTheme();
4083
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react_native30.View, { style: [{ alignSelf: "stretch" }, style], children: [
4084
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react_native30.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
4164
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react_native31.View, { style: [{ alignSelf: "stretch" }, style], children: [
4165
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react_native31.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
4085
4166
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Avatar, { uri: avatarUri, name: creatorName, size: 24, style: { marginRight: theme.spacing.sm } }),
4086
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react_native30.View, { style: { flexDirection: "row", alignItems: "center", flex: 1, minWidth: 0, marginRight: theme.spacing.sm }, children: [
4167
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react_native31.View, { style: { flexDirection: "row", alignItems: "center", flex: 1, minWidth: 0, marginRight: theme.spacing.sm }, children: [
4087
4168
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
4088
4169
  Text,
4089
4170
  {
@@ -4098,9 +4179,9 @@ function PreviewMetaRow({
4098
4179
  children: title
4099
4180
  }
4100
4181
  ),
4101
- tag ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react_native30.View, { style: { marginLeft: theme.spacing.sm }, children: tag }) : null
4182
+ tag ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react_native31.View, { style: { marginLeft: theme.spacing.sm }, children: tag }) : null
4102
4183
  ] }),
4103
- rightMetric ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react_native30.View, { children: rightMetric }) : null
4184
+ rightMetric ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react_native31.View, { children: rightMetric }) : null
4104
4185
  ] }),
4105
4186
  subtitle ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
4106
4187
  Text,
@@ -4156,9 +4237,9 @@ function PreviewMetaSection({ app, isOwner, creator, downloadsCount }) {
4156
4237
  subtitle: app.description,
4157
4238
  avatarUri: (creator == null ? void 0 : creator.avatar) ?? null,
4158
4239
  creatorName: (creator == null ? void 0 : creator.name) ?? null,
4159
- tag: isOwner || app.forkedFromAppId ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_react_native31.View, { style: { paddingHorizontal: 8, paddingVertical: 2, borderRadius: 999, backgroundColor: "#3700B3" }, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Text, { variant: "caption", style: { color: "#fff", fontWeight: theme.typography.fontWeight.semibold }, children: app.forkedFromAppId ? "Remix" : "Owner" }) }) : null,
4240
+ tag: isOwner || app.forkedFromAppId ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_react_native32.View, { style: { paddingHorizontal: 8, paddingVertical: 2, borderRadius: 999, backgroundColor: "#3700B3" }, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Text, { variant: "caption", style: { color: "#fff", fontWeight: theme.typography.fontWeight.semibold }, children: app.forkedFromAppId ? "Remix" : "Owner" }) }) : null,
4160
4241
  rightMetric: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
4161
- import_react_native31.View,
4242
+ import_react_native32.View,
4162
4243
  {
4163
4244
  style: {
4164
4245
  flexDirection: "row",
@@ -4192,10 +4273,10 @@ function PreviewMetaSection({ app, isOwner, creator, downloadsCount }) {
4192
4273
  }
4193
4274
 
4194
4275
  // src/studio/ui/preview-panel/PreviewCustomizeSection.tsx
4195
- var import_react_native33 = require("react-native");
4276
+ var import_react_native34 = require("react-native");
4196
4277
 
4197
4278
  // src/studio/ui/preview-panel/PressableCardRow.tsx
4198
- var import_react_native32 = require("react-native");
4279
+ var import_react_native33 = require("react-native");
4199
4280
  var import_jsx_runtime34 = require("react/jsx-runtime");
4200
4281
  function PressableCardRow({
4201
4282
  accessibilityLabel,
@@ -4208,20 +4289,20 @@ function PressableCardRow({
4208
4289
  style
4209
4290
  }) {
4210
4291
  return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
4211
- import_react_native32.Pressable,
4292
+ import_react_native33.Pressable,
4212
4293
  {
4213
4294
  accessibilityRole: "button",
4214
4295
  accessibilityLabel,
4215
4296
  disabled,
4216
4297
  onPress,
4217
4298
  style: ({ pressed }) => ({ opacity: disabled ? 0.6 : pressed ? 0.85 : 1 }),
4218
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Card, { padded: false, border: false, style, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react_native32.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
4299
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Card, { padded: false, border: false, style, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react_native33.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
4219
4300
  left,
4220
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react_native32.View, { style: { flex: 1, minWidth: 0 }, children: [
4301
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react_native33.View, { style: { flex: 1, minWidth: 0 }, children: [
4221
4302
  title,
4222
4303
  subtitle ? subtitle : null
4223
4304
  ] }),
4224
- right ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react_native32.View, { style: { marginLeft: 16 }, children: right }) : null
4305
+ right ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react_native33.View, { style: { marginLeft: 16 }, children: right }) : null
4225
4306
  ] }) })
4226
4307
  }
4227
4308
  );
@@ -4263,7 +4344,7 @@ function PreviewCustomizeSection({
4263
4344
  return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
4264
4345
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(SectionTitle, { children: "Customize" }),
4265
4346
  showProcessing ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4266
- import_react_native33.View,
4347
+ import_react_native34.View,
4267
4348
  {
4268
4349
  style: {
4269
4350
  flexDirection: "row",
@@ -4277,7 +4358,7 @@ function PreviewCustomizeSection({
4277
4358
  },
4278
4359
  children: [
4279
4360
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4280
- import_react_native33.View,
4361
+ import_react_native34.View,
4281
4362
  {
4282
4363
  style: {
4283
4364
  width: 40,
@@ -4288,10 +4369,10 @@ function PreviewCustomizeSection({
4288
4369
  backgroundColor: withAlpha(theme.colors.warning, 0.1),
4289
4370
  marginRight: theme.spacing.lg
4290
4371
  },
4291
- children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react_native33.ActivityIndicator, { color: theme.colors.warning, size: "small" })
4372
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react_native34.ActivityIndicator, { color: theme.colors.warning, size: "small" })
4292
4373
  }
4293
4374
  ),
4294
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_react_native33.View, { style: { flex: 1, minWidth: 0 }, children: [
4375
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_react_native34.View, { style: { flex: 1, minWidth: 0 }, children: [
4295
4376
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Text, { style: { color: theme.colors.text, fontSize: 16, lineHeight: 20, fontWeight: theme.typography.fontWeight.semibold }, children: app.status === "error" ? "Error" : "Processing" }),
4296
4377
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Text, { style: { color: theme.colors.textMuted, fontSize: 12, lineHeight: 16, marginTop: 2 }, children: statusDescription(app.status, app.statusError) })
4297
4378
  ] })
@@ -4312,7 +4393,7 @@ function PreviewCustomizeSection({
4312
4393
  marginBottom: theme.spacing.sm
4313
4394
  },
4314
4395
  left: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4315
- import_react_native33.View,
4396
+ import_react_native34.View,
4316
4397
  {
4317
4398
  style: {
4318
4399
  width: 40,
@@ -4345,7 +4426,7 @@ function PreviewCustomizeSection({
4345
4426
  marginBottom: theme.spacing.sm
4346
4427
  },
4347
4428
  left: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4348
- import_react_native33.View,
4429
+ import_react_native34.View,
4349
4430
  {
4350
4431
  style: {
4351
4432
  width: 40,
@@ -4368,17 +4449,17 @@ function PreviewCustomizeSection({
4368
4449
  }
4369
4450
 
4370
4451
  // src/studio/ui/preview-panel/PreviewCollaborateSection.tsx
4371
- var React28 = __toESM(require("react"));
4372
- var import_react_native39 = require("react-native");
4452
+ var React29 = __toESM(require("react"));
4453
+ var import_react_native40 = require("react-native");
4373
4454
  var import_lucide_react_native9 = require("lucide-react-native");
4374
4455
 
4375
4456
  // src/components/merge-requests/MergeRequestStatusCard.tsx
4376
- var React24 = __toESM(require("react"));
4377
- var import_react_native35 = require("react-native");
4457
+ var React25 = __toESM(require("react"));
4458
+ var import_react_native36 = require("react-native");
4378
4459
  var import_lucide_react_native7 = require("lucide-react-native");
4379
4460
 
4380
4461
  // src/components/primitives/MarkdownText.tsx
4381
- var import_react_native34 = require("react-native");
4462
+ var import_react_native35 = require("react-native");
4382
4463
  var import_react_native_markdown_display = __toESM(require("react-native-markdown-display"));
4383
4464
  var import_jsx_runtime37 = require("react/jsx-runtime");
4384
4465
  function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
@@ -4391,7 +4472,7 @@ function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
4391
4472
  const codeTextColor = isDark ? "#FFFFFF" : theme.colors.text;
4392
4473
  const paragraphBottom = variant === "mergeRequest" ? 8 : 6;
4393
4474
  const baseLineHeight = variant === "mergeRequest" ? 22 : 20;
4394
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_react_native34.View, { style, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
4475
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_react_native35.View, { style, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
4395
4476
  import_react_native_markdown_display.default,
4396
4477
  {
4397
4478
  style: {
@@ -4404,7 +4485,7 @@ function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
4404
4485
  paddingHorizontal: variant === "mergeRequest" ? 6 : 4,
4405
4486
  paddingVertical: variant === "mergeRequest" ? 2 : 0,
4406
4487
  borderRadius: variant === "mergeRequest" ? 6 : 4,
4407
- fontFamily: import_react_native34.Platform.OS === "ios" ? "Menlo" : "monospace",
4488
+ fontFamily: import_react_native35.Platform.OS === "ios" ? "Menlo" : "monospace",
4408
4489
  fontSize: 13
4409
4490
  },
4410
4491
  code_block: {
@@ -4455,11 +4536,11 @@ function toIsoString(input) {
4455
4536
  }
4456
4537
 
4457
4538
  // src/components/merge-requests/useControlledExpansion.ts
4458
- var React23 = __toESM(require("react"));
4539
+ var React24 = __toESM(require("react"));
4459
4540
  function useControlledExpansion(props) {
4460
- const [uncontrolled, setUncontrolled] = React23.useState(false);
4541
+ const [uncontrolled, setUncontrolled] = React24.useState(false);
4461
4542
  const expanded = props.expanded ?? uncontrolled;
4462
- const setExpanded = React23.useCallback(
4543
+ const setExpanded = React24.useCallback(
4463
4544
  (next) => {
4464
4545
  var _a;
4465
4546
  (_a = props.onExpandedChange) == null ? void 0 : _a.call(props, next);
@@ -4484,8 +4565,8 @@ function MergeRequestStatusCard({
4484
4565
  const isDark = theme.scheme === "dark";
4485
4566
  const textColor = isDark ? "#FFFFFF" : "#000000";
4486
4567
  const subTextColor = isDark ? "#A1A1AA" : "#71717A";
4487
- const status = React24.useMemo(() => getMergeRequestStatusDisplay(String(mergeRequest.status)), [mergeRequest.status]);
4488
- const { StatusIcon, iconColor, bgColor, statusText } = React24.useMemo(() => {
4568
+ const status = React25.useMemo(() => getMergeRequestStatusDisplay(String(mergeRequest.status)), [mergeRequest.status]);
4569
+ const { StatusIcon, iconColor, bgColor, statusText } = React25.useMemo(() => {
4489
4570
  switch (mergeRequest.status) {
4490
4571
  case "approved":
4491
4572
  case "merged":
@@ -4516,15 +4597,15 @@ function MergeRequestStatusCard({
4516
4597
  const createdIso = toIsoString(mergeRequest.createdAt ?? null);
4517
4598
  const headerTimeAgo = updatedIso ? formatTimeAgo(updatedIso) : "";
4518
4599
  const createdTimeAgo = createdIso ? formatTimeAgo(createdIso) : "";
4519
- const rotate = React24.useRef(new import_react_native35.Animated.Value(expanded ? 1 : 0)).current;
4520
- React24.useEffect(() => {
4521
- import_react_native35.Animated.timing(rotate, {
4600
+ const rotate = React25.useRef(new import_react_native36.Animated.Value(expanded ? 1 : 0)).current;
4601
+ React25.useEffect(() => {
4602
+ import_react_native36.Animated.timing(rotate, {
4522
4603
  toValue: expanded ? 1 : 0,
4523
4604
  duration: 200,
4524
4605
  useNativeDriver: true
4525
4606
  }).start();
4526
4607
  }, [expanded, rotate]);
4527
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_react_native35.Pressable, { onPress: () => setExpanded(!expanded), style: ({ pressed }) => [{ opacity: pressed ? 0.95 : 1 }], children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
4608
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_react_native36.Pressable, { onPress: () => setExpanded(!expanded), style: ({ pressed }) => [{ opacity: pressed ? 0.95 : 1 }], children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
4528
4609
  Card,
4529
4610
  {
4530
4611
  padded: false,
@@ -4537,10 +4618,10 @@ function MergeRequestStatusCard({
4537
4618
  style
4538
4619
  ],
4539
4620
  children: [
4540
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_react_native35.View, { style: { flexDirection: "row", alignItems: "center", gap: theme.spacing.lg }, children: [
4541
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_react_native35.View, { style: { width: 40, height: 40, borderRadius: 999, alignItems: "center", justifyContent: "center", backgroundColor: bgColor }, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(StatusIcon, { size: 20, color: iconColor }) }),
4542
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_react_native35.View, { style: { flex: 1, minWidth: 0 }, children: [
4543
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_react_native35.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" }, children: [
4621
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_react_native36.View, { style: { flexDirection: "row", alignItems: "center", gap: theme.spacing.lg }, children: [
4622
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_react_native36.View, { style: { width: 40, height: 40, borderRadius: 999, alignItems: "center", justifyContent: "center", backgroundColor: bgColor }, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(StatusIcon, { size: 20, color: iconColor }) }),
4623
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_react_native36.View, { style: { flex: 1, minWidth: 0 }, children: [
4624
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_react_native36.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" }, children: [
4544
4625
  /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
4545
4626
  Text,
4546
4627
  {
@@ -4559,8 +4640,8 @@ function MergeRequestStatusCard({
4559
4640
  ] }),
4560
4641
  /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Text, { style: { fontSize: 12, lineHeight: 16, color: theme.colors.textMuted }, numberOfLines: 1, children: mergeRequest.title ?? "Untitled merge request" })
4561
4642
  ] }),
4562
- headerRight ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_react_native35.View, { children: headerRight }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
4563
- import_react_native35.Animated.View,
4643
+ headerRight ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_react_native36.View, { children: headerRight }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
4644
+ import_react_native36.Animated.View,
4564
4645
  {
4565
4646
  style: {
4566
4647
  transform: [
@@ -4573,7 +4654,7 @@ function MergeRequestStatusCard({
4573
4654
  }
4574
4655
  )
4575
4656
  ] }),
4576
- expanded ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_react_native35.View, { style: { marginTop: 16, marginLeft: 56 }, children: [
4657
+ expanded ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_react_native36.View, { style: { marginTop: 16, marginLeft: 56 }, children: [
4577
4658
  /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
4578
4659
  Text,
4579
4660
  {
@@ -4608,17 +4689,17 @@ function MergeRequestStatusCard({
4608
4689
  }
4609
4690
 
4610
4691
  // src/components/merge-requests/ReviewMergeRequestCarousel.tsx
4611
- var React27 = __toESM(require("react"));
4612
- var import_react_native38 = require("react-native");
4692
+ var React28 = __toESM(require("react"));
4693
+ var import_react_native39 = require("react-native");
4613
4694
 
4614
4695
  // src/components/merge-requests/ReviewMergeRequestCard.tsx
4615
- var React26 = __toESM(require("react"));
4616
- var import_react_native37 = require("react-native");
4696
+ var React27 = __toESM(require("react"));
4697
+ var import_react_native38 = require("react-native");
4617
4698
  var import_lucide_react_native8 = require("lucide-react-native");
4618
4699
 
4619
4700
  // src/components/merge-requests/ReviewMergeRequestActionButton.tsx
4620
- var React25 = __toESM(require("react"));
4621
- var import_react_native36 = require("react-native");
4701
+ var React26 = __toESM(require("react"));
4702
+ var import_react_native37 = require("react-native");
4622
4703
  var import_jsx_runtime39 = require("react/jsx-runtime");
4623
4704
  function ReviewMergeRequestActionButton({
4624
4705
  accessibilityLabel,
@@ -4628,14 +4709,14 @@ function ReviewMergeRequestActionButton({
4628
4709
  children,
4629
4710
  iconOnly
4630
4711
  }) {
4631
- const [pressed, setPressed] = React25.useState(false);
4712
+ const [pressed, setPressed] = React26.useState(false);
4632
4713
  const height = iconOnly ? 36 : 40;
4633
4714
  const width = iconOnly ? 36 : void 0;
4634
4715
  const paddingHorizontal = iconOnly ? 0 : 16;
4635
4716
  const paddingVertical = iconOnly ? 0 : 8;
4636
4717
  const opacity = disabled ? 0.5 : pressed ? 0.9 : 1;
4637
4718
  return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
4638
- import_react_native36.View,
4719
+ import_react_native37.View,
4639
4720
  {
4640
4721
  style: {
4641
4722
  width,
@@ -4650,7 +4731,7 @@ function ReviewMergeRequestActionButton({
4650
4731
  justifyContent: "center"
4651
4732
  },
4652
4733
  children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
4653
- import_react_native36.Pressable,
4734
+ import_react_native37.Pressable,
4654
4735
  {
4655
4736
  accessibilityRole: "button",
4656
4737
  accessibilityLabel,
@@ -4690,14 +4771,14 @@ function ReviewMergeRequestCard({
4690
4771
  onTest
4691
4772
  }) {
4692
4773
  const theme = useTheme();
4693
- const status = React26.useMemo(() => getMergeRequestStatusDisplay(mr.status), [mr.status]);
4774
+ const status = React27.useMemo(() => getMergeRequestStatusDisplay(mr.status), [mr.status]);
4694
4775
  const canAct = mr.status === "open";
4695
- const rotate = React26.useRef(new import_react_native37.Animated.Value(isExpanded ? 1 : 0)).current;
4696
- React26.useEffect(() => {
4697
- import_react_native37.Animated.timing(rotate, { toValue: isExpanded ? 1 : 0, duration: 200, useNativeDriver: true }).start();
4776
+ const rotate = React27.useRef(new import_react_native38.Animated.Value(isExpanded ? 1 : 0)).current;
4777
+ React27.useEffect(() => {
4778
+ import_react_native38.Animated.timing(rotate, { toValue: isExpanded ? 1 : 0, duration: 200, useNativeDriver: true }).start();
4698
4779
  }, [isExpanded, rotate]);
4699
4780
  const position = total > 1 ? `${index + 1}/${total}` : "Merge request";
4700
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_native37.Pressable, { onPress: onToggle, style: ({ pressed }) => ({ opacity: pressed ? 0.95 : 1 }), children: /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
4781
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_native38.Pressable, { onPress: onToggle, style: ({ pressed }) => ({ opacity: pressed ? 0.95 : 1 }), children: /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
4701
4782
  Card,
4702
4783
  {
4703
4784
  padded: false,
@@ -4710,9 +4791,9 @@ function ReviewMergeRequestCard({
4710
4791
  }
4711
4792
  ],
4712
4793
  children: [
4713
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native37.View, { style: { flexDirection: "row", alignItems: "center", gap: 12 }, children: [
4794
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native38.View, { style: { flexDirection: "row", alignItems: "center", gap: 12 }, children: [
4714
4795
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Avatar, { size: 40, uri: (creator == null ? void 0 : creator.avatar) ?? null, name: (creator == null ? void 0 : creator.name) ?? void 0 }),
4715
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native37.View, { style: { flex: 1, minWidth: 0 }, children: [
4796
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native38.View, { style: { flex: 1, minWidth: 0 }, children: [
4716
4797
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
4717
4798
  Text,
4718
4799
  {
@@ -4728,7 +4809,7 @@ function ReviewMergeRequestCard({
4728
4809
  ] })
4729
4810
  ] }),
4730
4811
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
4731
- import_react_native37.Animated.View,
4812
+ import_react_native38.Animated.View,
4732
4813
  {
4733
4814
  style: {
4734
4815
  transform: [{ rotate: rotate.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "180deg"] }) }]
@@ -4737,7 +4818,7 @@ function ReviewMergeRequestCard({
4737
4818
  }
4738
4819
  )
4739
4820
  ] }),
4740
- isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native37.View, { style: { marginTop: 16 }, children: [
4821
+ isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native38.View, { style: { marginTop: 16 }, children: [
4741
4822
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
4742
4823
  Text,
4743
4824
  {
@@ -4755,9 +4836,9 @@ function ReviewMergeRequestCard({
4755
4836
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Text, { style: { color: theme.colors.textMuted, fontSize: 12, lineHeight: 16, marginBottom: 12 }, children: creator ? `${creator.approvedOpenedMergeRequests} approved merge${creator.approvedOpenedMergeRequests !== 1 ? "s" : ""}` : "Loading stats..." }),
4756
4837
  mr.description ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(MarkdownText, { markdown: mr.description, variant: "mergeRequest" }) : null
4757
4838
  ] }) : null,
4758
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_native37.View, { style: { height: 1, backgroundColor: withAlpha(theme.colors.borderStrong, 0.5), marginTop: 12, marginBottom: 12 } }),
4759
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native37.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" }, children: [
4760
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native37.View, { style: { flexDirection: "row", gap: 8 }, children: [
4839
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_native38.View, { style: { height: 1, backgroundColor: withAlpha(theme.colors.borderStrong, 0.5), marginTop: 12, marginBottom: 12 } }),
4840
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native38.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" }, children: [
4841
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native38.View, { style: { flexDirection: "row", gap: 8 }, children: [
4761
4842
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
4762
4843
  ReviewMergeRequestActionButton,
4763
4844
  {
@@ -4766,7 +4847,7 @@ function ReviewMergeRequestCard({
4766
4847
  disabled: !canAct || isAnyProcessing,
4767
4848
  onPress: onReject,
4768
4849
  iconOnly: !isExpanded,
4769
- children: /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native37.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
4850
+ children: /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native38.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
4770
4851
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react_native8.X, { size: 18, color: "#FFFFFF" }),
4771
4852
  isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Text, { style: { fontSize: 13, color: "#FFFFFF", fontWeight: theme.typography.fontWeight.semibold }, children: "Reject" }) : null
4772
4853
  ] })
@@ -4780,10 +4861,10 @@ function ReviewMergeRequestCard({
4780
4861
  disabled: !canAct || isAnyProcessing,
4781
4862
  onPress: onApprove,
4782
4863
  iconOnly: !isExpanded,
4783
- children: isProcessing ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native37.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
4784
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_native37.ActivityIndicator, { size: "small", color: "#FFFFFF" }),
4864
+ children: isProcessing ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native38.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
4865
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_native38.ActivityIndicator, { size: "small", color: "#FFFFFF" }),
4785
4866
  isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Text, { style: { fontSize: 13, color: "#FFFFFF", fontWeight: theme.typography.fontWeight.semibold }, children: "Processing" }) : null
4786
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native37.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
4867
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native38.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
4787
4868
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react_native8.Check, { size: 18, color: "#FFFFFF" }),
4788
4869
  isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Text, { style: { fontSize: 13, color: "#FFFFFF", fontWeight: theme.typography.fontWeight.semibold }, children: "Approve" }) : null
4789
4870
  ] })
@@ -4798,7 +4879,7 @@ function ReviewMergeRequestCard({
4798
4879
  disabled: isBuilding || isTestingThis,
4799
4880
  onPress: onTest,
4800
4881
  iconOnly: !isExpanded,
4801
- children: isTestingThis ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_native37.ActivityIndicator, { size: "small", color: "#888" }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native37.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
4882
+ children: isTestingThis ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_native38.ActivityIndicator, { size: "small", color: "#888" }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native38.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
4802
4883
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react_native8.Play, { size: 14, color: theme.colors.text }),
4803
4884
  isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Text, { style: { fontSize: 13, color: theme.colors.text, fontWeight: theme.typography.fontWeight.semibold }, children: "Test" }) : null
4804
4885
  ] })
@@ -4824,32 +4905,32 @@ function ReviewMergeRequestCarousel({
4824
4905
  style
4825
4906
  }) {
4826
4907
  const theme = useTheme();
4827
- const { width } = (0, import_react_native38.useWindowDimensions)();
4828
- const [expanded, setExpanded] = React27.useState({});
4829
- const carouselScrollX = React27.useRef(new import_react_native38.Animated.Value(0)).current;
4908
+ const { width } = (0, import_react_native39.useWindowDimensions)();
4909
+ const [expanded, setExpanded] = React28.useState({});
4910
+ const carouselScrollX = React28.useRef(new import_react_native39.Animated.Value(0)).current;
4830
4911
  const peekAmount = 24;
4831
4912
  const gap = 16;
4832
- const cardWidth = React27.useMemo(() => Math.max(1, width - theme.spacing.lg * 2 - peekAmount), [peekAmount, theme.spacing.lg, width]);
4913
+ const cardWidth = React28.useMemo(() => Math.max(1, width - theme.spacing.lg * 2 - peekAmount), [peekAmount, theme.spacing.lg, width]);
4833
4914
  const snapInterval = cardWidth + gap;
4834
4915
  const dotColor = theme.scheme === "dark" ? "#FFFFFF" : "#000000";
4835
4916
  if (mergeRequests.length === 0) return null;
4836
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_react_native38.View, { style: [{ marginHorizontal: -theme.spacing.lg }, style], children: [
4917
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_react_native39.View, { style: [{ marginHorizontal: -theme.spacing.lg }, style], children: [
4837
4918
  /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
4838
- import_react_native38.FlatList,
4919
+ import_react_native39.FlatList,
4839
4920
  {
4840
4921
  horizontal: true,
4841
4922
  data: mergeRequests,
4842
4923
  keyExtractor: (mr) => mr.id,
4843
4924
  showsHorizontalScrollIndicator: false,
4844
4925
  contentContainerStyle: { paddingHorizontal: theme.spacing.lg, paddingVertical: theme.spacing.sm },
4845
- ItemSeparatorComponent: () => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_react_native38.View, { style: { width: gap } }),
4926
+ ItemSeparatorComponent: () => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_react_native39.View, { style: { width: gap } }),
4846
4927
  snapToAlignment: "start",
4847
4928
  decelerationRate: "fast",
4848
4929
  snapToInterval: snapInterval,
4849
4930
  disableIntervalMomentum: true,
4850
4931
  style: { paddingRight: peekAmount },
4851
- ListFooterComponent: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_react_native38.View, { style: { width: peekAmount } }),
4852
- onScroll: import_react_native38.Animated.event([{ nativeEvent: { contentOffset: { x: carouselScrollX } } }], {
4932
+ ListFooterComponent: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_react_native39.View, { style: { width: peekAmount } }),
4933
+ onScroll: import_react_native39.Animated.event([{ nativeEvent: { contentOffset: { x: carouselScrollX } } }], {
4853
4934
  useNativeDriver: false
4854
4935
  }),
4855
4936
  scrollEventThrottle: 16,
@@ -4860,7 +4941,7 @@ function ReviewMergeRequestCarousel({
4860
4941
  const isProcessing = Boolean(processingMrId && processingMrId === item.id);
4861
4942
  const isAnyProcessing = Boolean(processingMrId);
4862
4943
  const isTestingThis = Boolean(testingMrId && testingMrId === item.id);
4863
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_react_native38.View, { style: { width: cardWidth }, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
4944
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_react_native39.View, { style: { width: cardWidth }, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
4864
4945
  ReviewMergeRequestCard,
4865
4946
  {
4866
4947
  mr: item,
@@ -4881,7 +4962,7 @@ function ReviewMergeRequestCarousel({
4881
4962
  }
4882
4963
  }
4883
4964
  ),
4884
- mergeRequests.length >= 1 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_react_native38.View, { style: { flexDirection: "row", justifyContent: "center", columnGap: 8, marginTop: theme.spacing.md }, children: mergeRequests.map((mr, index) => {
4965
+ mergeRequests.length >= 1 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_react_native39.View, { style: { flexDirection: "row", justifyContent: "center", columnGap: 8, marginTop: theme.spacing.md }, children: mergeRequests.map((mr, index) => {
4885
4966
  const inputRange = [(index - 1) * snapInterval, index * snapInterval, (index + 1) * snapInterval];
4886
4967
  const scale = carouselScrollX.interpolate({
4887
4968
  inputRange,
@@ -4894,7 +4975,7 @@ function ReviewMergeRequestCarousel({
4894
4975
  extrapolate: "clamp"
4895
4976
  });
4896
4977
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
4897
- import_react_native38.Animated.View,
4978
+ import_react_native39.Animated.View,
4898
4979
  {
4899
4980
  style: {
4900
4981
  width: 8,
@@ -4928,7 +5009,7 @@ function PreviewCollaborateSection({
4928
5009
  onTestMr
4929
5010
  }) {
4930
5011
  const theme = useTheme();
4931
- const [submittingMr, setSubmittingMr] = React28.useState(false);
5012
+ const [submittingMr, setSubmittingMr] = React29.useState(false);
4932
5013
  const hasSection = canSubmitMergeRequest || incomingMergeRequests.length > 0 || outgoingMergeRequests.length > 0;
4933
5014
  if (!hasSection) return null;
4934
5015
  const showActionsSubtitle = canSubmitMergeRequest && onSubmitMergeRequest || onTestMr && incomingMergeRequests.length > 0;
@@ -4955,7 +5036,7 @@ function PreviewCollaborateSection({
4955
5036
  accessibilityLabel: "Submit merge request",
4956
5037
  disabled: submittingMr,
4957
5038
  onPress: () => {
4958
- import_react_native39.Alert.alert(
5039
+ import_react_native40.Alert.alert(
4959
5040
  "Submit Merge Request",
4960
5041
  "Are you sure you want to submit your changes to the original app?",
4961
5042
  [
@@ -4981,7 +5062,7 @@ function PreviewCollaborateSection({
4981
5062
  marginBottom: theme.spacing.sm
4982
5063
  },
4983
5064
  left: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4984
- import_react_native39.View,
5065
+ import_react_native40.View,
4985
5066
  {
4986
5067
  style: {
4987
5068
  width: 40,
@@ -4992,7 +5073,7 @@ function PreviewCollaborateSection({
4992
5073
  backgroundColor: withAlpha("#03DAC6", 0.1),
4993
5074
  marginRight: theme.spacing.lg
4994
5075
  },
4995
- children: submittingMr ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_react_native39.ActivityIndicator, { color: "#03DAC6", size: "small" }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(MergeIcon, { width: 20, height: 20, color: "#03DAC6" })
5076
+ children: submittingMr ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_react_native40.ActivityIndicator, { color: "#03DAC6", size: "small" }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(MergeIcon, { width: 20, height: 20, color: "#03DAC6" })
4996
5077
  }
4997
5078
  ),
4998
5079
  title: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Text, { style: { color: theme.colors.text, fontSize: 16, lineHeight: 20, fontWeight: theme.typography.fontWeight.semibold }, children: "Submit your new changes" }),
@@ -5030,13 +5111,13 @@ function PreviewCollaborateSection({
5030
5111
  children: "History"
5031
5112
  }
5032
5113
  ),
5033
- outgoingMergeRequests.map((mr) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_react_native39.View, { style: { marginBottom: theme.spacing.sm }, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(MergeRequestStatusCard, { mergeRequest: toMergeRequestSummary(mr) }) }, mr.id))
5114
+ outgoingMergeRequests.map((mr) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_react_native40.View, { style: { marginBottom: theme.spacing.sm }, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(MergeRequestStatusCard, { mergeRequest: toMergeRequestSummary(mr) }) }, mr.id))
5034
5115
  ] }) : null
5035
5116
  ] });
5036
5117
  }
5037
5118
 
5038
5119
  // src/studio/ui/preview-panel/usePreviewPanelData.ts
5039
- var React30 = __toESM(require("react"));
5120
+ var React31 = __toESM(require("react"));
5040
5121
 
5041
5122
  // src/data/apps/images/remote.ts
5042
5123
  var AppImagesRemoteDataSourceImpl = class extends BaseRemote {
@@ -5087,7 +5168,7 @@ var AppImagesRepositoryImpl = class extends BaseRepository {
5087
5168
  var appImagesRepository = new AppImagesRepositoryImpl(appImagesRemoteDataSource);
5088
5169
 
5089
5170
  // src/studio/hooks/useAppStats.ts
5090
- var React29 = __toESM(require("react"));
5171
+ var React30 = __toESM(require("react"));
5091
5172
  var Haptics2 = __toESM(require("expo-haptics"));
5092
5173
 
5093
5174
  // src/data/likes/remote.ts
@@ -5156,34 +5237,34 @@ function useAppStats({
5156
5237
  initialIsLiked = false,
5157
5238
  onOpenComments
5158
5239
  }) {
5159
- const [likeCount, setLikeCount] = React29.useState(initialLikes);
5160
- const [commentCount, setCommentCount] = React29.useState(initialComments);
5161
- const [forkCount, setForkCount] = React29.useState(initialForks);
5162
- const [isLiked, setIsLiked] = React29.useState(initialIsLiked);
5163
- const didMutateRef = React29.useRef(false);
5164
- const lastAppIdRef = React29.useRef("");
5165
- React29.useEffect(() => {
5240
+ const [likeCount, setLikeCount] = React30.useState(initialLikes);
5241
+ const [commentCount, setCommentCount] = React30.useState(initialComments);
5242
+ const [forkCount, setForkCount] = React30.useState(initialForks);
5243
+ const [isLiked, setIsLiked] = React30.useState(initialIsLiked);
5244
+ const didMutateRef = React30.useRef(false);
5245
+ const lastAppIdRef = React30.useRef("");
5246
+ React30.useEffect(() => {
5166
5247
  if (lastAppIdRef.current === appId) return;
5167
5248
  lastAppIdRef.current = appId;
5168
5249
  didMutateRef.current = false;
5169
5250
  }, [appId]);
5170
- React29.useEffect(() => {
5251
+ React30.useEffect(() => {
5171
5252
  if (didMutateRef.current) return;
5172
5253
  setLikeCount(initialLikes);
5173
5254
  }, [appId, initialLikes]);
5174
- React29.useEffect(() => {
5255
+ React30.useEffect(() => {
5175
5256
  if (didMutateRef.current) return;
5176
5257
  setCommentCount(initialComments);
5177
5258
  }, [appId, initialComments]);
5178
- React29.useEffect(() => {
5259
+ React30.useEffect(() => {
5179
5260
  if (didMutateRef.current) return;
5180
5261
  setForkCount(initialForks);
5181
5262
  }, [appId, initialForks]);
5182
- React29.useEffect(() => {
5263
+ React30.useEffect(() => {
5183
5264
  if (didMutateRef.current) return;
5184
5265
  setIsLiked(initialIsLiked);
5185
5266
  }, [appId, initialIsLiked]);
5186
- const handleLike = React29.useCallback(async () => {
5267
+ const handleLike = React30.useCallback(async () => {
5187
5268
  var _a, _b;
5188
5269
  if (!appId) return;
5189
5270
  didMutateRef.current = true;
@@ -5207,7 +5288,7 @@ function useAppStats({
5207
5288
  setLikeCount((prev) => Math.max(0, prev + (newIsLiked ? -1 : 1)));
5208
5289
  }
5209
5290
  }, [appId, isLiked, likeCount]);
5210
- const handleOpenComments = React29.useCallback(() => {
5291
+ const handleOpenComments = React30.useCallback(() => {
5211
5292
  if (!appId) return;
5212
5293
  try {
5213
5294
  void Haptics2.impactAsync(Haptics2.ImpactFeedbackStyle.Light);
@@ -5222,11 +5303,11 @@ function useAppStats({
5222
5303
  var LIKE_DEBUG_PREFIX = "[COMERGE_LIKE_DEBUG]";
5223
5304
  function usePreviewPanelData(params) {
5224
5305
  const { app, isOwner, outgoingMergeRequests, onOpenComments, commentCountOverride } = params;
5225
- const [imageUrl, setImageUrl] = React30.useState(null);
5226
- const [imageLoaded, setImageLoaded] = React30.useState(false);
5227
- const [insights, setInsights] = React30.useState({ likes: 0, comments: 0, forks: 0, downloads: 0 });
5228
- const [creator, setCreator] = React30.useState(null);
5229
- React30.useEffect(() => {
5306
+ const [imageUrl, setImageUrl] = React31.useState(null);
5307
+ const [imageLoaded, setImageLoaded] = React31.useState(false);
5308
+ const [insights, setInsights] = React31.useState({ likes: 0, comments: 0, forks: 0, downloads: 0 });
5309
+ const [creator, setCreator] = React31.useState(null);
5310
+ React31.useEffect(() => {
5230
5311
  if (!(app == null ? void 0 : app.id)) return;
5231
5312
  let cancelled = false;
5232
5313
  (async () => {
@@ -5241,7 +5322,7 @@ function usePreviewPanelData(params) {
5241
5322
  cancelled = true;
5242
5323
  };
5243
5324
  }, [app == null ? void 0 : app.id]);
5244
- React30.useEffect(() => {
5325
+ React31.useEffect(() => {
5245
5326
  if (!(app == null ? void 0 : app.createdBy)) return;
5246
5327
  let cancelled = false;
5247
5328
  (async () => {
@@ -5257,10 +5338,10 @@ function usePreviewPanelData(params) {
5257
5338
  cancelled = true;
5258
5339
  };
5259
5340
  }, [app == null ? void 0 : app.createdBy]);
5260
- React30.useEffect(() => {
5341
+ React31.useEffect(() => {
5261
5342
  setImageLoaded(false);
5262
5343
  }, [app == null ? void 0 : app.id]);
5263
- React30.useEffect(() => {
5344
+ React31.useEffect(() => {
5264
5345
  if (!(app == null ? void 0 : app.id)) return;
5265
5346
  let cancelled = false;
5266
5347
  (async () => {
@@ -5285,7 +5366,7 @@ function usePreviewPanelData(params) {
5285
5366
  cancelled = true;
5286
5367
  };
5287
5368
  }, [app == null ? void 0 : app.id]);
5288
- React30.useEffect(() => {
5369
+ React31.useEffect(() => {
5289
5370
  if (!(app == null ? void 0 : app.id)) return;
5290
5371
  log.debug(
5291
5372
  `${LIKE_DEBUG_PREFIX} usePreviewPanelData.appChanged appId=${app.id} app.isLiked=${String(app.isLiked)}`
@@ -5299,7 +5380,7 @@ function usePreviewPanelData(params) {
5299
5380
  initialIsLiked: Boolean(app == null ? void 0 : app.isLiked),
5300
5381
  onOpenComments
5301
5382
  });
5302
- const canSubmitMergeRequest = React30.useMemo(() => {
5383
+ const canSubmitMergeRequest = React31.useMemo(() => {
5303
5384
  if (!isOwner) return false;
5304
5385
  if (!app) return false;
5305
5386
  if (!app.forkedFromAppId) return false;
@@ -5354,9 +5435,9 @@ function PreviewPanel({
5354
5435
  });
5355
5436
  const header = /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(PreviewPanelHeader, { isOwner, onClose, onNavigateHome, onGoToChat });
5356
5437
  if (loading || !app) {
5357
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(PreviewPage, { header, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_react_native40.View, { style: { flex: 1, justifyContent: "center", alignItems: "center", padding: 24 }, children: [
5358
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native40.ActivityIndicator, {}),
5359
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native40.View, { style: { height: 12 } }),
5438
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(PreviewPage, { header, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_react_native41.View, { style: { flex: 1, justifyContent: "center", alignItems: "center", padding: 24 }, children: [
5439
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native41.ActivityIndicator, {}),
5440
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native41.View, { style: { height: 12 } }),
5360
5441
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Text, { variant: "bodyMuted", children: "Loading app\u2026" })
5361
5442
  ] }) });
5362
5443
  }
@@ -5412,22 +5493,22 @@ function PreviewPanel({
5412
5493
  }
5413
5494
 
5414
5495
  // src/studio/ui/ChatPanel.tsx
5415
- var React35 = __toESM(require("react"));
5416
- var import_react_native48 = require("react-native");
5496
+ var React36 = __toESM(require("react"));
5497
+ var import_react_native49 = require("react-native");
5417
5498
 
5418
5499
  // src/components/chat/ChatPage.tsx
5419
- var React33 = __toESM(require("react"));
5420
- var import_react_native44 = require("react-native");
5500
+ var React34 = __toESM(require("react"));
5501
+ var import_react_native45 = require("react-native");
5421
5502
  var import_react_native_safe_area_context4 = require("react-native-safe-area-context");
5422
5503
  var import_react_native_reanimated2 = __toESM(require("react-native-reanimated"));
5423
5504
 
5424
5505
  // src/components/chat/ChatMessageList.tsx
5425
- var React32 = __toESM(require("react"));
5426
- var import_react_native43 = require("react-native");
5506
+ var React33 = __toESM(require("react"));
5507
+ var import_react_native44 = require("react-native");
5427
5508
  var import_bottom_sheet5 = require("@gorhom/bottom-sheet");
5428
5509
 
5429
5510
  // src/components/chat/ChatMessageBubble.tsx
5430
- var import_react_native41 = require("react-native");
5511
+ var import_react_native42 = require("react-native");
5431
5512
  var import_lucide_react_native10 = require("lucide-react-native");
5432
5513
  var import_jsx_runtime44 = require("react/jsx-runtime");
5433
5514
  function ChatMessageBubble({ message, renderContent, style }) {
@@ -5443,7 +5524,7 @@ function ChatMessageBubble({ message, renderContent, style }) {
5443
5524
  const bubbleVariant = isHuman ? "surface" : "surfaceRaised";
5444
5525
  const cornerStyle = isHuman ? { borderTopRightRadius: 0 } : { borderTopLeftRadius: 0 };
5445
5526
  const bodyColor = metaStatus === "success" ? theme.colors.success : metaStatus === "error" ? theme.colors.danger : void 0;
5446
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native41.View, { style: [align, style], children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
5527
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native42.View, { style: [align, style], children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
5447
5528
  Surface,
5448
5529
  {
5449
5530
  variant: bubbleVariant,
@@ -5458,34 +5539,34 @@ function ChatMessageBubble({ message, renderContent, style }) {
5458
5539
  },
5459
5540
  cornerStyle
5460
5541
  ],
5461
- children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_react_native41.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
5542
+ children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_react_native42.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
5462
5543
  isMergeCompleted ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react_native10.CheckCheck, { size: 16, color: theme.colors.success, style: { marginRight: theme.spacing.sm } }) : null,
5463
5544
  isMergeApproved ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react_native10.GitMerge, { size: 16, color: theme.colors.text, style: { marginRight: theme.spacing.sm } }) : null,
5464
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native41.View, { style: { flexShrink: 1, minWidth: 0 }, children: renderContent ? renderContent(message) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(MarkdownText, { markdown: message.content, variant: "chat", bodyColor }) })
5545
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native42.View, { style: { flexShrink: 1, minWidth: 0 }, children: renderContent ? renderContent(message) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(MarkdownText, { markdown: message.content, variant: "chat", bodyColor }) })
5465
5546
  ] })
5466
5547
  }
5467
5548
  ) });
5468
5549
  }
5469
5550
 
5470
5551
  // src/components/chat/TypingIndicator.tsx
5471
- var React31 = __toESM(require("react"));
5472
- var import_react_native42 = require("react-native");
5552
+ var React32 = __toESM(require("react"));
5553
+ var import_react_native43 = require("react-native");
5473
5554
  var import_jsx_runtime45 = require("react/jsx-runtime");
5474
5555
  function TypingIndicator({ style }) {
5475
5556
  const theme = useTheme();
5476
5557
  const dotColor = theme.colors.textSubtle;
5477
- const anims = React31.useMemo(
5478
- () => [new import_react_native42.Animated.Value(0.3), new import_react_native42.Animated.Value(0.3), new import_react_native42.Animated.Value(0.3)],
5558
+ const anims = React32.useMemo(
5559
+ () => [new import_react_native43.Animated.Value(0.3), new import_react_native43.Animated.Value(0.3), new import_react_native43.Animated.Value(0.3)],
5479
5560
  []
5480
5561
  );
5481
- React31.useEffect(() => {
5562
+ React32.useEffect(() => {
5482
5563
  const loops = [];
5483
5564
  anims.forEach((a, idx) => {
5484
- const seq = import_react_native42.Animated.sequence([
5485
- import_react_native42.Animated.timing(a, { toValue: 1, duration: 420, useNativeDriver: true, delay: idx * 140 }),
5486
- import_react_native42.Animated.timing(a, { toValue: 0.3, duration: 420, useNativeDriver: true })
5565
+ const seq = import_react_native43.Animated.sequence([
5566
+ import_react_native43.Animated.timing(a, { toValue: 1, duration: 420, useNativeDriver: true, delay: idx * 140 }),
5567
+ import_react_native43.Animated.timing(a, { toValue: 0.3, duration: 420, useNativeDriver: true })
5487
5568
  ]);
5488
- const loop = import_react_native42.Animated.loop(seq);
5569
+ const loop = import_react_native43.Animated.loop(seq);
5489
5570
  loops.push(loop);
5490
5571
  loop.start();
5491
5572
  });
@@ -5493,8 +5574,8 @@ function TypingIndicator({ style }) {
5493
5574
  loops.forEach((l) => l.stop());
5494
5575
  };
5495
5576
  }, [anims]);
5496
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_react_native42.View, { style: [{ flexDirection: "row", alignItems: "center" }, style], children: anims.map((a, i) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
5497
- import_react_native42.Animated.View,
5577
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_react_native43.View, { style: [{ flexDirection: "row", alignItems: "center" }, style], children: anims.map((a, i) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
5578
+ import_react_native43.Animated.View,
5498
5579
  {
5499
5580
  style: {
5500
5581
  width: 8,
@@ -5503,7 +5584,7 @@ function TypingIndicator({ style }) {
5503
5584
  marginHorizontal: 3,
5504
5585
  backgroundColor: dotColor,
5505
5586
  opacity: a,
5506
- transform: [{ translateY: import_react_native42.Animated.multiply(import_react_native42.Animated.subtract(a, 0.3), 2) }]
5587
+ transform: [{ translateY: import_react_native43.Animated.multiply(import_react_native43.Animated.subtract(a, 0.3), 2) }]
5507
5588
  }
5508
5589
  },
5509
5590
  i
@@ -5512,39 +5593,43 @@ function TypingIndicator({ style }) {
5512
5593
 
5513
5594
  // src/components/chat/ChatMessageList.tsx
5514
5595
  var import_jsx_runtime46 = require("react/jsx-runtime");
5515
- var ChatMessageList = React32.forwardRef(
5596
+ var ChatMessageList = React33.forwardRef(
5516
5597
  ({
5517
5598
  messages,
5518
5599
  showTypingIndicator = false,
5519
5600
  renderMessageContent,
5520
5601
  contentStyle,
5602
+ bottomInset = 0,
5521
5603
  onNearBottomChange,
5522
5604
  nearBottomThreshold = 200
5523
5605
  }, ref) => {
5524
5606
  const theme = useTheme();
5525
- const listRef = React32.useRef(null);
5526
- const nearBottomRef = React32.useRef(true);
5527
- const initialScrollDoneRef = React32.useRef(false);
5528
- const lastMessageIdRef = React32.useRef(null);
5529
- const scrollToBottom = React32.useCallback((options) => {
5607
+ const listRef = React33.useRef(null);
5608
+ const nearBottomRef = React33.useRef(true);
5609
+ const initialScrollDoneRef = React33.useRef(false);
5610
+ const lastMessageIdRef = React33.useRef(null);
5611
+ const scrollToBottom = React33.useCallback((options) => {
5530
5612
  var _a;
5531
5613
  const animated = (options == null ? void 0 : options.animated) ?? true;
5532
5614
  (_a = listRef.current) == null ? void 0 : _a.scrollToEnd({ animated });
5533
5615
  }, []);
5534
- React32.useImperativeHandle(ref, () => ({ scrollToBottom }), [scrollToBottom]);
5535
- const handleScroll = React32.useCallback(
5616
+ React33.useImperativeHandle(ref, () => ({ scrollToBottom }), [scrollToBottom]);
5617
+ const handleScroll = React33.useCallback(
5536
5618
  (e) => {
5537
5619
  const { contentOffset, contentSize, layoutMeasurement } = e.nativeEvent;
5538
- const distanceFromBottom = Math.max(contentSize.height - (contentOffset.y + layoutMeasurement.height), 0);
5620
+ const distanceFromBottom = Math.max(
5621
+ contentSize.height - Math.max(bottomInset, 0) - (contentOffset.y + layoutMeasurement.height),
5622
+ 0
5623
+ );
5539
5624
  const isNear = distanceFromBottom <= nearBottomThreshold;
5540
5625
  if (nearBottomRef.current !== isNear) {
5541
5626
  nearBottomRef.current = isNear;
5542
5627
  onNearBottomChange == null ? void 0 : onNearBottomChange(isNear);
5543
5628
  }
5544
5629
  },
5545
- [nearBottomThreshold, onNearBottomChange]
5630
+ [bottomInset, nearBottomThreshold, onNearBottomChange]
5546
5631
  );
5547
- React32.useEffect(() => {
5632
+ React33.useEffect(() => {
5548
5633
  var _a;
5549
5634
  if (initialScrollDoneRef.current) return;
5550
5635
  if (messages.length === 0) return;
@@ -5553,7 +5638,7 @@ var ChatMessageList = React32.forwardRef(
5553
5638
  const id = requestAnimationFrame(() => scrollToBottom({ animated: false }));
5554
5639
  return () => cancelAnimationFrame(id);
5555
5640
  }, [messages, scrollToBottom]);
5556
- React32.useEffect(() => {
5641
+ React33.useEffect(() => {
5557
5642
  if (!initialScrollDoneRef.current) return;
5558
5643
  const lastId = messages.length > 0 ? messages[messages.length - 1].id : null;
5559
5644
  const prevLastId = lastMessageIdRef.current;
@@ -5563,13 +5648,19 @@ var ChatMessageList = React32.forwardRef(
5563
5648
  const id = requestAnimationFrame(() => scrollToBottom({ animated: true }));
5564
5649
  return () => cancelAnimationFrame(id);
5565
5650
  }, [messages, scrollToBottom]);
5566
- React32.useEffect(() => {
5651
+ React33.useEffect(() => {
5567
5652
  if (showTypingIndicator && nearBottomRef.current) {
5568
5653
  const id = requestAnimationFrame(() => scrollToBottom({ animated: true }));
5569
5654
  return () => cancelAnimationFrame(id);
5570
5655
  }
5571
5656
  return void 0;
5572
5657
  }, [showTypingIndicator, scrollToBottom]);
5658
+ React33.useEffect(() => {
5659
+ if (!initialScrollDoneRef.current) return;
5660
+ if (!nearBottomRef.current) return;
5661
+ const id = requestAnimationFrame(() => scrollToBottom({ animated: false }));
5662
+ return () => cancelAnimationFrame(id);
5663
+ }, [bottomInset, scrollToBottom]);
5573
5664
  return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
5574
5665
  import_bottom_sheet5.BottomSheetFlatList,
5575
5666
  {
@@ -5583,13 +5674,15 @@ var ChatMessageList = React32.forwardRef(
5583
5674
  {
5584
5675
  paddingHorizontal: theme.spacing.lg,
5585
5676
  paddingTop: theme.spacing.sm,
5586
- paddingBottom: theme.spacing.xl
5677
+ paddingBottom: theme.spacing.sm
5587
5678
  },
5588
5679
  contentStyle
5589
5680
  ],
5590
- renderItem: ({ item, index }) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_react_native43.View, { style: { marginTop: index === 0 ? 0 : theme.spacing.sm }, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ChatMessageBubble, { message: item, renderContent: renderMessageContent }) }),
5591
- ListFooterComponent: showTypingIndicator ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_react_native43.View, { style: { marginTop: theme.spacing.sm, alignSelf: "flex-start", paddingHorizontal: theme.spacing.lg }, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(TypingIndicator, {}) }) : null,
5592
- maintainVisibleContentPosition: { minIndexForVisible: 0, autoscrollToTopThreshold: nearBottomThreshold }
5681
+ renderItem: ({ item, index }) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_react_native44.View, { style: { marginTop: index === 0 ? 0 : theme.spacing.sm }, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ChatMessageBubble, { message: item, renderContent: renderMessageContent }) }),
5682
+ ListFooterComponent: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_react_native44.View, { children: [
5683
+ showTypingIndicator ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_react_native44.View, { style: { marginTop: theme.spacing.sm, alignSelf: "flex-start", paddingHorizontal: theme.spacing.lg }, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(TypingIndicator, {}) }) : null,
5684
+ bottomInset > 0 ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_react_native44.View, { style: { height: bottomInset } }) : null
5685
+ ] })
5593
5686
  }
5594
5687
  );
5595
5688
  }
@@ -5612,37 +5705,38 @@ function ChatPage({
5612
5705
  }) {
5613
5706
  const theme = useTheme();
5614
5707
  const insets = (0, import_react_native_safe_area_context4.useSafeAreaInsets)();
5615
- const [composerHeight, setComposerHeight] = React33.useState(0);
5616
- const [keyboardVisible, setKeyboardVisible] = React33.useState(false);
5708
+ const [composerHeight, setComposerHeight] = React34.useState(0);
5709
+ const [keyboardVisible, setKeyboardVisible] = React34.useState(false);
5617
5710
  const animatedKeyboard = (0, import_react_native_reanimated2.useAnimatedKeyboard)();
5618
- React33.useEffect(() => {
5619
- if (import_react_native44.Platform.OS !== "ios") return;
5620
- const show = import_react_native44.Keyboard.addListener("keyboardWillShow", () => setKeyboardVisible(true));
5621
- const hide = import_react_native44.Keyboard.addListener("keyboardWillHide", () => setKeyboardVisible(false));
5711
+ React34.useEffect(() => {
5712
+ if (import_react_native45.Platform.OS !== "ios") return;
5713
+ const show = import_react_native45.Keyboard.addListener("keyboardWillShow", () => setKeyboardVisible(true));
5714
+ const hide = import_react_native45.Keyboard.addListener("keyboardWillHide", () => setKeyboardVisible(false));
5622
5715
  return () => {
5623
5716
  show.remove();
5624
5717
  hide.remove();
5625
5718
  };
5626
5719
  }, []);
5627
- const footerBottomPadding = import_react_native44.Platform.OS === "ios" ? keyboardVisible ? 0 : insets.bottom : insets.bottom + 10;
5720
+ const footerBottomPadding = import_react_native45.Platform.OS === "ios" ? keyboardVisible ? 0 : insets.bottom : insets.bottom + 10;
5628
5721
  const footerAnimatedStyle = (0, import_react_native_reanimated2.useAnimatedStyle)(() => {
5629
- if (import_react_native44.Platform.OS !== "ios") return { paddingBottom: insets.bottom + 10 };
5722
+ if (import_react_native45.Platform.OS !== "ios") return { paddingBottom: insets.bottom + 10 };
5630
5723
  return { paddingBottom: animatedKeyboard.height.value > 0 ? 0 : insets.bottom };
5631
5724
  });
5632
5725
  const overlayBottom = composerHeight + footerBottomPadding + theme.spacing.lg;
5633
- const resolvedOverlay = React33.useMemo(() => {
5726
+ const bottomInset = composerHeight + footerBottomPadding + theme.spacing.xl;
5727
+ const resolvedOverlay = React34.useMemo(() => {
5634
5728
  var _a;
5635
5729
  if (!overlay) return null;
5636
- if (!React33.isValidElement(overlay)) return overlay;
5730
+ if (!React34.isValidElement(overlay)) return overlay;
5637
5731
  const prevStyle = (_a = overlay.props) == null ? void 0 : _a.style;
5638
- return React33.cloneElement(overlay, {
5732
+ return React34.cloneElement(overlay, {
5639
5733
  style: [prevStyle, { bottom: overlayBottom }]
5640
5734
  });
5641
5735
  }, [overlay, overlayBottom]);
5642
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native44.View, { style: [{ flex: 1 }, style], children: [
5643
- header ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native44.View, { children: header }) : null,
5644
- topBanner ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native44.View, { style: { paddingHorizontal: theme.spacing.lg, paddingTop: theme.spacing.sm }, children: topBanner }) : null,
5645
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native44.View, { style: { flex: 1 }, children: [
5736
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native45.View, { style: [{ flex: 1 }, style], children: [
5737
+ header ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native45.View, { children: header }) : null,
5738
+ topBanner ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native45.View, { style: { paddingHorizontal: theme.spacing.lg, paddingTop: theme.spacing.sm }, children: topBanner }) : null,
5739
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native45.View, { style: { flex: 1 }, children: [
5646
5740
  /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
5647
5741
  ChatMessageList,
5648
5742
  {
@@ -5651,7 +5745,7 @@ function ChatPage({
5651
5745
  showTypingIndicator,
5652
5746
  renderMessageContent,
5653
5747
  onNearBottomChange,
5654
- contentStyle: { paddingBottom: theme.spacing.xl + composerHeight + footerBottomPadding }
5748
+ bottomInset
5655
5749
  }
5656
5750
  ),
5657
5751
  resolvedOverlay,
@@ -5684,15 +5778,15 @@ function ChatPage({
5684
5778
  }
5685
5779
 
5686
5780
  // src/components/chat/ScrollToBottomButton.tsx
5687
- var React34 = __toESM(require("react"));
5688
- var import_react_native45 = require("react-native");
5781
+ var React35 = __toESM(require("react"));
5782
+ var import_react_native46 = require("react-native");
5689
5783
  var import_react_native_reanimated3 = __toESM(require("react-native-reanimated"));
5690
5784
  var import_jsx_runtime48 = require("react/jsx-runtime");
5691
5785
  function ScrollToBottomButton({ visible, onPress, children, style }) {
5692
5786
  const theme = useTheme();
5693
5787
  const progress = (0, import_react_native_reanimated3.useSharedValue)(visible ? 1 : 0);
5694
- const [pressed, setPressed] = React34.useState(false);
5695
- React34.useEffect(() => {
5788
+ const [pressed, setPressed] = React35.useState(false);
5789
+ React35.useEffect(() => {
5696
5790
  progress.value = (0, import_react_native_reanimated3.withTiming)(visible ? 1 : 0, { duration: 200, easing: import_react_native_reanimated3.Easing.out(import_react_native_reanimated3.Easing.ease) });
5697
5791
  }, [progress, visible]);
5698
5792
  const animStyle = (0, import_react_native_reanimated3.useAnimatedStyle)(() => ({
@@ -5716,7 +5810,7 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
5716
5810
  animStyle
5717
5811
  ],
5718
5812
  children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
5719
- import_react_native45.View,
5813
+ import_react_native46.View,
5720
5814
  {
5721
5815
  style: {
5722
5816
  width: 44,
@@ -5735,7 +5829,7 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
5735
5829
  opacity: pressed ? 0.85 : 1
5736
5830
  },
5737
5831
  children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
5738
- import_react_native45.Pressable,
5832
+ import_react_native46.Pressable,
5739
5833
  {
5740
5834
  onPress,
5741
5835
  onPressIn: () => setPressed(true),
@@ -5752,10 +5846,10 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
5752
5846
  }
5753
5847
 
5754
5848
  // src/components/chat/ChatHeader.tsx
5755
- var import_react_native46 = require("react-native");
5849
+ var import_react_native47 = require("react-native");
5756
5850
  var import_jsx_runtime49 = require("react/jsx-runtime");
5757
5851
  function ChatHeader({ left, right, center, style }) {
5758
- const flattenedStyle = import_react_native46.StyleSheet.flatten([
5852
+ const flattenedStyle = import_react_native47.StyleSheet.flatten([
5759
5853
  {
5760
5854
  paddingTop: 0
5761
5855
  },
@@ -5773,7 +5867,7 @@ function ChatHeader({ left, right, center, style }) {
5773
5867
  }
5774
5868
 
5775
5869
  // src/components/chat/ForkNoticeBanner.tsx
5776
- var import_react_native47 = require("react-native");
5870
+ var import_react_native48 = require("react-native");
5777
5871
  var import_jsx_runtime50 = require("react/jsx-runtime");
5778
5872
  function ForkNoticeBanner({ isOwner = true, title, description, style }) {
5779
5873
  const theme = useTheme();
@@ -5794,7 +5888,7 @@ function ForkNoticeBanner({ isOwner = true, title, description, style }) {
5794
5888
  },
5795
5889
  style
5796
5890
  ],
5797
- children: /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_react_native47.View, { style: { minWidth: 0 }, children: [
5891
+ children: /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_react_native48.View, { style: { minWidth: 0 }, children: [
5798
5892
  /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
5799
5893
  Text,
5800
5894
  {
@@ -5847,32 +5941,34 @@ function ChatPanel({
5847
5941
  onStartDraw,
5848
5942
  onSend
5849
5943
  }) {
5850
- const listRef = React35.useRef(null);
5851
- const [nearBottom, setNearBottom] = React35.useState(true);
5852
- const handleSend = React35.useCallback(
5944
+ const listRef = React36.useRef(null);
5945
+ const [nearBottom, setNearBottom] = React36.useState(true);
5946
+ const handleSend = React36.useCallback(
5853
5947
  async (text, composerAttachments) => {
5854
5948
  const all = composerAttachments ?? attachments;
5855
5949
  await onSend(text, all.length > 0 ? all : void 0);
5856
5950
  onClearAttachments == null ? void 0 : onClearAttachments();
5857
- requestAnimationFrame(() => {
5858
- var _a;
5859
- return (_a = listRef.current) == null ? void 0 : _a.scrollToBottom({ animated: true });
5860
- });
5951
+ if (!nearBottom) {
5952
+ requestAnimationFrame(() => {
5953
+ var _a;
5954
+ return (_a = listRef.current) == null ? void 0 : _a.scrollToBottom({ animated: true });
5955
+ });
5956
+ }
5861
5957
  },
5862
- [attachments, onClearAttachments, onSend]
5958
+ [attachments, nearBottom, onClearAttachments, onSend]
5863
5959
  );
5864
- const handleScrollToBottom = React35.useCallback(() => {
5960
+ const handleScrollToBottom = React36.useCallback(() => {
5865
5961
  var _a;
5866
5962
  (_a = listRef.current) == null ? void 0 : _a.scrollToBottom({ animated: true });
5867
5963
  }, []);
5868
5964
  const header = /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
5869
5965
  ChatHeader,
5870
5966
  {
5871
- left: /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_react_native48.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
5967
+ left: /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_react_native49.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
5872
5968
  /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(StudioSheetHeaderIconButton, { onPress: onBack, accessibilityLabel: "Back", style: { marginRight: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(IconBack, { size: 20, colorToken: "floatingContent" }) }),
5873
5969
  onNavigateHome ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(StudioSheetHeaderIconButton, { onPress: onNavigateHome, accessibilityLabel: "Home", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(IconHome, { size: 20, colorToken: "floatingContent" }) }) : null
5874
5970
  ] }),
5875
- right: /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_react_native48.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
5971
+ right: /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_react_native49.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
5876
5972
  onStartDraw ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(StudioSheetHeaderIconButton, { onPress: onStartDraw, accessibilityLabel: "Draw", intent: "danger", style: { marginRight: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(IconDraw, { size: 20, colorToken: "onDanger" }) }) : null,
5877
5973
  /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(StudioSheetHeaderIconButton, { onPress: onClose, accessibilityLabel: "Close", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(IconClose, { size: 20, colorToken: "floatingContent" }) })
5878
5974
  ] }),
@@ -5888,12 +5984,12 @@ function ChatPanel({
5888
5984
  ) : null;
5889
5985
  const showMessagesLoading = Boolean(loading) && messages.length === 0 || forking;
5890
5986
  if (showMessagesLoading) {
5891
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_react_native48.View, { style: { flex: 1 }, children: [
5892
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native48.View, { children: header }),
5893
- topBanner ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native48.View, { style: { paddingHorizontal: 16, paddingTop: 8 }, children: topBanner }) : null,
5894
- /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_react_native48.View, { style: { flex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 24, paddingVertical: 12 }, children: [
5895
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native48.ActivityIndicator, {}),
5896
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native48.View, { style: { height: 12 } }),
5987
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_react_native49.View, { style: { flex: 1 }, children: [
5988
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native49.View, { children: header }),
5989
+ topBanner ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native49.View, { style: { paddingHorizontal: 16, paddingTop: 8 }, children: topBanner }) : null,
5990
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_react_native49.View, { style: { flex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 24, paddingVertical: 12 }, children: [
5991
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native49.ActivityIndicator, {}),
5992
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native49.View, { style: { height: 12 } }),
5897
5993
  /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Text, { variant: "bodyMuted", children: forking ? "Creating your copy\u2026" : "Loading messages\u2026" })
5898
5994
  ] })
5899
5995
  ] });
@@ -5917,7 +6013,10 @@ function ChatPanel({
5917
6013
  }
5918
6014
  ),
5919
6015
  composer: {
5920
- disabled: Boolean(loading) || Boolean(sendDisabled) || Boolean(forking),
6016
+ // Keep the input editable even when sending is disallowed (e.g. agent still working),
6017
+ // otherwise iOS will drop focus/keyboard and BottomSheet can get "stuck" with a keyboard-sized gap.
6018
+ disabled: Boolean(loading) || Boolean(forking),
6019
+ sendDisabled: Boolean(sendDisabled) || Boolean(loading) || Boolean(forking),
5921
6020
  sending: Boolean(sending),
5922
6021
  autoFocus: autoFocusComposer,
5923
6022
  onSend: handleSend,
@@ -5931,11 +6030,11 @@ function ChatPanel({
5931
6030
  }
5932
6031
 
5933
6032
  // src/components/dialogs/ConfirmMergeRequestDialog.tsx
5934
- var React36 = __toESM(require("react"));
5935
- var import_react_native50 = require("react-native");
6033
+ var React37 = __toESM(require("react"));
6034
+ var import_react_native51 = require("react-native");
5936
6035
 
5937
6036
  // src/components/primitives/Modal.tsx
5938
- var import_react_native49 = require("react-native");
6037
+ var import_react_native50 = require("react-native");
5939
6038
  var import_jsx_runtime52 = require("react/jsx-runtime");
5940
6039
  function Modal({
5941
6040
  visible,
@@ -5946,15 +6045,15 @@ function Modal({
5946
6045
  }) {
5947
6046
  const theme = useTheme();
5948
6047
  return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
5949
- import_react_native49.Modal,
6048
+ import_react_native50.Modal,
5950
6049
  {
5951
6050
  visible,
5952
6051
  transparent: true,
5953
6052
  animationType: "fade",
5954
6053
  onRequestClose,
5955
- children: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_react_native49.View, { style: { flex: 1, backgroundColor: theme.colors.backdrop, justifyContent: "center", padding: theme.spacing.lg }, children: [
6054
+ children: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_react_native50.View, { style: { flex: 1, backgroundColor: theme.colors.backdrop, justifyContent: "center", padding: theme.spacing.lg }, children: [
5956
6055
  /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
5957
- import_react_native49.Pressable,
6056
+ import_react_native50.Pressable,
5958
6057
  {
5959
6058
  accessibilityRole: "button",
5960
6059
  onPress: dismissOnBackdropPress ? onRequestClose : void 0,
@@ -5979,14 +6078,14 @@ function ConfirmMergeRequestDialog({
5979
6078
  onTestFirst
5980
6079
  }) {
5981
6080
  const theme = useTheme();
5982
- const close = React36.useCallback(() => onOpenChange(false), [onOpenChange]);
6081
+ const close = React37.useCallback(() => onOpenChange(false), [onOpenChange]);
5983
6082
  const canConfirm = Boolean(mergeRequest) && !approveDisabled;
5984
- const handleConfirm = React36.useCallback(() => {
6083
+ const handleConfirm = React37.useCallback(() => {
5985
6084
  if (!mergeRequest) return;
5986
6085
  onOpenChange(false);
5987
6086
  void onConfirm();
5988
6087
  }, [mergeRequest, onConfirm, onOpenChange]);
5989
- const handleTestFirst = React36.useCallback(() => {
6088
+ const handleTestFirst = React37.useCallback(() => {
5990
6089
  if (!mergeRequest) return;
5991
6090
  onOpenChange(false);
5992
6091
  void onTestFirst(mergeRequest);
@@ -6009,7 +6108,7 @@ function ConfirmMergeRequestDialog({
6009
6108
  backgroundColor: theme.colors.background
6010
6109
  },
6011
6110
  children: [
6012
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_react_native50.View, { children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
6111
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_react_native51.View, { children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
6013
6112
  Text,
6014
6113
  {
6015
6114
  style: {
@@ -6021,9 +6120,9 @@ function ConfirmMergeRequestDialog({
6021
6120
  children: "Are you sure you want to approve this merge request?"
6022
6121
  }
6023
6122
  ) }),
6024
- /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_react_native50.View, { style: { marginTop: 16 }, children: [
6123
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_react_native51.View, { style: { marginTop: 16 }, children: [
6025
6124
  /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
6026
- import_react_native50.View,
6125
+ import_react_native51.View,
6027
6126
  {
6028
6127
  style: [
6029
6128
  fullWidthButtonBase,
@@ -6033,7 +6132,7 @@ function ConfirmMergeRequestDialog({
6033
6132
  }
6034
6133
  ],
6035
6134
  children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
6036
- import_react_native50.Pressable,
6135
+ import_react_native51.Pressable,
6037
6136
  {
6038
6137
  accessibilityRole: "button",
6039
6138
  accessibilityLabel: "Approve Merge",
@@ -6045,9 +6144,9 @@ function ConfirmMergeRequestDialog({
6045
6144
  )
6046
6145
  }
6047
6146
  ),
6048
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_react_native50.View, { style: { height: 8 } }),
6147
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_react_native51.View, { style: { height: 8 } }),
6049
6148
  /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
6050
- import_react_native50.View,
6149
+ import_react_native51.View,
6051
6150
  {
6052
6151
  style: [
6053
6152
  fullWidthButtonBase,
@@ -6059,7 +6158,7 @@ function ConfirmMergeRequestDialog({
6059
6158
  }
6060
6159
  ],
6061
6160
  children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
6062
- import_react_native50.Pressable,
6161
+ import_react_native51.Pressable,
6063
6162
  {
6064
6163
  accessibilityRole: "button",
6065
6164
  accessibilityLabel: isBuilding ? "Preparing\u2026" : "Test edits first",
@@ -6071,9 +6170,9 @@ function ConfirmMergeRequestDialog({
6071
6170
  )
6072
6171
  }
6073
6172
  ),
6074
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_react_native50.View, { style: { height: 8 } }),
6173
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_react_native51.View, { style: { height: 8 } }),
6075
6174
  /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
6076
- import_react_native50.View,
6175
+ import_react_native51.View,
6077
6176
  {
6078
6177
  style: [
6079
6178
  fullWidthButtonBase,
@@ -6084,7 +6183,7 @@ function ConfirmMergeRequestDialog({
6084
6183
  }
6085
6184
  ],
6086
6185
  children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
6087
- import_react_native50.Pressable,
6186
+ import_react_native51.Pressable,
6088
6187
  {
6089
6188
  accessibilityRole: "button",
6090
6189
  accessibilityLabel: "Cancel",
@@ -6165,30 +6264,30 @@ function StudioOverlay({
6165
6264
  onNavigateHome
6166
6265
  }) {
6167
6266
  const theme = useTheme();
6168
- const { width } = (0, import_react_native51.useWindowDimensions)();
6169
- const [sheetOpen, setSheetOpen] = React37.useState(false);
6170
- const [activePage, setActivePage] = React37.useState("preview");
6171
- const [drawing, setDrawing] = React37.useState(false);
6172
- const [chatAttachments, setChatAttachments] = React37.useState([]);
6173
- const [commentsAppId, setCommentsAppId] = React37.useState(null);
6174
- const [commentsCount, setCommentsCount] = React37.useState(null);
6175
- const [confirmMrId, setConfirmMrId] = React37.useState(null);
6176
- const confirmMr = React37.useMemo(
6267
+ const { width } = (0, import_react_native52.useWindowDimensions)();
6268
+ const [sheetOpen, setSheetOpen] = React38.useState(false);
6269
+ const [activePage, setActivePage] = React38.useState("preview");
6270
+ const [drawing, setDrawing] = React38.useState(false);
6271
+ const [chatAttachments, setChatAttachments] = React38.useState([]);
6272
+ const [commentsAppId, setCommentsAppId] = React38.useState(null);
6273
+ const [commentsCount, setCommentsCount] = React38.useState(null);
6274
+ const [confirmMrId, setConfirmMrId] = React38.useState(null);
6275
+ const confirmMr = React38.useMemo(
6177
6276
  () => confirmMrId ? incomingMergeRequests.find((m) => m.id === confirmMrId) ?? null : null,
6178
6277
  [confirmMrId, incomingMergeRequests]
6179
6278
  );
6180
- const closeSheet = React37.useCallback(() => {
6279
+ const closeSheet = React38.useCallback(() => {
6181
6280
  setSheetOpen(false);
6182
- import_react_native51.Keyboard.dismiss();
6281
+ import_react_native52.Keyboard.dismiss();
6183
6282
  }, []);
6184
- const openSheet = React37.useCallback(() => setSheetOpen(true), []);
6185
- const goToChat = React37.useCallback(() => {
6283
+ const openSheet = React38.useCallback(() => setSheetOpen(true), []);
6284
+ const goToChat = React38.useCallback(() => {
6186
6285
  setActivePage("chat");
6187
6286
  openSheet();
6188
6287
  }, [openSheet]);
6189
- const backToPreview = React37.useCallback(() => {
6190
- if (import_react_native51.Platform.OS !== "ios") {
6191
- import_react_native51.Keyboard.dismiss();
6288
+ const backToPreview = React38.useCallback(() => {
6289
+ if (import_react_native52.Platform.OS !== "ios") {
6290
+ import_react_native52.Keyboard.dismiss();
6192
6291
  setActivePage("preview");
6193
6292
  return;
6194
6293
  }
@@ -6200,15 +6299,15 @@ function StudioOverlay({
6200
6299
  clearTimeout(t);
6201
6300
  setActivePage("preview");
6202
6301
  };
6203
- const sub = import_react_native51.Keyboard.addListener("keyboardDidHide", finalize);
6302
+ const sub = import_react_native52.Keyboard.addListener("keyboardDidHide", finalize);
6204
6303
  const t = setTimeout(finalize, 350);
6205
- import_react_native51.Keyboard.dismiss();
6304
+ import_react_native52.Keyboard.dismiss();
6206
6305
  }, []);
6207
- const startDraw = React37.useCallback(() => {
6306
+ const startDraw = React38.useCallback(() => {
6208
6307
  setDrawing(true);
6209
6308
  closeSheet();
6210
6309
  }, [closeSheet]);
6211
- const handleDrawCapture = React37.useCallback(
6310
+ const handleDrawCapture = React38.useCallback(
6212
6311
  (dataUrl) => {
6213
6312
  setChatAttachments((prev) => [...prev, dataUrl]);
6214
6313
  setDrawing(false);
@@ -6217,7 +6316,7 @@ function StudioOverlay({
6217
6316
  },
6218
6317
  [openSheet]
6219
6318
  );
6220
- const toggleSheet = React37.useCallback(async () => {
6319
+ const toggleSheet = React38.useCallback(async () => {
6221
6320
  if (!sheetOpen) {
6222
6321
  const shouldExitTest = Boolean(testingMrId) || isTesting;
6223
6322
  if (shouldExitTest) {
@@ -6229,7 +6328,7 @@ function StudioOverlay({
6229
6328
  closeSheet();
6230
6329
  }
6231
6330
  }, [closeSheet, isTesting, onRestoreBase, sheetOpen, testingMrId]);
6232
- const handleTestMr = React37.useCallback(
6331
+ const handleTestMr = React38.useCallback(
6233
6332
  async (mr) => {
6234
6333
  if (!onTestMr) return;
6235
6334
  await onTestMr(mr);
@@ -6301,7 +6400,7 @@ function StudioOverlay({
6301
6400
  badgeCount: incomingMergeRequests.length,
6302
6401
  onPress: toggleSheet,
6303
6402
  isLoading: (app == null ? void 0 : app.status) === "editing",
6304
- children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_react_native51.View, { style: { width: 28, height: 28, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(MergeIcon, { width: 24, height: 24, color: theme.colors.floatingContent }) })
6403
+ children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_react_native52.View, { style: { width: 28, height: 28, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(MergeIcon, { width: 24, height: 24, color: theme.colors.floatingContent }) })
6305
6404
  }
6306
6405
  ),
6307
6406
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
@@ -6347,16 +6446,16 @@ function ComergeStudio({
6347
6446
  onNavigateHome,
6348
6447
  style
6349
6448
  }) {
6350
- const [activeAppId, setActiveAppId] = React38.useState(appId);
6351
- const [runtimeAppId, setRuntimeAppId] = React38.useState(appId);
6352
- const [pendingRuntimeTargetAppId, setPendingRuntimeTargetAppId] = React38.useState(null);
6353
- const platform = React38.useMemo(() => import_react_native52.Platform.OS === "ios" ? "ios" : "android", []);
6354
- React38.useEffect(() => {
6449
+ const [activeAppId, setActiveAppId] = React39.useState(appId);
6450
+ const [runtimeAppId, setRuntimeAppId] = React39.useState(appId);
6451
+ const [pendingRuntimeTargetAppId, setPendingRuntimeTargetAppId] = React39.useState(null);
6452
+ const platform = React39.useMemo(() => import_react_native53.Platform.OS === "ios" ? "ios" : "android", []);
6453
+ React39.useEffect(() => {
6355
6454
  setActiveAppId(appId);
6356
6455
  setRuntimeAppId(appId);
6357
6456
  setPendingRuntimeTargetAppId(null);
6358
6457
  }, [appId]);
6359
- const captureTargetRef = React38.useRef(null);
6458
+ const captureTargetRef = React39.useRef(null);
6360
6459
  return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(StudioBootstrap, { apiKey, children: ({ userId }) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_bottom_sheet6.BottomSheetModalProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
6361
6460
  ComergeStudioInner,
6362
6461
  {
@@ -6392,11 +6491,11 @@ function ComergeStudioInner({
6392
6491
  const { app, loading: appLoading } = useApp(activeAppId);
6393
6492
  const { app: runtimeAppFromHook } = useApp(runtimeAppId, { enabled: runtimeAppId !== activeAppId });
6394
6493
  const runtimeApp = runtimeAppId === activeAppId ? app : runtimeAppFromHook;
6395
- const sawEditingOnPendingTargetRef = React38.useRef(false);
6396
- React38.useEffect(() => {
6494
+ const sawEditingOnPendingTargetRef = React39.useRef(false);
6495
+ React39.useEffect(() => {
6397
6496
  sawEditingOnPendingTargetRef.current = false;
6398
6497
  }, [pendingRuntimeTargetAppId]);
6399
- React38.useEffect(() => {
6498
+ React39.useEffect(() => {
6400
6499
  if (!pendingRuntimeTargetAppId) return;
6401
6500
  if (activeAppId !== pendingRuntimeTargetAppId) return;
6402
6501
  if ((app == null ? void 0 : app.status) === "editing") {
@@ -6416,10 +6515,10 @@ function ComergeStudioInner({
6416
6515
  const threadId = (app == null ? void 0 : app.threadId) ?? "";
6417
6516
  const thread = useThreadMessages(threadId);
6418
6517
  const mergeRequests = useMergeRequests({ appId: activeAppId });
6419
- const hasOpenOutgoingMr = React38.useMemo(() => {
6518
+ const hasOpenOutgoingMr = React39.useMemo(() => {
6420
6519
  return mergeRequests.lists.outgoing.some((mr) => mr.status === "open");
6421
6520
  }, [mergeRequests.lists.outgoing]);
6422
- const incomingReviewMrs = React38.useMemo(() => {
6521
+ const incomingReviewMrs = React39.useMemo(() => {
6423
6522
  if (!userId) return mergeRequests.lists.incoming;
6424
6523
  return mergeRequests.lists.incoming.filter((mr) => mr.createdBy !== userId);
6425
6524
  }, [mergeRequests.lists.incoming, userId]);
@@ -6441,16 +6540,16 @@ function ComergeStudioInner({
6441
6540
  uploadAttachments: uploader.uploadBase64Images
6442
6541
  });
6443
6542
  const chatSendDisabled = hasNoOutcomeAfterLastHuman(thread.raw);
6444
- const [processingMrId, setProcessingMrId] = React38.useState(null);
6445
- const [testingMrId, setTestingMrId] = React38.useState(null);
6446
- const chatShowTypingIndicator = React38.useMemo(() => {
6543
+ const [processingMrId, setProcessingMrId] = React39.useState(null);
6544
+ const [testingMrId, setTestingMrId] = React39.useState(null);
6545
+ const chatShowTypingIndicator = React39.useMemo(() => {
6447
6546
  var _a;
6448
6547
  if (!thread.raw || thread.raw.length === 0) return false;
6449
6548
  const last = thread.raw[thread.raw.length - 1];
6450
6549
  const payloadType = typeof ((_a = last.payload) == null ? void 0 : _a.type) === "string" ? String(last.payload.type) : void 0;
6451
6550
  return payloadType !== "outcome";
6452
6551
  }, [thread.raw]);
6453
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_react_native52.View, { style: [{ flex: 1 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_react_native52.View, { ref: captureTargetRef, style: { flex: 1 }, collapsable: false, children: [
6552
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_react_native53.View, { style: [{ flex: 1 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_react_native53.View, { ref: captureTargetRef, style: { flex: 1 }, collapsable: false, children: [
6454
6553
  /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(RuntimeRenderer, { appKey, bundlePath: bundle.bundlePath, renderToken: bundle.renderToken }),
6455
6554
  /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
6456
6555
  StudioOverlay,