@comergehq/studio 0.1.17 → 0.1.18

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,7 +36,7 @@ __export(index_exports, {
36
36
  module.exports = __toCommonJS(index_exports);
37
37
 
38
38
  // src/studio/ComergeStudio.tsx
39
- var React46 = __toESM(require("react"));
39
+ var React47 = __toESM(require("react"));
40
40
  var import_react_native56 = require("react-native");
41
41
  var import_bottom_sheet6 = require("@gorhom/bottom-sheet");
42
42
 
@@ -2062,7 +2062,7 @@ function RuntimeRenderer({
2062
2062
  }
2063
2063
 
2064
2064
  // src/studio/ui/StudioOverlay.tsx
2065
- var React43 = __toESM(require("react"));
2065
+ var React44 = __toESM(require("react"));
2066
2066
  var import_react_native55 = require("react-native");
2067
2067
 
2068
2068
  // src/components/studio-sheet/StudioBottomSheet.tsx
@@ -3252,6 +3252,7 @@ var IconSend = makeIcon(import_lucide_react_native2.Send);
3252
3252
  var IconPlay = makeIcon(import_lucide_react_native2.Play);
3253
3253
  var IconArrowDown = makeIcon(import_lucide_react_native2.ArrowDown);
3254
3254
  var IconApprove = makeIcon(import_lucide_react_native2.Check);
3255
+ var IconShare = makeIcon(import_lucide_react_native2.Share2);
3255
3256
 
3256
3257
  // src/components/chat/ChatComposer.tsx
3257
3258
  var import_jsx_runtime17 = require("react/jsx-runtime");
@@ -3968,6 +3969,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
3968
3969
  }
3969
3970
 
3970
3971
  // src/studio/ui/PreviewPanel.tsx
3972
+ var React35 = __toESM(require("react"));
3971
3973
  var import_react_native43 = require("react-native");
3972
3974
 
3973
3975
  // src/components/preview/PreviewPage.tsx
@@ -4118,7 +4120,14 @@ function StudioSheetHeaderIconButton({
4118
4120
 
4119
4121
  // src/studio/ui/preview-panel/PreviewPanelHeader.tsx
4120
4122
  var import_jsx_runtime24 = require("react/jsx-runtime");
4121
- function PreviewPanelHeader({ isOwner, onClose, onNavigateHome, onGoToChat }) {
4123
+ function PreviewPanelHeader({
4124
+ isOwner,
4125
+ isPublic,
4126
+ onClose,
4127
+ onNavigateHome,
4128
+ onGoToChat,
4129
+ onShare
4130
+ }) {
4122
4131
  return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4123
4132
  StudioSheetHeader,
4124
4133
  {
@@ -4136,6 +4145,17 @@ function PreviewPanelHeader({ isOwner, onClose, onNavigateHome, onGoToChat }) {
4136
4145
  children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(IconChat, { size: 20, colorToken: "onPrimary" })
4137
4146
  }
4138
4147
  ) : null,
4148
+ isPublic && onShare ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4149
+ StudioSheetHeaderIconButton,
4150
+ {
4151
+ onPress: onShare,
4152
+ accessibilityLabel: "Share",
4153
+ intent: "primary",
4154
+ appearance: "glass",
4155
+ style: { marginRight: 8 },
4156
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(IconShare, { size: 20, colorToken: "onPrimary" })
4157
+ }
4158
+ ) : null,
4139
4159
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(StudioSheetHeaderIconButton, { onPress: onClose, accessibilityLabel: "Close", appearance: "glass", intent: "primary", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(IconClose, { size: 20, colorToken: "onPrimary" }) })
4140
4160
  ] })
4141
4161
  }
@@ -5800,6 +5820,27 @@ function PreviewPanel({
5800
5820
  onOpenComments,
5801
5821
  commentCountOverride
5802
5822
  }) {
5823
+ const handleShare = React35.useCallback(async () => {
5824
+ if (!app || !app.isPublic) return;
5825
+ const shareUrl = `https://comerge.ai/app/${app.id}`;
5826
+ const message = app.name ? `${app.name} on Comerge
5827
+ ${shareUrl}` : `Check out this app on Comerge
5828
+ ${shareUrl}`;
5829
+ try {
5830
+ const title = app.name ?? "Comerge app";
5831
+ const payload = import_react_native43.Platform.OS === "ios" ? {
5832
+ title,
5833
+ message
5834
+ } : {
5835
+ title,
5836
+ message,
5837
+ url: shareUrl
5838
+ };
5839
+ await import_react_native43.Share.share(payload);
5840
+ } catch (error) {
5841
+ log.warn("PreviewPanel share failed", error);
5842
+ }
5843
+ }, [app]);
5803
5844
  const { imageUrl, imageLoaded, setImageLoaded, creator, insights, stats, showProcessing, canSubmitMergeRequest } = usePreviewPanelData({
5804
5845
  app,
5805
5846
  isOwner,
@@ -5807,7 +5848,17 @@ function PreviewPanel({
5807
5848
  onOpenComments,
5808
5849
  commentCountOverride
5809
5850
  });
5810
- const header = /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(PreviewPanelHeader, { isOwner, onClose, onNavigateHome, onGoToChat });
5851
+ const header = /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
5852
+ PreviewPanelHeader,
5853
+ {
5854
+ isOwner,
5855
+ isPublic: Boolean(app == null ? void 0 : app.isPublic),
5856
+ onClose,
5857
+ onNavigateHome,
5858
+ onGoToChat,
5859
+ onShare: handleShare
5860
+ }
5861
+ );
5811
5862
  if (loading || !app) {
5812
5863
  return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(PreviewPage, { header, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_react_native43.View, { style: { flex: 1, justifyContent: "center", alignItems: "center", padding: 24 }, children: [
5813
5864
  /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_react_native43.ActivityIndicator, {}),
@@ -5867,16 +5918,16 @@ function PreviewPanel({
5867
5918
  }
5868
5919
 
5869
5920
  // src/studio/ui/ChatPanel.tsx
5870
- var React40 = __toESM(require("react"));
5921
+ var React41 = __toESM(require("react"));
5871
5922
  var import_react_native52 = require("react-native");
5872
5923
 
5873
5924
  // src/components/chat/ChatPage.tsx
5874
- var React37 = __toESM(require("react"));
5925
+ var React38 = __toESM(require("react"));
5875
5926
  var import_react_native47 = require("react-native");
5876
5927
  var import_react_native_safe_area_context4 = require("react-native-safe-area-context");
5877
5928
 
5878
5929
  // src/components/chat/ChatMessageList.tsx
5879
- var React36 = __toESM(require("react"));
5930
+ var React37 = __toESM(require("react"));
5880
5931
  var import_react_native46 = require("react-native");
5881
5932
  var import_bottom_sheet5 = require("@gorhom/bottom-sheet");
5882
5933
 
@@ -5922,17 +5973,17 @@ function ChatMessageBubble({ message, renderContent, style }) {
5922
5973
  }
5923
5974
 
5924
5975
  // src/components/chat/TypingIndicator.tsx
5925
- var React35 = __toESM(require("react"));
5976
+ var React36 = __toESM(require("react"));
5926
5977
  var import_react_native45 = require("react-native");
5927
5978
  var import_jsx_runtime47 = require("react/jsx-runtime");
5928
5979
  function TypingIndicator({ style }) {
5929
5980
  const theme = useTheme();
5930
5981
  const dotColor = theme.colors.textSubtle;
5931
- const anims = React35.useMemo(
5982
+ const anims = React36.useMemo(
5932
5983
  () => [new import_react_native45.Animated.Value(0.3), new import_react_native45.Animated.Value(0.3), new import_react_native45.Animated.Value(0.3)],
5933
5984
  []
5934
5985
  );
5935
- React35.useEffect(() => {
5986
+ React36.useEffect(() => {
5936
5987
  const loops = [];
5937
5988
  anims.forEach((a, idx) => {
5938
5989
  const seq = import_react_native45.Animated.sequence([
@@ -5966,7 +6017,7 @@ function TypingIndicator({ style }) {
5966
6017
 
5967
6018
  // src/components/chat/ChatMessageList.tsx
5968
6019
  var import_jsx_runtime48 = require("react/jsx-runtime");
5969
- var ChatMessageList = React36.forwardRef(
6020
+ var ChatMessageList = React37.forwardRef(
5970
6021
  ({
5971
6022
  messages,
5972
6023
  showTypingIndicator = false,
@@ -5977,20 +6028,20 @@ var ChatMessageList = React36.forwardRef(
5977
6028
  nearBottomThreshold = 200
5978
6029
  }, ref) => {
5979
6030
  const theme = useTheme();
5980
- const listRef = React36.useRef(null);
5981
- const nearBottomRef = React36.useRef(true);
5982
- const initialScrollDoneRef = React36.useRef(false);
5983
- const lastMessageIdRef = React36.useRef(null);
5984
- const data = React36.useMemo(() => {
6031
+ const listRef = React37.useRef(null);
6032
+ const nearBottomRef = React37.useRef(true);
6033
+ const initialScrollDoneRef = React37.useRef(false);
6034
+ const lastMessageIdRef = React37.useRef(null);
6035
+ const data = React37.useMemo(() => {
5985
6036
  return [...messages].reverse();
5986
6037
  }, [messages]);
5987
- const scrollToBottom = React36.useCallback((options) => {
6038
+ const scrollToBottom = React37.useCallback((options) => {
5988
6039
  var _a;
5989
6040
  const animated = (options == null ? void 0 : options.animated) ?? true;
5990
6041
  (_a = listRef.current) == null ? void 0 : _a.scrollToOffset({ offset: 0, animated });
5991
6042
  }, []);
5992
- React36.useImperativeHandle(ref, () => ({ scrollToBottom }), [scrollToBottom]);
5993
- const handleScroll = React36.useCallback(
6043
+ React37.useImperativeHandle(ref, () => ({ scrollToBottom }), [scrollToBottom]);
6044
+ const handleScroll = React37.useCallback(
5994
6045
  (e) => {
5995
6046
  const { contentOffset, contentSize, layoutMeasurement } = e.nativeEvent;
5996
6047
  const distanceFromBottom = Math.max(contentOffset.y - Math.max(bottomInset, 0), 0);
@@ -6002,7 +6053,7 @@ var ChatMessageList = React36.forwardRef(
6002
6053
  },
6003
6054
  [bottomInset, nearBottomThreshold, onNearBottomChange]
6004
6055
  );
6005
- React36.useEffect(() => {
6056
+ React37.useEffect(() => {
6006
6057
  if (!initialScrollDoneRef.current) return;
6007
6058
  const lastId = messages.length > 0 ? messages[messages.length - 1].id : null;
6008
6059
  const prevLastId = lastMessageIdRef.current;
@@ -6012,7 +6063,7 @@ var ChatMessageList = React36.forwardRef(
6012
6063
  const id = requestAnimationFrame(() => scrollToBottom({ animated: true }));
6013
6064
  return () => cancelAnimationFrame(id);
6014
6065
  }, [messages, scrollToBottom]);
6015
- React36.useEffect(() => {
6066
+ React37.useEffect(() => {
6016
6067
  if (showTypingIndicator && nearBottomRef.current) {
6017
6068
  const id = requestAnimationFrame(() => scrollToBottom({ animated: true }));
6018
6069
  return () => cancelAnimationFrame(id);
@@ -6075,10 +6126,10 @@ function ChatPage({
6075
6126
  }) {
6076
6127
  const theme = useTheme();
6077
6128
  const insets = (0, import_react_native_safe_area_context4.useSafeAreaInsets)();
6078
- const [composerHeight, setComposerHeight] = React37.useState(0);
6079
- const [composerTopHeight, setComposerTopHeight] = React37.useState(0);
6080
- const [keyboardVisible, setKeyboardVisible] = React37.useState(false);
6081
- React37.useEffect(() => {
6129
+ const [composerHeight, setComposerHeight] = React38.useState(0);
6130
+ const [composerTopHeight, setComposerTopHeight] = React38.useState(0);
6131
+ const [keyboardVisible, setKeyboardVisible] = React38.useState(false);
6132
+ React38.useEffect(() => {
6082
6133
  if (import_react_native47.Platform.OS !== "ios") return;
6083
6134
  const show = import_react_native47.Keyboard.addListener("keyboardWillShow", () => setKeyboardVisible(true));
6084
6135
  const hide = import_react_native47.Keyboard.addListener("keyboardWillHide", () => setKeyboardVisible(false));
@@ -6091,16 +6142,16 @@ function ChatPage({
6091
6142
  const totalComposerHeight = composerHeight + composerTopHeight;
6092
6143
  const overlayBottom = totalComposerHeight + footerBottomPadding + theme.spacing.lg;
6093
6144
  const bottomInset = totalComposerHeight + footerBottomPadding + theme.spacing.xl;
6094
- const resolvedOverlay = React37.useMemo(() => {
6145
+ const resolvedOverlay = React38.useMemo(() => {
6095
6146
  var _a;
6096
6147
  if (!overlay) return null;
6097
- if (!React37.isValidElement(overlay)) return overlay;
6148
+ if (!React38.isValidElement(overlay)) return overlay;
6098
6149
  const prevStyle = (_a = overlay.props) == null ? void 0 : _a.style;
6099
- return React37.cloneElement(overlay, {
6150
+ return React38.cloneElement(overlay, {
6100
6151
  style: [prevStyle, { bottom: overlayBottom }]
6101
6152
  });
6102
6153
  }, [overlay, overlayBottom]);
6103
- React37.useEffect(() => {
6154
+ React38.useEffect(() => {
6104
6155
  if (composerTop) return;
6105
6156
  setComposerTopHeight(0);
6106
6157
  }, [composerTop]);
@@ -6165,15 +6216,15 @@ function ChatPage({
6165
6216
  }
6166
6217
 
6167
6218
  // src/components/chat/ScrollToBottomButton.tsx
6168
- var React38 = __toESM(require("react"));
6219
+ var React39 = __toESM(require("react"));
6169
6220
  var import_react_native48 = require("react-native");
6170
6221
  var import_react_native_reanimated2 = __toESM(require("react-native-reanimated"));
6171
6222
  var import_jsx_runtime50 = require("react/jsx-runtime");
6172
6223
  function ScrollToBottomButton({ visible, onPress, children, style }) {
6173
6224
  const theme = useTheme();
6174
6225
  const progress = (0, import_react_native_reanimated2.useSharedValue)(visible ? 1 : 0);
6175
- const [pressed, setPressed] = React38.useState(false);
6176
- React38.useEffect(() => {
6226
+ const [pressed, setPressed] = React39.useState(false);
6227
+ React39.useEffect(() => {
6177
6228
  progress.value = (0, import_react_native_reanimated2.withTiming)(visible ? 1 : 0, { duration: 200, easing: import_react_native_reanimated2.Easing.out(import_react_native_reanimated2.Easing.ease) });
6178
6229
  }, [progress, visible]);
6179
6230
  const animStyle = (0, import_react_native_reanimated2.useAnimatedStyle)(() => ({
@@ -6308,16 +6359,16 @@ function ForkNoticeBanner({ isOwner = true, title, description, style }) {
6308
6359
  }
6309
6360
 
6310
6361
  // src/components/chat/ChatQueue.tsx
6311
- var React39 = __toESM(require("react"));
6362
+ var React40 = __toESM(require("react"));
6312
6363
  var import_react_native51 = require("react-native");
6313
6364
  var import_jsx_runtime53 = require("react/jsx-runtime");
6314
6365
  function ChatQueue({ items, onRemove }) {
6315
6366
  const theme = useTheme();
6316
- const [expanded, setExpanded] = React39.useState({});
6317
- const [canExpand, setCanExpand] = React39.useState({});
6318
- const [collapsedText, setCollapsedText] = React39.useState({});
6319
- const [removing, setRemoving] = React39.useState({});
6320
- const buildCollapsedText = React39.useCallback((lines) => {
6367
+ const [expanded, setExpanded] = React40.useState({});
6368
+ const [canExpand, setCanExpand] = React40.useState({});
6369
+ const [collapsedText, setCollapsedText] = React40.useState({});
6370
+ const [removing, setRemoving] = React40.useState({});
6371
+ const buildCollapsedText = React40.useCallback((lines) => {
6321
6372
  var _a, _b;
6322
6373
  const line1 = ((_a = lines[0]) == null ? void 0 : _a.text) ?? "";
6323
6374
  const line2 = ((_b = lines[1]) == null ? void 0 : _b.text) ?? "";
@@ -6333,7 +6384,7 @@ function ChatQueue({ items, onRemove }) {
6333
6384
  return `${line1}
6334
6385
  ${trimmedLine2}\u2026 `;
6335
6386
  }, []);
6336
- React39.useEffect(() => {
6387
+ React40.useEffect(() => {
6337
6388
  if (items.length === 0) return;
6338
6389
  const ids = new Set(items.map((item) => item.id));
6339
6390
  setExpanded((prev) => Object.fromEntries(Object.entries(prev).filter(([id]) => ids.has(id))));
@@ -6476,9 +6527,9 @@ function ChatPanel({
6476
6527
  queueItems = [],
6477
6528
  onRemoveQueueItem
6478
6529
  }) {
6479
- const listRef = React40.useRef(null);
6480
- const [nearBottom, setNearBottom] = React40.useState(true);
6481
- const handleSend = React40.useCallback(
6530
+ const listRef = React41.useRef(null);
6531
+ const [nearBottom, setNearBottom] = React41.useState(true);
6532
+ const handleSend = React41.useCallback(
6482
6533
  async (text, composerAttachments) => {
6483
6534
  const all = composerAttachments ?? attachments;
6484
6535
  await onSend(text, all.length > 0 ? all : void 0);
@@ -6492,7 +6543,7 @@ function ChatPanel({
6492
6543
  },
6493
6544
  [attachments, nearBottom, onClearAttachments, onSend]
6494
6545
  );
6495
- const handleScrollToBottom = React40.useCallback(() => {
6546
+ const handleScrollToBottom = React41.useCallback(() => {
6496
6547
  var _a;
6497
6548
  (_a = listRef.current) == null ? void 0 : _a.scrollToBottom({ animated: true });
6498
6549
  }, []);
@@ -6568,7 +6619,7 @@ function ChatPanel({
6568
6619
  }
6569
6620
 
6570
6621
  // src/components/dialogs/ConfirmMergeRequestDialog.tsx
6571
- var React41 = __toESM(require("react"));
6622
+ var React42 = __toESM(require("react"));
6572
6623
  var import_react_native54 = require("react-native");
6573
6624
 
6574
6625
  // src/components/primitives/Modal.tsx
@@ -6616,14 +6667,14 @@ function ConfirmMergeRequestDialog({
6616
6667
  onTestFirst
6617
6668
  }) {
6618
6669
  const theme = useTheme();
6619
- const close = React41.useCallback(() => onOpenChange(false), [onOpenChange]);
6670
+ const close = React42.useCallback(() => onOpenChange(false), [onOpenChange]);
6620
6671
  const canConfirm = Boolean(mergeRequest) && !approveDisabled;
6621
- const handleConfirm = React41.useCallback(() => {
6672
+ const handleConfirm = React42.useCallback(() => {
6622
6673
  if (!mergeRequest) return;
6623
6674
  onOpenChange(false);
6624
6675
  void onConfirm();
6625
6676
  }, [mergeRequest, onConfirm, onOpenChange]);
6626
- const handleTestFirst = React41.useCallback(() => {
6677
+ const handleTestFirst = React42.useCallback(() => {
6627
6678
  if (!mergeRequest) return;
6628
6679
  onOpenChange(false);
6629
6680
  void onTestFirst(mergeRequest);
@@ -6772,7 +6823,7 @@ function ConfirmMergeFlow({
6772
6823
  }
6773
6824
 
6774
6825
  // src/studio/hooks/useOptimisticChatMessages.ts
6775
- var React42 = __toESM(require("react"));
6826
+ var React43 = __toESM(require("react"));
6776
6827
  function makeOptimisticId() {
6777
6828
  return `optimistic:${Date.now().toString(36)}:${Math.random().toString(36).slice(2, 10)}`;
6778
6829
  }
@@ -6811,11 +6862,11 @@ function useOptimisticChatMessages({
6811
6862
  chatMessages,
6812
6863
  onSendChat
6813
6864
  }) {
6814
- const [optimisticChat, setOptimisticChat] = React42.useState([]);
6815
- React42.useEffect(() => {
6865
+ const [optimisticChat, setOptimisticChat] = React43.useState([]);
6866
+ React43.useEffect(() => {
6816
6867
  setOptimisticChat([]);
6817
6868
  }, [threadId]);
6818
- const messages = React42.useMemo(() => {
6869
+ const messages = React43.useMemo(() => {
6819
6870
  if (!optimisticChat || optimisticChat.length === 0) return chatMessages;
6820
6871
  const unresolved = optimisticChat.filter((o) => !isOptimisticResolvedByServer(chatMessages, o));
6821
6872
  if (unresolved.length === 0) return chatMessages;
@@ -6831,7 +6882,7 @@ function useOptimisticChatMessages({
6831
6882
  merged.sort((a, b) => String(a.createdAt).localeCompare(String(b.createdAt)));
6832
6883
  return merged;
6833
6884
  }, [chatMessages, optimisticChat]);
6834
- React42.useEffect(() => {
6885
+ React43.useEffect(() => {
6835
6886
  if (optimisticChat.length === 0) return;
6836
6887
  setOptimisticChat((prev) => {
6837
6888
  if (prev.length === 0) return prev;
@@ -6839,7 +6890,7 @@ function useOptimisticChatMessages({
6839
6890
  return next.length === prev.length ? prev : next;
6840
6891
  });
6841
6892
  }, [chatMessages, optimisticChat.length]);
6842
- const onSend = React42.useCallback(
6893
+ const onSend = React43.useCallback(
6843
6894
  async (text, attachments) => {
6844
6895
  if (shouldForkOnEdit || disableOptimistic) {
6845
6896
  await onSendChat(text, attachments);
@@ -6895,13 +6946,13 @@ function StudioOverlay({
6895
6946
  }) {
6896
6947
  const theme = useTheme();
6897
6948
  const { width } = (0, import_react_native55.useWindowDimensions)();
6898
- const [sheetOpen, setSheetOpen] = React43.useState(false);
6899
- const sheetOpenRef = React43.useRef(sheetOpen);
6900
- const [activePage, setActivePage] = React43.useState("preview");
6901
- const [drawing, setDrawing] = React43.useState(false);
6902
- const [chatAttachments, setChatAttachments] = React43.useState([]);
6903
- const [commentsAppId, setCommentsAppId] = React43.useState(null);
6904
- const [commentsCount, setCommentsCount] = React43.useState(null);
6949
+ const [sheetOpen, setSheetOpen] = React44.useState(false);
6950
+ const sheetOpenRef = React44.useRef(sheetOpen);
6951
+ const [activePage, setActivePage] = React44.useState("preview");
6952
+ const [drawing, setDrawing] = React44.useState(false);
6953
+ const [chatAttachments, setChatAttachments] = React44.useState([]);
6954
+ const [commentsAppId, setCommentsAppId] = React44.useState(null);
6955
+ const [commentsCount, setCommentsCount] = React44.useState(null);
6905
6956
  const threadId = (app == null ? void 0 : app.threadId) ?? null;
6906
6957
  const isForking = chatForking || (app == null ? void 0 : app.status) === "forking";
6907
6958
  const queueItemsForChat = isForking ? [] : chatQueueItems;
@@ -6913,24 +6964,24 @@ function StudioOverlay({
6913
6964
  chatMessages,
6914
6965
  onSendChat
6915
6966
  });
6916
- const [confirmMrId, setConfirmMrId] = React43.useState(null);
6917
- const confirmMr = React43.useMemo(
6967
+ const [confirmMrId, setConfirmMrId] = React44.useState(null);
6968
+ const confirmMr = React44.useMemo(
6918
6969
  () => confirmMrId ? incomingMergeRequests.find((m) => m.id === confirmMrId) ?? null : null,
6919
6970
  [confirmMrId, incomingMergeRequests]
6920
6971
  );
6921
- const handleSheetOpenChange = React43.useCallback((open) => {
6972
+ const handleSheetOpenChange = React44.useCallback((open) => {
6922
6973
  setSheetOpen(open);
6923
6974
  if (!open) import_react_native55.Keyboard.dismiss();
6924
6975
  }, []);
6925
- const closeSheet = React43.useCallback(() => {
6976
+ const closeSheet = React44.useCallback(() => {
6926
6977
  handleSheetOpenChange(false);
6927
6978
  }, [handleSheetOpenChange]);
6928
- const openSheet = React43.useCallback(() => setSheetOpen(true), []);
6929
- const goToChat = React43.useCallback(() => {
6979
+ const openSheet = React44.useCallback(() => setSheetOpen(true), []);
6980
+ const goToChat = React44.useCallback(() => {
6930
6981
  setActivePage("chat");
6931
6982
  openSheet();
6932
6983
  }, [openSheet]);
6933
- const backToPreview = React43.useCallback(() => {
6984
+ const backToPreview = React44.useCallback(() => {
6934
6985
  if (import_react_native55.Platform.OS !== "ios") {
6935
6986
  import_react_native55.Keyboard.dismiss();
6936
6987
  setActivePage("preview");
@@ -6948,11 +6999,11 @@ function StudioOverlay({
6948
6999
  const t = setTimeout(finalize, 350);
6949
7000
  import_react_native55.Keyboard.dismiss();
6950
7001
  }, []);
6951
- const startDraw = React43.useCallback(() => {
7002
+ const startDraw = React44.useCallback(() => {
6952
7003
  setDrawing(true);
6953
7004
  closeSheet();
6954
7005
  }, [closeSheet]);
6955
- const handleDrawCapture = React43.useCallback(
7006
+ const handleDrawCapture = React44.useCallback(
6956
7007
  (dataUrl) => {
6957
7008
  setChatAttachments((prev) => [...prev, dataUrl]);
6958
7009
  setDrawing(false);
@@ -6961,7 +7012,7 @@ function StudioOverlay({
6961
7012
  },
6962
7013
  [openSheet]
6963
7014
  );
6964
- const toggleSheet = React43.useCallback(async () => {
7015
+ const toggleSheet = React44.useCallback(async () => {
6965
7016
  if (!sheetOpen) {
6966
7017
  const shouldExitTest = Boolean(testingMrId) || isTesting;
6967
7018
  if (shouldExitTest) {
@@ -6973,7 +7024,7 @@ function StudioOverlay({
6973
7024
  closeSheet();
6974
7025
  }
6975
7026
  }, [closeSheet, isTesting, onRestoreBase, sheetOpen, testingMrId]);
6976
- const handleTestMr = React43.useCallback(
7027
+ const handleTestMr = React44.useCallback(
6977
7028
  async (mr) => {
6978
7029
  if (!onTestMr) return;
6979
7030
  await onTestMr(mr);
@@ -6981,10 +7032,10 @@ function StudioOverlay({
6981
7032
  },
6982
7033
  [closeSheet, onTestMr]
6983
7034
  );
6984
- React43.useEffect(() => {
7035
+ React44.useEffect(() => {
6985
7036
  sheetOpenRef.current = sheetOpen;
6986
7037
  }, [sheetOpen]);
6987
- React43.useEffect(() => {
7038
+ React44.useEffect(() => {
6988
7039
  const poller = (0, import_studio_control.startStudioControlPolling)((action) => {
6989
7040
  if (action === "show" && !sheetOpenRef.current) openSheet();
6990
7041
  if (action === "hide" && sheetOpenRef.current) closeSheet();
@@ -6992,7 +7043,7 @@ function StudioOverlay({
6992
7043
  }, studioControlOptions);
6993
7044
  return () => poller.stop();
6994
7045
  }, [closeSheet, openSheet, studioControlOptions, toggleSheet]);
6995
- React43.useEffect(() => {
7046
+ React44.useEffect(() => {
6996
7047
  void (0, import_studio_control.publishComergeStudioUIState)(sheetOpen, studioControlOptions);
6997
7048
  }, [sheetOpen, studioControlOptions]);
6998
7049
  return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
@@ -7099,7 +7150,7 @@ function StudioOverlay({
7099
7150
  }
7100
7151
 
7101
7152
  // src/studio/hooks/useEditQueue.ts
7102
- var React44 = __toESM(require("react"));
7153
+ var React45 = __toESM(require("react"));
7103
7154
 
7104
7155
  // src/data/apps/edit-queue/remote.ts
7105
7156
  var EditQueueRemoteDataSourceImpl = class extends BaseRemote {
@@ -7210,17 +7261,17 @@ var editQueueRepository = new EditQueueRepositoryImpl(
7210
7261
 
7211
7262
  // src/studio/hooks/useEditQueue.ts
7212
7263
  function useEditQueue(appId) {
7213
- const [items, setItems] = React44.useState([]);
7214
- const [loading, setLoading] = React44.useState(false);
7215
- const [error, setError] = React44.useState(null);
7216
- const activeRequestIdRef = React44.useRef(0);
7264
+ const [items, setItems] = React45.useState([]);
7265
+ const [loading, setLoading] = React45.useState(false);
7266
+ const [error, setError] = React45.useState(null);
7267
+ const activeRequestIdRef = React45.useRef(0);
7217
7268
  const foregroundSignal = useForegroundSignal(Boolean(appId));
7218
- const upsertSorted = React44.useCallback((prev, nextItem) => {
7269
+ const upsertSorted = React45.useCallback((prev, nextItem) => {
7219
7270
  const next = prev.some((x) => x.id === nextItem.id) ? prev.map((x) => x.id === nextItem.id ? nextItem : x) : [...prev, nextItem];
7220
7271
  next.sort((a, b) => String(a.createdAt).localeCompare(String(b.createdAt)));
7221
7272
  return next;
7222
7273
  }, []);
7223
- const refetch = React44.useCallback(async () => {
7274
+ const refetch = React45.useCallback(async () => {
7224
7275
  if (!appId) {
7225
7276
  setItems([]);
7226
7277
  return;
@@ -7240,10 +7291,10 @@ function useEditQueue(appId) {
7240
7291
  if (activeRequestIdRef.current === requestId) setLoading(false);
7241
7292
  }
7242
7293
  }, [appId]);
7243
- React44.useEffect(() => {
7294
+ React45.useEffect(() => {
7244
7295
  void refetch();
7245
7296
  }, [refetch]);
7246
- React44.useEffect(() => {
7297
+ React45.useEffect(() => {
7247
7298
  if (!appId) return;
7248
7299
  const unsubscribe = editQueueRepository.subscribeEditQueue(appId, {
7249
7300
  onInsert: (item) => setItems((prev) => upsertSorted(prev, item)),
@@ -7252,7 +7303,7 @@ function useEditQueue(appId) {
7252
7303
  });
7253
7304
  return unsubscribe;
7254
7305
  }, [appId, upsertSorted, foregroundSignal]);
7255
- React44.useEffect(() => {
7306
+ React45.useEffect(() => {
7256
7307
  if (!appId) return;
7257
7308
  if (foregroundSignal <= 0) return;
7258
7309
  void refetch();
@@ -7261,16 +7312,16 @@ function useEditQueue(appId) {
7261
7312
  }
7262
7313
 
7263
7314
  // src/studio/hooks/useEditQueueActions.ts
7264
- var React45 = __toESM(require("react"));
7315
+ var React46 = __toESM(require("react"));
7265
7316
  function useEditQueueActions(appId) {
7266
- const update = React45.useCallback(
7317
+ const update = React46.useCallback(
7267
7318
  async (queueItemId, payload) => {
7268
7319
  if (!appId) return;
7269
7320
  await editQueueRepository.update(appId, queueItemId, payload);
7270
7321
  },
7271
7322
  [appId]
7272
7323
  );
7273
- const cancel = React45.useCallback(
7324
+ const cancel = React46.useCallback(
7274
7325
  async (queueItemId) => {
7275
7326
  if (!appId) return;
7276
7327
  await editQueueRepository.cancel(appId, queueItemId);
@@ -7292,16 +7343,16 @@ function ComergeStudio({
7292
7343
  studioControlOptions,
7293
7344
  embeddedBaseBundles
7294
7345
  }) {
7295
- const [activeAppId, setActiveAppId] = React46.useState(appId);
7296
- const [runtimeAppId, setRuntimeAppId] = React46.useState(appId);
7297
- const [pendingRuntimeTargetAppId, setPendingRuntimeTargetAppId] = React46.useState(null);
7298
- const platform = React46.useMemo(() => import_react_native56.Platform.OS === "ios" ? "ios" : "android", []);
7299
- React46.useEffect(() => {
7346
+ const [activeAppId, setActiveAppId] = React47.useState(appId);
7347
+ const [runtimeAppId, setRuntimeAppId] = React47.useState(appId);
7348
+ const [pendingRuntimeTargetAppId, setPendingRuntimeTargetAppId] = React47.useState(null);
7349
+ const platform = React47.useMemo(() => import_react_native56.Platform.OS === "ios" ? "ios" : "android", []);
7350
+ React47.useEffect(() => {
7300
7351
  setActiveAppId(appId);
7301
7352
  setRuntimeAppId(appId);
7302
7353
  setPendingRuntimeTargetAppId(null);
7303
7354
  }, [appId]);
7304
- const captureTargetRef = React46.useRef(null);
7355
+ const captureTargetRef = React47.useRef(null);
7305
7356
  return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(StudioBootstrap, { clientKey: clientKey2, fallback: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_react_native56.View, { style: { flex: 1 } }), children: ({ userId }) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_bottom_sheet6.BottomSheetModalProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(LiquidGlassResetProvider, { resetTriggers: [appId, activeAppId, runtimeAppId], children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
7306
7357
  ComergeStudioInner,
7307
7358
  {
@@ -7343,11 +7394,11 @@ function ComergeStudioInner({
7343
7394
  const { app, loading: appLoading } = useApp(activeAppId);
7344
7395
  const { app: runtimeAppFromHook } = useApp(runtimeAppId, { enabled: runtimeAppId !== activeAppId });
7345
7396
  const runtimeApp = runtimeAppId === activeAppId ? app : runtimeAppFromHook;
7346
- const sawEditingOnPendingTargetRef = React46.useRef(false);
7347
- React46.useEffect(() => {
7397
+ const sawEditingOnPendingTargetRef = React47.useRef(false);
7398
+ React47.useEffect(() => {
7348
7399
  sawEditingOnPendingTargetRef.current = false;
7349
7400
  }, [pendingRuntimeTargetAppId]);
7350
- React46.useEffect(() => {
7401
+ React47.useEffect(() => {
7351
7402
  if (!pendingRuntimeTargetAppId) return;
7352
7403
  if (activeAppId !== pendingRuntimeTargetAppId) return;
7353
7404
  if ((app == null ? void 0 : app.status) === "editing") {
@@ -7365,13 +7416,13 @@ function ComergeStudioInner({
7365
7416
  canRequestLatest: (runtimeApp == null ? void 0 : runtimeApp.status) === "ready",
7366
7417
  embeddedBaseBundles
7367
7418
  });
7368
- const sawEditingOnActiveAppRef = React46.useRef(false);
7369
- const [showPostEditPreparing, setShowPostEditPreparing] = React46.useState(false);
7370
- React46.useEffect(() => {
7419
+ const sawEditingOnActiveAppRef = React47.useRef(false);
7420
+ const [showPostEditPreparing, setShowPostEditPreparing] = React47.useState(false);
7421
+ React47.useEffect(() => {
7371
7422
  sawEditingOnActiveAppRef.current = false;
7372
7423
  setShowPostEditPreparing(false);
7373
7424
  }, [activeAppId]);
7374
- React46.useEffect(() => {
7425
+ React47.useEffect(() => {
7375
7426
  if (!(app == null ? void 0 : app.id)) return;
7376
7427
  if (app.status === "editing") {
7377
7428
  sawEditingOnActiveAppRef.current = true;
@@ -7383,7 +7434,7 @@ function ComergeStudioInner({
7383
7434
  sawEditingOnActiveAppRef.current = false;
7384
7435
  }
7385
7436
  }, [app == null ? void 0 : app.id, app == null ? void 0 : app.status]);
7386
- React46.useEffect(() => {
7437
+ React47.useEffect(() => {
7387
7438
  if (!showPostEditPreparing) return;
7388
7439
  const stillProcessingBaseBundle = bundle.loading && bundle.loadingMode === "base" && !bundle.isTesting;
7389
7440
  if (!stillProcessingBaseBundle) {
@@ -7394,19 +7445,19 @@ function ComergeStudioInner({
7394
7445
  const thread = useThreadMessages(threadId);
7395
7446
  const editQueue = useEditQueue(activeAppId);
7396
7447
  const editQueueActions = useEditQueueActions(activeAppId);
7397
- const [lastEditQueueInfo, setLastEditQueueInfo] = React46.useState(null);
7398
- const lastEditQueueInfoRef = React46.useRef(null);
7399
- const [suppressQueueUntilResponse, setSuppressQueueUntilResponse] = React46.useState(false);
7448
+ const [lastEditQueueInfo, setLastEditQueueInfo] = React47.useState(null);
7449
+ const lastEditQueueInfoRef = React47.useRef(null);
7450
+ const [suppressQueueUntilResponse, setSuppressQueueUntilResponse] = React47.useState(false);
7400
7451
  const mergeRequests = useMergeRequests({ appId: activeAppId });
7401
- const hasOpenOutgoingMr = React46.useMemo(() => {
7452
+ const hasOpenOutgoingMr = React47.useMemo(() => {
7402
7453
  return mergeRequests.lists.outgoing.some((mr) => mr.status === "open");
7403
7454
  }, [mergeRequests.lists.outgoing]);
7404
- const incomingReviewMrs = React46.useMemo(() => {
7455
+ const incomingReviewMrs = React47.useMemo(() => {
7405
7456
  if (!userId) return mergeRequests.lists.incoming;
7406
7457
  return mergeRequests.lists.incoming.filter((mr) => mr.createdBy !== userId);
7407
7458
  }, [mergeRequests.lists.incoming, userId]);
7408
7459
  const uploader = useAttachmentUpload();
7409
- const updateLastEditQueueInfo = React46.useCallback(
7460
+ const updateLastEditQueueInfo = React47.useCallback(
7410
7461
  (info) => {
7411
7462
  lastEditQueueInfoRef.current = info;
7412
7463
  setLastEditQueueInfo(info);
@@ -7447,20 +7498,20 @@ function ComergeStudioInner({
7447
7498
  }
7448
7499
  });
7449
7500
  const chatSendDisabled = false;
7450
- const [processingMrId, setProcessingMrId] = React46.useState(null);
7451
- const [testingMrId, setTestingMrId] = React46.useState(null);
7452
- const chatShowTypingIndicator = React46.useMemo(() => {
7501
+ const [processingMrId, setProcessingMrId] = React47.useState(null);
7502
+ const [testingMrId, setTestingMrId] = React47.useState(null);
7503
+ const chatShowTypingIndicator = React47.useMemo(() => {
7453
7504
  var _a;
7454
7505
  if (!thread.raw || thread.raw.length === 0) return false;
7455
7506
  const last = thread.raw[thread.raw.length - 1];
7456
7507
  const payloadType = typeof ((_a = last.payload) == null ? void 0 : _a.type) === "string" ? String(last.payload.type) : void 0;
7457
7508
  return payloadType !== "outcome";
7458
7509
  }, [thread.raw]);
7459
- React46.useEffect(() => {
7510
+ React47.useEffect(() => {
7460
7511
  updateLastEditQueueInfo(null);
7461
7512
  setSuppressQueueUntilResponse(false);
7462
7513
  }, [activeAppId, updateLastEditQueueInfo]);
7463
- React46.useEffect(() => {
7514
+ React47.useEffect(() => {
7464
7515
  if (!(lastEditQueueInfo == null ? void 0 : lastEditQueueInfo.queueItemId)) return;
7465
7516
  const stillPresent = editQueue.items.some((item) => item.id === lastEditQueueInfo.queueItemId);
7466
7517
  if (!stillPresent) {
@@ -7468,7 +7519,7 @@ function ComergeStudioInner({
7468
7519
  setSuppressQueueUntilResponse(false);
7469
7520
  }
7470
7521
  }, [editQueue.items, lastEditQueueInfo == null ? void 0 : lastEditQueueInfo.queueItemId]);
7471
- const chatQueueItems = React46.useMemo(() => {
7522
+ const chatQueueItems = React47.useMemo(() => {
7472
7523
  var _a;
7473
7524
  if (suppressQueueUntilResponse && editQueue.items.length <= 1) {
7474
7525
  return [];