@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 +675 -576
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +423 -324
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/chat/ChatComposer.tsx +3 -1
- package/src/components/chat/ChatMessageList.tsx +26 -9
- package/src/components/chat/ChatPage.tsx +2 -1
- package/src/components/comments/AppCommentsSheet.tsx +6 -1
- package/src/components/comments/useIosKeyboardSnapFix.ts +11 -3
- package/src/components/studio-sheet/StudioBottomSheet.tsx +33 -5
- package/src/studio/hooks/useApp.ts +10 -4
- package/src/studio/hooks/useForegroundSignal.ts +37 -0
- package/src/studio/hooks/useThreadMessages.ts +25 -5
- package/src/studio/ui/ChatPanel.tsx +9 -3
package/dist/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
// src/studio/ComergeStudio.tsx
|
|
9
|
-
import * as
|
|
9
|
+
import * as React39 from "react";
|
|
10
10
|
import { Platform as RNPlatform, View as View45 } from "react-native";
|
|
11
11
|
import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";
|
|
12
12
|
|
|
@@ -363,7 +363,7 @@ function StudioBootstrap({ children, fallback, renderError, apiKey }) {
|
|
|
363
363
|
}
|
|
364
364
|
|
|
365
365
|
// src/studio/hooks/useApp.ts
|
|
366
|
-
import * as
|
|
366
|
+
import * as React3 from "react";
|
|
367
367
|
|
|
368
368
|
// src/core/services/http/index.ts
|
|
369
369
|
import axios2 from "axios";
|
|
@@ -662,13 +662,40 @@ var AppsRepositoryImpl = class extends BaseRepository {
|
|
|
662
662
|
};
|
|
663
663
|
var appsRepository = new AppsRepositoryImpl(appsRemoteDataSource);
|
|
664
664
|
|
|
665
|
+
// src/studio/hooks/useForegroundSignal.ts
|
|
666
|
+
import * as React2 from "react";
|
|
667
|
+
import { AppState } from "react-native";
|
|
668
|
+
function useForegroundSignal(enabled = true) {
|
|
669
|
+
const [signal, setSignal] = React2.useState(0);
|
|
670
|
+
const lastStateRef = React2.useRef(AppState.currentState);
|
|
671
|
+
React2.useEffect(() => {
|
|
672
|
+
if (!enabled) return;
|
|
673
|
+
const sub = AppState.addEventListener("change", (nextState) => {
|
|
674
|
+
var _a, _b;
|
|
675
|
+
const prevState = lastStateRef.current;
|
|
676
|
+
lastStateRef.current = nextState;
|
|
677
|
+
const didResume = (prevState === "background" || prevState === "inactive") && nextState === "active";
|
|
678
|
+
if (!didResume) return;
|
|
679
|
+
try {
|
|
680
|
+
const supabase = getSupabaseClient();
|
|
681
|
+
(_b = (_a = supabase == null ? void 0 : supabase.realtime) == null ? void 0 : _a.connect) == null ? void 0 : _b.call(_a);
|
|
682
|
+
} catch {
|
|
683
|
+
}
|
|
684
|
+
setSignal((s) => s + 1);
|
|
685
|
+
});
|
|
686
|
+
return () => sub.remove();
|
|
687
|
+
}, [enabled]);
|
|
688
|
+
return signal;
|
|
689
|
+
}
|
|
690
|
+
|
|
665
691
|
// src/studio/hooks/useApp.ts
|
|
666
692
|
function useApp(appId, options) {
|
|
667
693
|
const enabled = (options == null ? void 0 : options.enabled) ?? true;
|
|
668
|
-
const [app, setApp] =
|
|
669
|
-
const [loading, setLoading] =
|
|
670
|
-
const [error, setError] =
|
|
671
|
-
const
|
|
694
|
+
const [app, setApp] = React3.useState(null);
|
|
695
|
+
const [loading, setLoading] = React3.useState(false);
|
|
696
|
+
const [error, setError] = React3.useState(null);
|
|
697
|
+
const foregroundSignal = useForegroundSignal(enabled && Boolean(appId));
|
|
698
|
+
const mergeApp = React3.useCallback((prev, next) => {
|
|
672
699
|
const merged = {
|
|
673
700
|
...prev ?? {},
|
|
674
701
|
...next,
|
|
@@ -677,7 +704,7 @@ function useApp(appId, options) {
|
|
|
677
704
|
};
|
|
678
705
|
return merged;
|
|
679
706
|
}, []);
|
|
680
|
-
const fetchOnce =
|
|
707
|
+
const fetchOnce = React3.useCallback(async () => {
|
|
681
708
|
if (!enabled) return;
|
|
682
709
|
if (!appId) return;
|
|
683
710
|
setLoading(true);
|
|
@@ -692,34 +719,37 @@ function useApp(appId, options) {
|
|
|
692
719
|
setLoading(false);
|
|
693
720
|
}
|
|
694
721
|
}, [appId, enabled]);
|
|
695
|
-
|
|
722
|
+
React3.useEffect(() => {
|
|
696
723
|
if (!enabled) return;
|
|
697
724
|
void fetchOnce();
|
|
698
725
|
}, [enabled, fetchOnce]);
|
|
699
|
-
|
|
726
|
+
React3.useEffect(() => {
|
|
700
727
|
if (!enabled) return;
|
|
701
728
|
if (!appId) return;
|
|
702
729
|
const unsubscribe = appsRepository.subscribeApp(appId, {
|
|
703
730
|
onInsert: (a) => {
|
|
704
|
-
console.log("[useApp] onInsert", a);
|
|
705
731
|
setApp((prev) => mergeApp(prev, a));
|
|
706
732
|
},
|
|
707
733
|
onUpdate: (a) => {
|
|
708
|
-
console.log("[useApp] onUpdate", a);
|
|
709
734
|
setApp((prev) => mergeApp(prev, a));
|
|
710
735
|
},
|
|
711
736
|
onDelete: () => {
|
|
712
|
-
console.log("[useApp] onDelete");
|
|
713
737
|
setApp(null);
|
|
714
738
|
}
|
|
715
739
|
});
|
|
716
740
|
return unsubscribe;
|
|
717
|
-
}, [appId, enabled, mergeApp]);
|
|
741
|
+
}, [appId, enabled, mergeApp, foregroundSignal]);
|
|
742
|
+
React3.useEffect(() => {
|
|
743
|
+
if (!enabled) return;
|
|
744
|
+
if (!appId) return;
|
|
745
|
+
if (foregroundSignal <= 0) return;
|
|
746
|
+
void fetchOnce();
|
|
747
|
+
}, [appId, enabled, fetchOnce, foregroundSignal]);
|
|
718
748
|
return { app, loading, error, refetch: fetchOnce };
|
|
719
749
|
}
|
|
720
750
|
|
|
721
751
|
// src/studio/hooks/useThreadMessages.ts
|
|
722
|
-
import * as
|
|
752
|
+
import * as React4 from "react";
|
|
723
753
|
|
|
724
754
|
// src/data/messages/remote.ts
|
|
725
755
|
var MessagesRemoteDataSourceImpl = class extends BaseRemote {
|
|
@@ -820,44 +850,59 @@ function mapMessageToChatMessage(m) {
|
|
|
820
850
|
};
|
|
821
851
|
}
|
|
822
852
|
function useThreadMessages(threadId) {
|
|
823
|
-
const [raw, setRaw] =
|
|
824
|
-
const [loading, setLoading] =
|
|
825
|
-
const [error, setError] =
|
|
826
|
-
const
|
|
853
|
+
const [raw, setRaw] = React4.useState([]);
|
|
854
|
+
const [loading, setLoading] = React4.useState(false);
|
|
855
|
+
const [error, setError] = React4.useState(null);
|
|
856
|
+
const activeRequestIdRef = React4.useRef(0);
|
|
857
|
+
const foregroundSignal = useForegroundSignal(Boolean(threadId));
|
|
858
|
+
const upsertSorted = React4.useCallback((prev, m) => {
|
|
859
|
+
const next = prev.some((x) => x.id === m.id) ? prev.map((x) => x.id === m.id ? m : x) : [...prev, m];
|
|
860
|
+
next.sort((a, b) => String(a.createdAt).localeCompare(String(b.createdAt)));
|
|
861
|
+
return next;
|
|
862
|
+
}, []);
|
|
863
|
+
const refetch = React4.useCallback(async () => {
|
|
827
864
|
if (!threadId) {
|
|
828
865
|
setRaw([]);
|
|
829
866
|
return;
|
|
830
867
|
}
|
|
868
|
+
const requestId = ++activeRequestIdRef.current;
|
|
831
869
|
setLoading(true);
|
|
832
870
|
setError(null);
|
|
833
871
|
try {
|
|
834
872
|
const list = await messagesRepository.list(threadId);
|
|
835
|
-
|
|
873
|
+
if (activeRequestIdRef.current !== requestId) return;
|
|
874
|
+
setRaw([...list].sort((a, b) => String(a.createdAt).localeCompare(String(b.createdAt))));
|
|
836
875
|
} catch (e) {
|
|
876
|
+
if (activeRequestIdRef.current !== requestId) return;
|
|
837
877
|
setError(e instanceof Error ? e : new Error(String(e)));
|
|
838
878
|
setRaw([]);
|
|
839
879
|
} finally {
|
|
840
|
-
setLoading(false);
|
|
880
|
+
if (activeRequestIdRef.current === requestId) setLoading(false);
|
|
841
881
|
}
|
|
842
882
|
}, [threadId]);
|
|
843
|
-
|
|
883
|
+
React4.useEffect(() => {
|
|
844
884
|
void refetch();
|
|
845
885
|
}, [refetch]);
|
|
846
|
-
|
|
886
|
+
React4.useEffect(() => {
|
|
847
887
|
if (!threadId) return;
|
|
848
888
|
const unsubscribe = messagesRepository.subscribeThread(threadId, {
|
|
849
|
-
onInsert: (m) => setRaw((prev) =>
|
|
850
|
-
onUpdate: (m) => setRaw((prev) => prev
|
|
889
|
+
onInsert: (m) => setRaw((prev) => upsertSorted(prev, m)),
|
|
890
|
+
onUpdate: (m) => setRaw((prev) => upsertSorted(prev, m)),
|
|
851
891
|
onDelete: (m) => setRaw((prev) => prev.filter((x) => x.id !== m.id))
|
|
852
892
|
});
|
|
853
893
|
return unsubscribe;
|
|
854
|
-
}, [threadId]);
|
|
855
|
-
|
|
894
|
+
}, [threadId, upsertSorted, foregroundSignal]);
|
|
895
|
+
React4.useEffect(() => {
|
|
896
|
+
if (!threadId) return;
|
|
897
|
+
if (foregroundSignal <= 0) return;
|
|
898
|
+
void refetch();
|
|
899
|
+
}, [foregroundSignal, refetch, threadId]);
|
|
900
|
+
const messages = React4.useMemo(() => raw.map(mapMessageToChatMessage), [raw]);
|
|
856
901
|
return { raw, messages, loading, error, refetch };
|
|
857
902
|
}
|
|
858
903
|
|
|
859
904
|
// src/studio/hooks/useBundleManager.ts
|
|
860
|
-
import * as
|
|
905
|
+
import * as React5 from "react";
|
|
861
906
|
import * as FileSystem from "expo-file-system/legacy";
|
|
862
907
|
|
|
863
908
|
// src/data/apps/bundles/remote.ts
|
|
@@ -1030,19 +1075,19 @@ function useBundleManager({
|
|
|
1030
1075
|
platform,
|
|
1031
1076
|
canRequestLatest = true
|
|
1032
1077
|
}) {
|
|
1033
|
-
const [bundlePath, setBundlePath] =
|
|
1034
|
-
const [renderToken, setRenderToken] =
|
|
1035
|
-
const [loading, setLoading] =
|
|
1036
|
-
const [statusLabel, setStatusLabel] =
|
|
1037
|
-
const [error, setError] =
|
|
1038
|
-
const [isTesting, setIsTesting] =
|
|
1039
|
-
const baseRef =
|
|
1078
|
+
const [bundlePath, setBundlePath] = React5.useState(null);
|
|
1079
|
+
const [renderToken, setRenderToken] = React5.useState(0);
|
|
1080
|
+
const [loading, setLoading] = React5.useState(false);
|
|
1081
|
+
const [statusLabel, setStatusLabel] = React5.useState(null);
|
|
1082
|
+
const [error, setError] = React5.useState(null);
|
|
1083
|
+
const [isTesting, setIsTesting] = React5.useState(false);
|
|
1084
|
+
const baseRef = React5.useRef(base);
|
|
1040
1085
|
baseRef.current = base;
|
|
1041
|
-
const baseOpIdRef =
|
|
1042
|
-
const testOpIdRef =
|
|
1043
|
-
const activeLoadModeRef =
|
|
1044
|
-
const canRequestLatestRef =
|
|
1045
|
-
|
|
1086
|
+
const baseOpIdRef = React5.useRef(0);
|
|
1087
|
+
const testOpIdRef = React5.useRef(0);
|
|
1088
|
+
const activeLoadModeRef = React5.useRef(null);
|
|
1089
|
+
const canRequestLatestRef = React5.useRef(canRequestLatest);
|
|
1090
|
+
React5.useEffect(() => {
|
|
1046
1091
|
canRequestLatestRef.current = canRequestLatest;
|
|
1047
1092
|
if (!canRequestLatest) {
|
|
1048
1093
|
baseOpIdRef.current += 1;
|
|
@@ -1053,11 +1098,11 @@ function useBundleManager({
|
|
|
1053
1098
|
}
|
|
1054
1099
|
}
|
|
1055
1100
|
}, [canRequestLatest]);
|
|
1056
|
-
const lastBaseBundlePathRef =
|
|
1057
|
-
const lastBaseFingerprintRef =
|
|
1058
|
-
const initialHydratedBaseFromDiskRef =
|
|
1059
|
-
const hasCompletedFirstNetworkBaseLoadRef =
|
|
1060
|
-
const hydrateBaseFromDisk =
|
|
1101
|
+
const lastBaseBundlePathRef = React5.useRef(null);
|
|
1102
|
+
const lastBaseFingerprintRef = React5.useRef(null);
|
|
1103
|
+
const initialHydratedBaseFromDiskRef = React5.useRef(false);
|
|
1104
|
+
const hasCompletedFirstNetworkBaseLoadRef = React5.useRef(false);
|
|
1105
|
+
const hydrateBaseFromDisk = React5.useCallback(
|
|
1061
1106
|
async (appId, reason) => {
|
|
1062
1107
|
try {
|
|
1063
1108
|
const dir = bundlesCacheDir();
|
|
@@ -1082,13 +1127,13 @@ function useBundleManager({
|
|
|
1082
1127
|
},
|
|
1083
1128
|
[platform]
|
|
1084
1129
|
);
|
|
1085
|
-
|
|
1130
|
+
React5.useEffect(() => {
|
|
1086
1131
|
if (!base.appId) return;
|
|
1087
1132
|
initialHydratedBaseFromDiskRef.current = false;
|
|
1088
1133
|
hasCompletedFirstNetworkBaseLoadRef.current = false;
|
|
1089
1134
|
void hydrateBaseFromDisk(base.appId, "initial");
|
|
1090
1135
|
}, [base.appId, platform, hydrateBaseFromDisk]);
|
|
1091
|
-
const activateCachedBase =
|
|
1136
|
+
const activateCachedBase = React5.useCallback(
|
|
1092
1137
|
async (appId) => {
|
|
1093
1138
|
setIsTesting(false);
|
|
1094
1139
|
setStatusLabel(null);
|
|
@@ -1102,7 +1147,7 @@ function useBundleManager({
|
|
|
1102
1147
|
},
|
|
1103
1148
|
[hydrateBaseFromDisk]
|
|
1104
1149
|
);
|
|
1105
|
-
const load =
|
|
1150
|
+
const load = React5.useCallback(async (src, mode) => {
|
|
1106
1151
|
if (!src.appId) return;
|
|
1107
1152
|
const canRequestLatest2 = canRequestLatestRef.current;
|
|
1108
1153
|
if (mode === "base" && !canRequestLatest2) {
|
|
@@ -1157,13 +1202,13 @@ function useBundleManager({
|
|
|
1157
1202
|
if (activeLoadModeRef.current === mode) activeLoadModeRef.current = null;
|
|
1158
1203
|
}
|
|
1159
1204
|
}, [activateCachedBase, platform]);
|
|
1160
|
-
const loadBase =
|
|
1205
|
+
const loadBase = React5.useCallback(async () => {
|
|
1161
1206
|
await load(baseRef.current, "base");
|
|
1162
1207
|
}, [load]);
|
|
1163
|
-
const loadTest =
|
|
1208
|
+
const loadTest = React5.useCallback(async (src) => {
|
|
1164
1209
|
await load(src, "test");
|
|
1165
1210
|
}, [load]);
|
|
1166
|
-
const restoreBase =
|
|
1211
|
+
const restoreBase = React5.useCallback(async () => {
|
|
1167
1212
|
const src = baseRef.current;
|
|
1168
1213
|
if (!src.appId) return;
|
|
1169
1214
|
await activateCachedBase(src.appId);
|
|
@@ -1171,7 +1216,7 @@ function useBundleManager({
|
|
|
1171
1216
|
await load(src, "base");
|
|
1172
1217
|
}
|
|
1173
1218
|
}, [activateCachedBase, load]);
|
|
1174
|
-
|
|
1219
|
+
React5.useEffect(() => {
|
|
1175
1220
|
if (!canRequestLatest) return;
|
|
1176
1221
|
void loadBase();
|
|
1177
1222
|
}, [base.appId, base.commitId, platform, canRequestLatest, loadBase]);
|
|
@@ -1179,7 +1224,7 @@ function useBundleManager({
|
|
|
1179
1224
|
}
|
|
1180
1225
|
|
|
1181
1226
|
// src/studio/hooks/useMergeRequests.ts
|
|
1182
|
-
import * as
|
|
1227
|
+
import * as React6 from "react";
|
|
1183
1228
|
|
|
1184
1229
|
// src/data/merge-requests/remote.ts
|
|
1185
1230
|
var MergeRequestsRemoteDataSourceImpl = class extends BaseRemote {
|
|
@@ -1325,12 +1370,12 @@ function toUiStatus(status) {
|
|
|
1325
1370
|
}
|
|
1326
1371
|
function useMergeRequests(params) {
|
|
1327
1372
|
const { appId } = params;
|
|
1328
|
-
const [incoming, setIncoming] =
|
|
1329
|
-
const [outgoing, setOutgoing] =
|
|
1330
|
-
const [loading, setLoading] =
|
|
1331
|
-
const [error, setError] =
|
|
1332
|
-
const [creatorStatsById, setCreatorStatsById] =
|
|
1333
|
-
const pollUntilMerged =
|
|
1373
|
+
const [incoming, setIncoming] = React6.useState([]);
|
|
1374
|
+
const [outgoing, setOutgoing] = React6.useState([]);
|
|
1375
|
+
const [loading, setLoading] = React6.useState(false);
|
|
1376
|
+
const [error, setError] = React6.useState(null);
|
|
1377
|
+
const [creatorStatsById, setCreatorStatsById] = React6.useState({});
|
|
1378
|
+
const pollUntilMerged = React6.useCallback(async (mrId) => {
|
|
1334
1379
|
const startedAt = Date.now();
|
|
1335
1380
|
const timeoutMs = 2 * 60 * 1e3;
|
|
1336
1381
|
for (; ; ) {
|
|
@@ -1340,7 +1385,7 @@ function useMergeRequests(params) {
|
|
|
1340
1385
|
await new Promise((r) => setTimeout(r, 1500));
|
|
1341
1386
|
}
|
|
1342
1387
|
}, []);
|
|
1343
|
-
const refresh =
|
|
1388
|
+
const refresh = React6.useCallback(async () => {
|
|
1344
1389
|
if (!appId) {
|
|
1345
1390
|
setIncoming([]);
|
|
1346
1391
|
setOutgoing([]);
|
|
@@ -1379,27 +1424,27 @@ function useMergeRequests(params) {
|
|
|
1379
1424
|
setLoading(false);
|
|
1380
1425
|
}
|
|
1381
1426
|
}, [appId]);
|
|
1382
|
-
|
|
1427
|
+
React6.useEffect(() => {
|
|
1383
1428
|
void refresh();
|
|
1384
1429
|
}, [refresh]);
|
|
1385
|
-
const openMergeRequest =
|
|
1430
|
+
const openMergeRequest = React6.useCallback(async (sourceAppId) => {
|
|
1386
1431
|
const mr = await mergeRequestsRepository.open({ sourceAppId });
|
|
1387
1432
|
await refresh();
|
|
1388
1433
|
return mr;
|
|
1389
1434
|
}, [refresh]);
|
|
1390
|
-
const approve =
|
|
1435
|
+
const approve = React6.useCallback(async (mrId) => {
|
|
1391
1436
|
const mr = await mergeRequestsRepository.update(mrId, { status: "approved" });
|
|
1392
1437
|
await refresh();
|
|
1393
1438
|
const merged = await pollUntilMerged(mrId);
|
|
1394
1439
|
await refresh();
|
|
1395
1440
|
return merged ?? mr;
|
|
1396
1441
|
}, [pollUntilMerged, refresh]);
|
|
1397
|
-
const reject =
|
|
1442
|
+
const reject = React6.useCallback(async (mrId) => {
|
|
1398
1443
|
const mr = await mergeRequestsRepository.update(mrId, { status: "rejected" });
|
|
1399
1444
|
await refresh();
|
|
1400
1445
|
return mr;
|
|
1401
1446
|
}, [refresh]);
|
|
1402
|
-
const toSummary =
|
|
1447
|
+
const toSummary = React6.useCallback((mr) => {
|
|
1403
1448
|
const stats = creatorStatsById[mr.createdBy];
|
|
1404
1449
|
return {
|
|
1405
1450
|
id: mr.id,
|
|
@@ -1415,7 +1460,7 @@ function useMergeRequests(params) {
|
|
|
1415
1460
|
updatedAt: mr.updatedAt
|
|
1416
1461
|
};
|
|
1417
1462
|
}, [creatorStatsById]);
|
|
1418
|
-
const byId =
|
|
1463
|
+
const byId = React6.useMemo(() => {
|
|
1419
1464
|
const all = [...incoming, ...outgoing];
|
|
1420
1465
|
const map = {};
|
|
1421
1466
|
for (const mr of all) map[mr.id] = mr;
|
|
@@ -1433,7 +1478,7 @@ function useMergeRequests(params) {
|
|
|
1433
1478
|
}
|
|
1434
1479
|
|
|
1435
1480
|
// src/studio/hooks/useAttachmentUpload.ts
|
|
1436
|
-
import * as
|
|
1481
|
+
import * as React7 from "react";
|
|
1437
1482
|
|
|
1438
1483
|
// src/data/attachment/remote.ts
|
|
1439
1484
|
var AttachmentRemoteDataSourceImpl = class extends BaseRemote {
|
|
@@ -1474,9 +1519,9 @@ var attachmentRepository = new AttachmentRepositoryImpl(
|
|
|
1474
1519
|
|
|
1475
1520
|
// src/studio/hooks/useAttachmentUpload.ts
|
|
1476
1521
|
function useAttachmentUpload() {
|
|
1477
|
-
const [uploading, setUploading] =
|
|
1478
|
-
const [error, setError] =
|
|
1479
|
-
const uploadBase64Images =
|
|
1522
|
+
const [uploading, setUploading] = React7.useState(false);
|
|
1523
|
+
const [error, setError] = React7.useState(null);
|
|
1524
|
+
const uploadBase64Images = React7.useCallback(async ({ threadId, appId, dataUrls }) => {
|
|
1480
1525
|
if (!threadId || !appId) return [];
|
|
1481
1526
|
if (!dataUrls || dataUrls.length === 0) return [];
|
|
1482
1527
|
setUploading(true);
|
|
@@ -1510,7 +1555,7 @@ function useAttachmentUpload() {
|
|
|
1510
1555
|
}
|
|
1511
1556
|
|
|
1512
1557
|
// src/studio/hooks/useStudioActions.ts
|
|
1513
|
-
import * as
|
|
1558
|
+
import * as React8 from "react";
|
|
1514
1559
|
|
|
1515
1560
|
// src/data/agent/remote.ts
|
|
1516
1561
|
var AgentRemoteDataSourceImpl = class extends BaseRemote {
|
|
@@ -1549,12 +1594,12 @@ function useStudioActions({
|
|
|
1549
1594
|
onForkedApp,
|
|
1550
1595
|
uploadAttachments
|
|
1551
1596
|
}) {
|
|
1552
|
-
const [forking, setForking] =
|
|
1553
|
-
const [sending, setSending] =
|
|
1554
|
-
const [error, setError] =
|
|
1597
|
+
const [forking, setForking] = React8.useState(false);
|
|
1598
|
+
const [sending, setSending] = React8.useState(false);
|
|
1599
|
+
const [error, setError] = React8.useState(null);
|
|
1555
1600
|
const isOwner = Boolean(userId && (app == null ? void 0 : app.createdBy) && userId === app.createdBy);
|
|
1556
1601
|
const shouldForkOnEdit = Boolean(userId && app && app.createdBy !== userId);
|
|
1557
|
-
const sendEdit =
|
|
1602
|
+
const sendEdit = React8.useCallback(
|
|
1558
1603
|
async ({ prompt, attachments }) => {
|
|
1559
1604
|
if (!userId || !app) return;
|
|
1560
1605
|
if (!prompt.trim()) return;
|
|
@@ -1636,12 +1681,12 @@ function RuntimeRenderer({ appKey, bundlePath, renderToken, style }) {
|
|
|
1636
1681
|
}
|
|
1637
1682
|
|
|
1638
1683
|
// src/studio/ui/StudioOverlay.tsx
|
|
1639
|
-
import * as
|
|
1684
|
+
import * as React38 from "react";
|
|
1640
1685
|
import { Keyboard as Keyboard5, Platform as Platform7, View as View44, useWindowDimensions as useWindowDimensions4 } from "react-native";
|
|
1641
1686
|
|
|
1642
1687
|
// src/components/studio-sheet/StudioBottomSheet.tsx
|
|
1643
|
-
import * as
|
|
1644
|
-
import { Keyboard, Platform as Platform2, View as View4 } from "react-native";
|
|
1688
|
+
import * as React9 from "react";
|
|
1689
|
+
import { AppState as AppState2, Keyboard, Platform as Platform2, View as View4 } from "react-native";
|
|
1645
1690
|
import BottomSheet from "@gorhom/bottom-sheet";
|
|
1646
1691
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
1647
1692
|
|
|
@@ -1708,19 +1753,43 @@ function StudioBottomSheet({
|
|
|
1708
1753
|
}) {
|
|
1709
1754
|
const theme = useTheme();
|
|
1710
1755
|
const insets = useSafeAreaInsets();
|
|
1711
|
-
const internalSheetRef =
|
|
1756
|
+
const internalSheetRef = React9.useRef(null);
|
|
1712
1757
|
const resolvedSheetRef = sheetRef ?? internalSheetRef;
|
|
1713
|
-
|
|
1758
|
+
const currentIndexRef = React9.useRef(open ? snapPoints.length - 1 : -1);
|
|
1759
|
+
const lastAppStateRef = React9.useRef(AppState2.currentState);
|
|
1760
|
+
React9.useEffect(() => {
|
|
1761
|
+
const sub = AppState2.addEventListener("change", (state) => {
|
|
1762
|
+
const prev = lastAppStateRef.current;
|
|
1763
|
+
lastAppStateRef.current = state;
|
|
1764
|
+
if (state === "background" || state === "inactive") {
|
|
1765
|
+
Keyboard.dismiss();
|
|
1766
|
+
return;
|
|
1767
|
+
}
|
|
1768
|
+
if (state !== "active") return;
|
|
1769
|
+
const sheet = resolvedSheetRef.current;
|
|
1770
|
+
if (!sheet) return;
|
|
1771
|
+
const idx = currentIndexRef.current;
|
|
1772
|
+
if (open && idx >= 0) {
|
|
1773
|
+
Keyboard.dismiss();
|
|
1774
|
+
requestAnimationFrame(() => sheet.snapToIndex(idx));
|
|
1775
|
+
setTimeout(() => sheet.snapToIndex(idx), 120);
|
|
1776
|
+
}
|
|
1777
|
+
});
|
|
1778
|
+
return () => sub.remove();
|
|
1779
|
+
}, [open, resolvedSheetRef]);
|
|
1780
|
+
React9.useEffect(() => {
|
|
1714
1781
|
if (Platform2.OS !== "ios") return;
|
|
1715
1782
|
const sub = Keyboard.addListener("keyboardDidHide", () => {
|
|
1716
1783
|
const sheet = resolvedSheetRef.current;
|
|
1717
1784
|
if (!sheet || !open) return;
|
|
1718
1785
|
const targetIndex = snapPoints.length - 1;
|
|
1719
|
-
|
|
1786
|
+
if (currentIndexRef.current === targetIndex) {
|
|
1787
|
+
setTimeout(() => sheet.snapToIndex(targetIndex), 10);
|
|
1788
|
+
}
|
|
1720
1789
|
});
|
|
1721
1790
|
return () => sub.remove();
|
|
1722
1791
|
}, [open, resolvedSheetRef, snapPoints.length]);
|
|
1723
|
-
|
|
1792
|
+
React9.useEffect(() => {
|
|
1724
1793
|
const sheet = resolvedSheetRef.current;
|
|
1725
1794
|
if (!sheet) return;
|
|
1726
1795
|
if (open) {
|
|
@@ -1729,8 +1798,9 @@ function StudioBottomSheet({
|
|
|
1729
1798
|
sheet.close();
|
|
1730
1799
|
}
|
|
1731
1800
|
}, [open, resolvedSheetRef, snapPoints.length]);
|
|
1732
|
-
const handleChange =
|
|
1801
|
+
const handleChange = React9.useCallback(
|
|
1733
1802
|
(index) => {
|
|
1803
|
+
currentIndexRef.current = index;
|
|
1734
1804
|
onOpenChange == null ? void 0 : onOpenChange(index >= 0);
|
|
1735
1805
|
},
|
|
1736
1806
|
[onOpenChange]
|
|
@@ -1742,7 +1812,7 @@ function StudioBottomSheet({
|
|
|
1742
1812
|
index: open ? snapPoints.length - 1 : -1,
|
|
1743
1813
|
snapPoints,
|
|
1744
1814
|
enablePanDownToClose: true,
|
|
1745
|
-
keyboardBehavior:
|
|
1815
|
+
keyboardBehavior: "interactive",
|
|
1746
1816
|
keyboardBlurBehavior: "restore",
|
|
1747
1817
|
android_keyboardInputMode: "adjustResize",
|
|
1748
1818
|
backgroundComponent: (props) => /* @__PURE__ */ jsx5(StudioSheetBackground, { ...props, renderBackground: background == null ? void 0 : background.renderBackground }),
|
|
@@ -1757,12 +1827,12 @@ function StudioBottomSheet({
|
|
|
1757
1827
|
}
|
|
1758
1828
|
|
|
1759
1829
|
// src/components/studio-sheet/StudioSheetPager.tsx
|
|
1760
|
-
import * as
|
|
1830
|
+
import * as React10 from "react";
|
|
1761
1831
|
import { Animated } from "react-native";
|
|
1762
1832
|
import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1763
1833
|
function StudioSheetPager({ activePage, width, preview, chat, style }) {
|
|
1764
|
-
const anim =
|
|
1765
|
-
|
|
1834
|
+
const anim = React10.useRef(new Animated.Value(activePage === "chat" ? 1 : 0)).current;
|
|
1835
|
+
React10.useEffect(() => {
|
|
1766
1836
|
Animated.spring(anim, {
|
|
1767
1837
|
toValue: activePage === "chat" ? 1 : 0,
|
|
1768
1838
|
useNativeDriver: true,
|
|
@@ -1811,7 +1881,7 @@ function StudioSheetPager({ activePage, width, preview, chat, style }) {
|
|
|
1811
1881
|
}
|
|
1812
1882
|
|
|
1813
1883
|
// src/components/floating-draggable-button/FloatingDraggableButton.tsx
|
|
1814
|
-
import { useCallback as useCallback8, useEffect as
|
|
1884
|
+
import { useCallback as useCallback8, useEffect as useEffect9, useMemo as useMemo3, useRef as useRef6 } from "react";
|
|
1815
1885
|
import {
|
|
1816
1886
|
PanResponder,
|
|
1817
1887
|
Pressable,
|
|
@@ -1890,8 +1960,8 @@ function FloatingDraggableButton({
|
|
|
1890
1960
|
const theme = useTheme();
|
|
1891
1961
|
const { width, height } = useWindowDimensions();
|
|
1892
1962
|
const isDanger = variant === "danger";
|
|
1893
|
-
const onPressRef =
|
|
1894
|
-
|
|
1963
|
+
const onPressRef = useRef6(onPress);
|
|
1964
|
+
useEffect9(() => {
|
|
1895
1965
|
onPressRef.current = onPress;
|
|
1896
1966
|
}, [onPress]);
|
|
1897
1967
|
const fallbackBgColor = useMemo3(() => {
|
|
@@ -1905,8 +1975,8 @@ function FloatingDraggableButton({
|
|
|
1905
1975
|
const rotation = useSharedValue(ENTER_ROTATION_FROM_DEG);
|
|
1906
1976
|
const opacity = useSharedValue(1);
|
|
1907
1977
|
const borderPulse = useSharedValue(0);
|
|
1908
|
-
const startPos =
|
|
1909
|
-
const isAnimatingOut =
|
|
1978
|
+
const startPos = useRef6({ x: 0, y: 0 });
|
|
1979
|
+
const isAnimatingOut = useRef6(false);
|
|
1910
1980
|
const animateToHidden = useCallback8(
|
|
1911
1981
|
(options) => {
|
|
1912
1982
|
translateX.value = withSpring(getHiddenTranslateX(size), SPRING_POSITION);
|
|
@@ -1942,7 +2012,7 @@ function FloatingDraggableButton({
|
|
|
1942
2012
|
}
|
|
1943
2013
|
});
|
|
1944
2014
|
}, [animateToHidden]);
|
|
1945
|
-
|
|
2015
|
+
useEffect9(() => {
|
|
1946
2016
|
if (isLoading) {
|
|
1947
2017
|
borderPulse.value = withRepeat(
|
|
1948
2018
|
withSequence(
|
|
@@ -1968,7 +2038,7 @@ function FloatingDraggableButton({
|
|
|
1968
2038
|
rotation.value = withSpring(0, SPRING_ROTATION_IN);
|
|
1969
2039
|
opacity.value = withTiming(1, TIMING_OPACITY_IN);
|
|
1970
2040
|
}, [height, offset.bottom, offset.left, opacity, rotation, scale, size, translateX, translateY]);
|
|
1971
|
-
|
|
2041
|
+
useEffect9(() => {
|
|
1972
2042
|
const timer = setTimeout(() => {
|
|
1973
2043
|
if (visible) {
|
|
1974
2044
|
animateIn();
|
|
@@ -1976,7 +2046,7 @@ function FloatingDraggableButton({
|
|
|
1976
2046
|
}, 100);
|
|
1977
2047
|
return () => clearTimeout(timer);
|
|
1978
2048
|
}, []);
|
|
1979
|
-
|
|
2049
|
+
useEffect9(() => {
|
|
1980
2050
|
if (visible && isAnimatingOut.current) {
|
|
1981
2051
|
animateIn();
|
|
1982
2052
|
} else if (!visible && !isAnimatingOut.current) {
|
|
@@ -1984,13 +2054,13 @@ function FloatingDraggableButton({
|
|
|
1984
2054
|
isAnimatingOut.current = true;
|
|
1985
2055
|
}
|
|
1986
2056
|
}, [visible, animateIn, animateToHidden]);
|
|
1987
|
-
|
|
2057
|
+
useEffect9(() => {
|
|
1988
2058
|
if (forceShowTrigger > 0 && visible) {
|
|
1989
2059
|
isAnimatingOut.current = false;
|
|
1990
2060
|
animateIn();
|
|
1991
2061
|
}
|
|
1992
2062
|
}, [forceShowTrigger, visible, animateIn]);
|
|
1993
|
-
const panResponder =
|
|
2063
|
+
const panResponder = useRef6(
|
|
1994
2064
|
PanResponder.create({
|
|
1995
2065
|
onStartShouldSetPanResponder: () => true,
|
|
1996
2066
|
onMoveShouldSetPanResponder: () => true,
|
|
@@ -2107,7 +2177,7 @@ var styles = StyleSheet.create({
|
|
|
2107
2177
|
});
|
|
2108
2178
|
|
|
2109
2179
|
// src/components/overlays/EdgeGlowFrame.tsx
|
|
2110
|
-
import * as
|
|
2180
|
+
import * as React11 from "react";
|
|
2111
2181
|
import { Animated as Animated3, View as View6 } from "react-native";
|
|
2112
2182
|
import { LinearGradient } from "expo-linear-gradient";
|
|
2113
2183
|
|
|
@@ -2150,8 +2220,8 @@ function EdgeGlowFrame({
|
|
|
2150
2220
|
}) {
|
|
2151
2221
|
const theme = useTheme();
|
|
2152
2222
|
const alpha = Math.max(0, Math.min(1, intensity));
|
|
2153
|
-
const anim =
|
|
2154
|
-
|
|
2223
|
+
const anim = React11.useRef(new Animated3.Value(visible ? 1 : 0)).current;
|
|
2224
|
+
React11.useEffect(() => {
|
|
2155
2225
|
Animated3.timing(anim, {
|
|
2156
2226
|
toValue: visible ? 1 : 0,
|
|
2157
2227
|
duration: 300,
|
|
@@ -2202,12 +2272,12 @@ function EdgeGlowFrame({
|
|
|
2202
2272
|
}
|
|
2203
2273
|
|
|
2204
2274
|
// src/components/draw/DrawModeOverlay.tsx
|
|
2205
|
-
import * as
|
|
2275
|
+
import * as React14 from "react";
|
|
2206
2276
|
import { StyleSheet as StyleSheet3, View as View10 } from "react-native";
|
|
2207
2277
|
import { captureRef } from "react-native-view-shot";
|
|
2208
2278
|
|
|
2209
2279
|
// src/components/draw/DrawSurface.tsx
|
|
2210
|
-
import * as
|
|
2280
|
+
import * as React12 from "react";
|
|
2211
2281
|
import { PanResponder as PanResponder2, StyleSheet as StyleSheet2, View as View7 } from "react-native";
|
|
2212
2282
|
import Svg, { Path } from "react-native-svg";
|
|
2213
2283
|
|
|
@@ -2239,25 +2309,25 @@ function DrawSurface({
|
|
|
2239
2309
|
style,
|
|
2240
2310
|
minDistance = 1
|
|
2241
2311
|
}) {
|
|
2242
|
-
const [renderTick, setRenderTick] =
|
|
2243
|
-
const currentPointsRef =
|
|
2244
|
-
const rafRef =
|
|
2245
|
-
const triggerRender =
|
|
2312
|
+
const [renderTick, setRenderTick] = React12.useState(0);
|
|
2313
|
+
const currentPointsRef = React12.useRef([]);
|
|
2314
|
+
const rafRef = React12.useRef(null);
|
|
2315
|
+
const triggerRender = React12.useCallback(() => {
|
|
2246
2316
|
if (rafRef.current !== null) return;
|
|
2247
2317
|
rafRef.current = requestAnimationFrame(() => {
|
|
2248
2318
|
rafRef.current = null;
|
|
2249
2319
|
setRenderTick((n) => n + 1);
|
|
2250
2320
|
});
|
|
2251
2321
|
}, []);
|
|
2252
|
-
|
|
2322
|
+
React12.useEffect(() => () => {
|
|
2253
2323
|
if (rafRef.current !== null) cancelAnimationFrame(rafRef.current);
|
|
2254
2324
|
}, []);
|
|
2255
|
-
const onStart =
|
|
2325
|
+
const onStart = React12.useCallback((e) => {
|
|
2256
2326
|
const { locationX, locationY } = e.nativeEvent;
|
|
2257
2327
|
currentPointsRef.current = [{ x: locationX, y: locationY }];
|
|
2258
2328
|
triggerRender();
|
|
2259
2329
|
}, [triggerRender]);
|
|
2260
|
-
const onMove =
|
|
2330
|
+
const onMove = React12.useCallback((e, _g) => {
|
|
2261
2331
|
const { locationX, locationY } = e.nativeEvent;
|
|
2262
2332
|
const pts = currentPointsRef.current;
|
|
2263
2333
|
if (pts.length > 0) {
|
|
@@ -2270,7 +2340,7 @@ function DrawSurface({
|
|
|
2270
2340
|
currentPointsRef.current = [...pts, { x: locationX, y: locationY }];
|
|
2271
2341
|
triggerRender();
|
|
2272
2342
|
}, [minDistance, triggerRender]);
|
|
2273
|
-
const onEnd =
|
|
2343
|
+
const onEnd = React12.useCallback(() => {
|
|
2274
2344
|
const points = currentPointsRef.current;
|
|
2275
2345
|
if (points.length > 0) {
|
|
2276
2346
|
onAddStroke({ points, color, width: strokeWidth });
|
|
@@ -2278,7 +2348,7 @@ function DrawSurface({
|
|
|
2278
2348
|
currentPointsRef.current = [];
|
|
2279
2349
|
triggerRender();
|
|
2280
2350
|
}, [color, onAddStroke, strokeWidth, triggerRender]);
|
|
2281
|
-
const panResponder =
|
|
2351
|
+
const panResponder = React12.useMemo(
|
|
2282
2352
|
() => PanResponder2.create({
|
|
2283
2353
|
onStartShouldSetPanResponder: () => true,
|
|
2284
2354
|
onMoveShouldSetPanResponder: () => true,
|
|
@@ -2328,7 +2398,7 @@ var styles2 = StyleSheet2.create({
|
|
|
2328
2398
|
});
|
|
2329
2399
|
|
|
2330
2400
|
// src/components/draw/DrawToolbar.tsx
|
|
2331
|
-
import * as
|
|
2401
|
+
import * as React13 from "react";
|
|
2332
2402
|
import {
|
|
2333
2403
|
ActivityIndicator,
|
|
2334
2404
|
Animated as Animated4,
|
|
@@ -2425,11 +2495,11 @@ function DrawToolbar({
|
|
|
2425
2495
|
}) {
|
|
2426
2496
|
const insets = useSafeAreaInsets2();
|
|
2427
2497
|
const { width: screenWidth, height: screenHeight } = useWindowDimensions2();
|
|
2428
|
-
const [expanded, setExpanded] =
|
|
2429
|
-
const pos =
|
|
2430
|
-
const start =
|
|
2431
|
-
const currentPos =
|
|
2432
|
-
|
|
2498
|
+
const [expanded, setExpanded] = React13.useState(false);
|
|
2499
|
+
const pos = React13.useRef(new Animated4.ValueXY({ x: screenWidth / 2 - 110, y: -140 })).current;
|
|
2500
|
+
const start = React13.useRef({ x: 0, y: 0 });
|
|
2501
|
+
const currentPos = React13.useRef({ x: 0, y: 0 });
|
|
2502
|
+
React13.useEffect(() => {
|
|
2433
2503
|
if (hidden) return;
|
|
2434
2504
|
Animated4.spring(pos.y, {
|
|
2435
2505
|
toValue: insets.top + 60,
|
|
@@ -2439,7 +2509,7 @@ function DrawToolbar({
|
|
|
2439
2509
|
mass: 0.8
|
|
2440
2510
|
}).start();
|
|
2441
2511
|
}, [hidden, insets.top, pos.y]);
|
|
2442
|
-
|
|
2512
|
+
React13.useEffect(() => {
|
|
2443
2513
|
const id = pos.addListener((v) => {
|
|
2444
2514
|
currentPos.current = { x: v.x ?? 0, y: v.y ?? 0 };
|
|
2445
2515
|
});
|
|
@@ -2447,7 +2517,7 @@ function DrawToolbar({
|
|
|
2447
2517
|
pos.removeListener(id);
|
|
2448
2518
|
};
|
|
2449
2519
|
}, [pos]);
|
|
2450
|
-
const clamp2 =
|
|
2520
|
+
const clamp2 = React13.useCallback(
|
|
2451
2521
|
(x, y) => {
|
|
2452
2522
|
const minX = 10;
|
|
2453
2523
|
const maxX = Math.max(10, screenWidth - 230);
|
|
@@ -2457,7 +2527,7 @@ function DrawToolbar({
|
|
|
2457
2527
|
},
|
|
2458
2528
|
[insets.top, screenHeight, screenWidth]
|
|
2459
2529
|
);
|
|
2460
|
-
const panResponder =
|
|
2530
|
+
const panResponder = React13.useMemo(
|
|
2461
2531
|
() => PanResponder3.create({
|
|
2462
2532
|
onStartShouldSetPanResponder: () => false,
|
|
2463
2533
|
onMoveShouldSetPanResponder: (_e, g) => Math.abs(g.dx) > 5 || Math.abs(g.dy) > 5,
|
|
@@ -2485,7 +2555,7 @@ function DrawToolbar({
|
|
|
2485
2555
|
children
|
|
2486
2556
|
}) {
|
|
2487
2557
|
const isDisabled = Boolean(disabled) || Boolean(capturingDisabled);
|
|
2488
|
-
const [pressed, setPressed] =
|
|
2558
|
+
const [pressed, setPressed] = React13.useState(false);
|
|
2489
2559
|
return /* @__PURE__ */ jsx11(
|
|
2490
2560
|
View9,
|
|
2491
2561
|
{
|
|
@@ -2623,7 +2693,7 @@ function DrawModeOverlay({
|
|
|
2623
2693
|
renderDragHandle
|
|
2624
2694
|
}) {
|
|
2625
2695
|
const theme = useTheme();
|
|
2626
|
-
const defaultPalette =
|
|
2696
|
+
const defaultPalette = React14.useMemo(
|
|
2627
2697
|
() => [
|
|
2628
2698
|
"#EF4444",
|
|
2629
2699
|
// Red
|
|
@@ -2641,11 +2711,11 @@ function DrawModeOverlay({
|
|
|
2641
2711
|
[]
|
|
2642
2712
|
);
|
|
2643
2713
|
const colors = palette && palette.length > 0 ? palette : defaultPalette;
|
|
2644
|
-
const [selectedColor, setSelectedColor] =
|
|
2645
|
-
const [strokes, setStrokes] =
|
|
2646
|
-
const [capturing, setCapturing] =
|
|
2647
|
-
const [hideUi, setHideUi] =
|
|
2648
|
-
|
|
2714
|
+
const [selectedColor, setSelectedColor] = React14.useState(colors[0] ?? "#EF4444");
|
|
2715
|
+
const [strokes, setStrokes] = React14.useState([]);
|
|
2716
|
+
const [capturing, setCapturing] = React14.useState(false);
|
|
2717
|
+
const [hideUi, setHideUi] = React14.useState(false);
|
|
2718
|
+
React14.useEffect(() => {
|
|
2649
2719
|
if (!visible) return;
|
|
2650
2720
|
setStrokes([]);
|
|
2651
2721
|
setSelectedColor(colors[0] ?? "#EF4444");
|
|
@@ -2653,14 +2723,14 @@ function DrawModeOverlay({
|
|
|
2653
2723
|
setHideUi(false);
|
|
2654
2724
|
}, [colors, visible]);
|
|
2655
2725
|
const canUndo = strokes.length > 0;
|
|
2656
|
-
const handleUndo =
|
|
2726
|
+
const handleUndo = React14.useCallback(() => {
|
|
2657
2727
|
setStrokes((prev) => prev.slice(0, -1));
|
|
2658
2728
|
}, []);
|
|
2659
|
-
const handleCancel =
|
|
2729
|
+
const handleCancel = React14.useCallback(() => {
|
|
2660
2730
|
setStrokes([]);
|
|
2661
2731
|
onCancel();
|
|
2662
2732
|
}, [onCancel]);
|
|
2663
|
-
const handleDone =
|
|
2733
|
+
const handleDone = React14.useCallback(async () => {
|
|
2664
2734
|
if (!captureTargetRef.current || capturing) return;
|
|
2665
2735
|
try {
|
|
2666
2736
|
setCapturing(true);
|
|
@@ -2720,7 +2790,7 @@ var styles3 = StyleSheet3.create({
|
|
|
2720
2790
|
});
|
|
2721
2791
|
|
|
2722
2792
|
// src/components/comments/AppCommentsSheet.tsx
|
|
2723
|
-
import * as
|
|
2793
|
+
import * as React21 from "react";
|
|
2724
2794
|
import { ActivityIndicator as ActivityIndicator3, Keyboard as Keyboard3, Platform as Platform4, Pressable as Pressable5, View as View14 } from "react-native";
|
|
2725
2795
|
import {
|
|
2726
2796
|
BottomSheetBackdrop,
|
|
@@ -2732,7 +2802,7 @@ import { LiquidGlassView as LiquidGlassView4, isLiquidGlassSupported as isLiquid
|
|
|
2732
2802
|
import { Play as Play2 } from "lucide-react-native";
|
|
2733
2803
|
|
|
2734
2804
|
// src/components/chat/ChatComposer.tsx
|
|
2735
|
-
import * as
|
|
2805
|
+
import * as React16 from "react";
|
|
2736
2806
|
import {
|
|
2737
2807
|
ActivityIndicator as ActivityIndicator2,
|
|
2738
2808
|
Animated as Animated5,
|
|
@@ -2746,11 +2816,11 @@ import { LiquidGlassView as LiquidGlassView3, isLiquidGlassSupported as isLiquid
|
|
|
2746
2816
|
import { Plus } from "lucide-react-native";
|
|
2747
2817
|
|
|
2748
2818
|
// src/components/chat/MultilineTextInput.tsx
|
|
2749
|
-
import * as
|
|
2819
|
+
import * as React15 from "react";
|
|
2750
2820
|
import { TextInput } from "react-native";
|
|
2751
2821
|
import { BottomSheetTextInput } from "@gorhom/bottom-sheet";
|
|
2752
2822
|
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
2753
|
-
var MultilineTextInput =
|
|
2823
|
+
var MultilineTextInput = React15.forwardRef(function MultilineTextInput2({ useBottomSheetTextInput = false, placeholder, placeholderTextColor, style, ...props }, ref) {
|
|
2754
2824
|
const theme = useTheme();
|
|
2755
2825
|
const baseStyle = {
|
|
2756
2826
|
minHeight: 44,
|
|
@@ -2834,7 +2904,7 @@ function AspectRatioThumbnail({
|
|
|
2834
2904
|
onRemove,
|
|
2835
2905
|
renderRemoveIcon
|
|
2836
2906
|
}) {
|
|
2837
|
-
const [aspectRatio, setAspectRatio] =
|
|
2907
|
+
const [aspectRatio, setAspectRatio] = React16.useState(1);
|
|
2838
2908
|
return /* @__PURE__ */ jsxs8(View11, { style: { height: THUMBNAIL_HEIGHT, aspectRatio, position: "relative" }, children: [
|
|
2839
2909
|
/* @__PURE__ */ jsx15(View11, { style: { flex: 1, borderRadius: 8, overflow: "hidden" }, children: /* @__PURE__ */ jsx15(
|
|
2840
2910
|
Image,
|
|
@@ -2876,6 +2946,7 @@ function ChatComposer({
|
|
|
2876
2946
|
onChangeValue,
|
|
2877
2947
|
placeholder = "Describe the idea you want to build",
|
|
2878
2948
|
disabled = false,
|
|
2949
|
+
sendDisabled = false,
|
|
2879
2950
|
sending = false,
|
|
2880
2951
|
autoFocus = false,
|
|
2881
2952
|
onSend,
|
|
@@ -2890,19 +2961,19 @@ function ChatComposer({
|
|
|
2890
2961
|
style
|
|
2891
2962
|
}) {
|
|
2892
2963
|
const theme = useTheme();
|
|
2893
|
-
const [internal, setInternal] =
|
|
2964
|
+
const [internal, setInternal] = React16.useState("");
|
|
2894
2965
|
const text = value ?? internal;
|
|
2895
2966
|
const setText = onChangeValue ?? setInternal;
|
|
2896
2967
|
const hasAttachments = attachments.length > 0;
|
|
2897
2968
|
const hasText = text.trim().length > 0;
|
|
2898
2969
|
const composerMinHeight = hasAttachments ? THUMBNAIL_HEIGHT + 44 + 24 : 44;
|
|
2899
|
-
const isButtonDisabled = sending || disabled;
|
|
2900
|
-
const maxInputHeight =
|
|
2901
|
-
const shakeAnim =
|
|
2902
|
-
const [sendPressed, setSendPressed] =
|
|
2903
|
-
const inputRef =
|
|
2904
|
-
const prevAutoFocusRef =
|
|
2905
|
-
|
|
2970
|
+
const isButtonDisabled = sending || disabled || sendDisabled;
|
|
2971
|
+
const maxInputHeight = React16.useMemo(() => Dimensions.get("window").height * 0.5, []);
|
|
2972
|
+
const shakeAnim = React16.useRef(new Animated5.Value(0)).current;
|
|
2973
|
+
const [sendPressed, setSendPressed] = React16.useState(false);
|
|
2974
|
+
const inputRef = React16.useRef(null);
|
|
2975
|
+
const prevAutoFocusRef = React16.useRef(false);
|
|
2976
|
+
React16.useEffect(() => {
|
|
2906
2977
|
const shouldFocus = autoFocus && !prevAutoFocusRef.current && !disabled && !sending;
|
|
2907
2978
|
prevAutoFocusRef.current = autoFocus;
|
|
2908
2979
|
if (!shouldFocus) return;
|
|
@@ -2912,7 +2983,7 @@ function ChatComposer({
|
|
|
2912
2983
|
}, 75);
|
|
2913
2984
|
return () => clearTimeout(t);
|
|
2914
2985
|
}, [autoFocus, disabled, sending]);
|
|
2915
|
-
const triggerShake =
|
|
2986
|
+
const triggerShake = React16.useCallback(() => {
|
|
2916
2987
|
shakeAnim.setValue(0);
|
|
2917
2988
|
Animated5.sequence([
|
|
2918
2989
|
Animated5.timing(shakeAnim, { toValue: 10, duration: 50, useNativeDriver: true }),
|
|
@@ -2922,7 +2993,7 @@ function ChatComposer({
|
|
|
2922
2993
|
Animated5.timing(shakeAnim, { toValue: 0, duration: 50, useNativeDriver: true })
|
|
2923
2994
|
]).start();
|
|
2924
2995
|
}, [shakeAnim]);
|
|
2925
|
-
const handleSend =
|
|
2996
|
+
const handleSend = React16.useCallback(async () => {
|
|
2926
2997
|
if (isButtonDisabled) return;
|
|
2927
2998
|
if (!hasText) {
|
|
2928
2999
|
triggerShake();
|
|
@@ -3055,7 +3126,7 @@ function ChatComposer({
|
|
|
3055
3126
|
}
|
|
3056
3127
|
|
|
3057
3128
|
// src/components/comments/CommentRow.tsx
|
|
3058
|
-
import * as
|
|
3129
|
+
import * as React17 from "react";
|
|
3059
3130
|
import { View as View13 } from "react-native";
|
|
3060
3131
|
|
|
3061
3132
|
// src/components/primitives/Avatar.tsx
|
|
@@ -3127,9 +3198,9 @@ function formatTimeAgo(iso) {
|
|
|
3127
3198
|
import { jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3128
3199
|
function CommentRow({ comment, showDivider }) {
|
|
3129
3200
|
const theme = useTheme();
|
|
3130
|
-
const [authorName, setAuthorName] =
|
|
3131
|
-
const [authorAvatar, setAuthorAvatar] =
|
|
3132
|
-
|
|
3201
|
+
const [authorName, setAuthorName] = React17.useState(null);
|
|
3202
|
+
const [authorAvatar, setAuthorAvatar] = React17.useState(null);
|
|
3203
|
+
React17.useEffect(() => {
|
|
3133
3204
|
let cancelled = false;
|
|
3134
3205
|
(async () => {
|
|
3135
3206
|
try {
|
|
@@ -3169,7 +3240,7 @@ function CommentRow({ comment, showDivider }) {
|
|
|
3169
3240
|
}
|
|
3170
3241
|
|
|
3171
3242
|
// src/components/comments/useAppComments.ts
|
|
3172
|
-
import * as
|
|
3243
|
+
import * as React18 from "react";
|
|
3173
3244
|
|
|
3174
3245
|
// src/data/comments/remote.ts
|
|
3175
3246
|
var AppCommentsRemoteDataSourceImpl = class extends BaseRemote {
|
|
@@ -3241,18 +3312,18 @@ var appCommentsRepository = new AppCommentsRepositoryImpl(appCommentsRemoteDataS
|
|
|
3241
3312
|
|
|
3242
3313
|
// src/components/comments/useAppComments.ts
|
|
3243
3314
|
function useAppComments(appId) {
|
|
3244
|
-
const [comments, setComments] =
|
|
3245
|
-
const [loading, setLoading] =
|
|
3246
|
-
const [sending, setSending] =
|
|
3247
|
-
const [error, setError] =
|
|
3248
|
-
const sortByCreatedAtAsc =
|
|
3315
|
+
const [comments, setComments] = React18.useState([]);
|
|
3316
|
+
const [loading, setLoading] = React18.useState(false);
|
|
3317
|
+
const [sending, setSending] = React18.useState(false);
|
|
3318
|
+
const [error, setError] = React18.useState(null);
|
|
3319
|
+
const sortByCreatedAtAsc = React18.useCallback((items) => {
|
|
3249
3320
|
return [...items].sort((a, b) => {
|
|
3250
3321
|
const at = a.createdAt ? new Date(a.createdAt).getTime() : 0;
|
|
3251
3322
|
const bt = b.createdAt ? new Date(b.createdAt).getTime() : 0;
|
|
3252
3323
|
return at - bt;
|
|
3253
3324
|
});
|
|
3254
3325
|
}, []);
|
|
3255
|
-
const refresh =
|
|
3326
|
+
const refresh = React18.useCallback(async () => {
|
|
3256
3327
|
if (!appId) {
|
|
3257
3328
|
setComments([]);
|
|
3258
3329
|
return;
|
|
@@ -3269,10 +3340,10 @@ function useAppComments(appId) {
|
|
|
3269
3340
|
setLoading(false);
|
|
3270
3341
|
}
|
|
3271
3342
|
}, [appId, sortByCreatedAtAsc]);
|
|
3272
|
-
|
|
3343
|
+
React18.useEffect(() => {
|
|
3273
3344
|
void refresh();
|
|
3274
3345
|
}, [refresh]);
|
|
3275
|
-
const create =
|
|
3346
|
+
const create = React18.useCallback(
|
|
3276
3347
|
async (text) => {
|
|
3277
3348
|
if (!appId) return;
|
|
3278
3349
|
const trimmed = text.trim();
|
|
@@ -3295,11 +3366,11 @@ function useAppComments(appId) {
|
|
|
3295
3366
|
}
|
|
3296
3367
|
|
|
3297
3368
|
// src/components/comments/useAppDetails.ts
|
|
3298
|
-
import * as
|
|
3369
|
+
import * as React19 from "react";
|
|
3299
3370
|
function useAppDetails(appId) {
|
|
3300
|
-
const [app, setApp] =
|
|
3301
|
-
const [loading, setLoading] =
|
|
3302
|
-
|
|
3371
|
+
const [app, setApp] = React19.useState(null);
|
|
3372
|
+
const [loading, setLoading] = React19.useState(false);
|
|
3373
|
+
React19.useEffect(() => {
|
|
3303
3374
|
if (!appId) {
|
|
3304
3375
|
setApp(null);
|
|
3305
3376
|
return;
|
|
@@ -3324,25 +3395,30 @@ function useAppDetails(appId) {
|
|
|
3324
3395
|
}
|
|
3325
3396
|
|
|
3326
3397
|
// src/components/comments/useIosKeyboardSnapFix.ts
|
|
3327
|
-
import * as
|
|
3398
|
+
import * as React20 from "react";
|
|
3328
3399
|
import { Keyboard as Keyboard2, Platform as Platform3 } from "react-native";
|
|
3329
|
-
function useIosKeyboardSnapFix(sheetRef) {
|
|
3330
|
-
const [keyboardVisible, setKeyboardVisible] =
|
|
3331
|
-
|
|
3400
|
+
function useIosKeyboardSnapFix(sheetRef, options) {
|
|
3401
|
+
const [keyboardVisible, setKeyboardVisible] = React20.useState(false);
|
|
3402
|
+
React20.useEffect(() => {
|
|
3332
3403
|
if (Platform3.OS !== "ios") return;
|
|
3333
3404
|
const show = Keyboard2.addListener("keyboardWillShow", () => setKeyboardVisible(true));
|
|
3334
3405
|
const hide = Keyboard2.addListener("keyboardWillHide", () => {
|
|
3406
|
+
var _a;
|
|
3335
3407
|
setKeyboardVisible(false);
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3408
|
+
const target = (options == null ? void 0 : options.targetIndex) ?? 1;
|
|
3409
|
+
const current = ((_a = options == null ? void 0 : options.getCurrentIndex) == null ? void 0 : _a.call(options)) ?? null;
|
|
3410
|
+
if (current === target) {
|
|
3411
|
+
setTimeout(() => {
|
|
3412
|
+
var _a2, _b;
|
|
3413
|
+
return (_b = (_a2 = sheetRef.current) == null ? void 0 : _a2.snapToIndex) == null ? void 0 : _b.call(_a2, target);
|
|
3414
|
+
}, 10);
|
|
3415
|
+
}
|
|
3340
3416
|
});
|
|
3341
3417
|
return () => {
|
|
3342
3418
|
show.remove();
|
|
3343
3419
|
hide.remove();
|
|
3344
3420
|
};
|
|
3345
|
-
}, [sheetRef]);
|
|
3421
|
+
}, [options == null ? void 0 : options.getCurrentIndex, options == null ? void 0 : options.targetIndex, sheetRef]);
|
|
3346
3422
|
return { keyboardVisible };
|
|
3347
3423
|
}
|
|
3348
3424
|
|
|
@@ -3351,12 +3427,16 @@ import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
|
3351
3427
|
function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
3352
3428
|
const theme = useTheme();
|
|
3353
3429
|
const insets = useSafeAreaInsets3();
|
|
3354
|
-
const sheetRef =
|
|
3355
|
-
const snapPoints =
|
|
3430
|
+
const sheetRef = React21.useRef(null);
|
|
3431
|
+
const snapPoints = React21.useMemo(() => ["50%", "90%"], []);
|
|
3432
|
+
const currentIndexRef = React21.useRef(1);
|
|
3356
3433
|
const { comments, loading, sending, error, create, refresh } = useAppComments(appId);
|
|
3357
3434
|
const { app, loading: loadingApp } = useAppDetails(appId);
|
|
3358
|
-
const { keyboardVisible } = useIosKeyboardSnapFix(sheetRef
|
|
3359
|
-
|
|
3435
|
+
const { keyboardVisible } = useIosKeyboardSnapFix(sheetRef, {
|
|
3436
|
+
getCurrentIndex: () => currentIndexRef.current,
|
|
3437
|
+
targetIndex: 1
|
|
3438
|
+
});
|
|
3439
|
+
React21.useEffect(() => {
|
|
3360
3440
|
var _a, _b;
|
|
3361
3441
|
if (appId) {
|
|
3362
3442
|
(_a = sheetRef.current) == null ? void 0 : _a.present();
|
|
@@ -3365,21 +3445,22 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
3365
3445
|
(_b = sheetRef.current) == null ? void 0 : _b.dismiss();
|
|
3366
3446
|
}
|
|
3367
3447
|
}, [appId, refresh]);
|
|
3368
|
-
|
|
3448
|
+
React21.useEffect(() => {
|
|
3369
3449
|
if (!appId) return;
|
|
3370
3450
|
onCountChange == null ? void 0 : onCountChange(comments.length);
|
|
3371
3451
|
}, [appId, comments.length, onCountChange]);
|
|
3372
|
-
const renderBackdrop =
|
|
3452
|
+
const renderBackdrop = React21.useCallback(
|
|
3373
3453
|
(props) => /* @__PURE__ */ jsx18(BottomSheetBackdrop, { ...props, disappearsOnIndex: -1, appearsOnIndex: 0, opacity: 0.5 }),
|
|
3374
3454
|
[]
|
|
3375
3455
|
);
|
|
3376
|
-
const handleChange =
|
|
3456
|
+
const handleChange = React21.useCallback(
|
|
3377
3457
|
(index) => {
|
|
3458
|
+
currentIndexRef.current = index;
|
|
3378
3459
|
if (index === -1) onClose();
|
|
3379
3460
|
},
|
|
3380
3461
|
[onClose]
|
|
3381
3462
|
);
|
|
3382
|
-
const handlePlay =
|
|
3463
|
+
const handlePlay = React21.useCallback(async () => {
|
|
3383
3464
|
var _a;
|
|
3384
3465
|
if (!appId) return;
|
|
3385
3466
|
(_a = sheetRef.current) == null ? void 0 : _a.dismiss();
|
|
@@ -3590,7 +3671,7 @@ function StudioSheetHeader({ left, center, right, style }) {
|
|
|
3590
3671
|
}
|
|
3591
3672
|
|
|
3592
3673
|
// src/components/studio-sheet/StudioSheetHeaderIconButton.tsx
|
|
3593
|
-
import * as
|
|
3674
|
+
import * as React22 from "react";
|
|
3594
3675
|
import { Pressable as Pressable6, View as View17 } from "react-native";
|
|
3595
3676
|
import { LiquidGlassView as LiquidGlassView5, isLiquidGlassSupported as isLiquidGlassSupported5 } from "@callstack/liquid-glass";
|
|
3596
3677
|
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
@@ -3605,7 +3686,7 @@ function StudioSheetHeaderIconButton({
|
|
|
3605
3686
|
}) {
|
|
3606
3687
|
const theme = useTheme();
|
|
3607
3688
|
const size = 44;
|
|
3608
|
-
const [pressed, setPressed] =
|
|
3689
|
+
const [pressed, setPressed] = React22.useState(false);
|
|
3609
3690
|
const solidBg = intent === "danger" ? theme.colors.danger : intent === "primary" ? theme.colors.primary : theme.colors.neutral;
|
|
3610
3691
|
const glassFallbackBg = theme.scheme === "dark" ? "#18181B" : "#F6F6F6";
|
|
3611
3692
|
const glassInnerBg = intent === "danger" ? theme.colors.danger : theme.colors.primary;
|
|
@@ -3795,14 +3876,14 @@ function PreviewHeroCard({
|
|
|
3795
3876
|
}
|
|
3796
3877
|
|
|
3797
3878
|
// src/components/preview/PreviewPlaceholder.tsx
|
|
3798
|
-
import * as
|
|
3879
|
+
import * as React23 from "react";
|
|
3799
3880
|
import { Animated as Animated6 } from "react-native";
|
|
3800
3881
|
import { LinearGradient as LinearGradient2 } from "expo-linear-gradient";
|
|
3801
3882
|
import { Fragment as Fragment3, jsx as jsx26, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3802
3883
|
function PreviewPlaceholder({ visible, style }) {
|
|
3803
3884
|
if (!visible) return null;
|
|
3804
|
-
const opacityAnim =
|
|
3805
|
-
|
|
3885
|
+
const opacityAnim = React23.useRef(new Animated6.Value(0)).current;
|
|
3886
|
+
React23.useEffect(() => {
|
|
3806
3887
|
if (!visible) return;
|
|
3807
3888
|
const animation = Animated6.loop(
|
|
3808
3889
|
Animated6.sequence([
|
|
@@ -4394,12 +4475,12 @@ function PreviewCustomizeSection({
|
|
|
4394
4475
|
}
|
|
4395
4476
|
|
|
4396
4477
|
// src/studio/ui/preview-panel/PreviewCollaborateSection.tsx
|
|
4397
|
-
import * as
|
|
4478
|
+
import * as React29 from "react";
|
|
4398
4479
|
import { ActivityIndicator as ActivityIndicator6, Alert, View as View32 } from "react-native";
|
|
4399
4480
|
import { Send as Send2 } from "lucide-react-native";
|
|
4400
4481
|
|
|
4401
4482
|
// src/components/merge-requests/MergeRequestStatusCard.tsx
|
|
4402
|
-
import * as
|
|
4483
|
+
import * as React25 from "react";
|
|
4403
4484
|
import { Animated as Animated7, Pressable as Pressable9, View as View28 } from "react-native";
|
|
4404
4485
|
import { Ban, Check as Check3, CheckCheck, ChevronDown as ChevronDown2 } from "lucide-react-native";
|
|
4405
4486
|
|
|
@@ -4481,11 +4562,11 @@ function toIsoString(input) {
|
|
|
4481
4562
|
}
|
|
4482
4563
|
|
|
4483
4564
|
// src/components/merge-requests/useControlledExpansion.ts
|
|
4484
|
-
import * as
|
|
4565
|
+
import * as React24 from "react";
|
|
4485
4566
|
function useControlledExpansion(props) {
|
|
4486
|
-
const [uncontrolled, setUncontrolled] =
|
|
4567
|
+
const [uncontrolled, setUncontrolled] = React24.useState(false);
|
|
4487
4568
|
const expanded = props.expanded ?? uncontrolled;
|
|
4488
|
-
const setExpanded =
|
|
4569
|
+
const setExpanded = React24.useCallback(
|
|
4489
4570
|
(next) => {
|
|
4490
4571
|
var _a;
|
|
4491
4572
|
(_a = props.onExpandedChange) == null ? void 0 : _a.call(props, next);
|
|
@@ -4510,8 +4591,8 @@ function MergeRequestStatusCard({
|
|
|
4510
4591
|
const isDark = theme.scheme === "dark";
|
|
4511
4592
|
const textColor = isDark ? "#FFFFFF" : "#000000";
|
|
4512
4593
|
const subTextColor = isDark ? "#A1A1AA" : "#71717A";
|
|
4513
|
-
const status =
|
|
4514
|
-
const { StatusIcon, iconColor, bgColor, statusText } =
|
|
4594
|
+
const status = React25.useMemo(() => getMergeRequestStatusDisplay(String(mergeRequest.status)), [mergeRequest.status]);
|
|
4595
|
+
const { StatusIcon, iconColor, bgColor, statusText } = React25.useMemo(() => {
|
|
4515
4596
|
switch (mergeRequest.status) {
|
|
4516
4597
|
case "approved":
|
|
4517
4598
|
case "merged":
|
|
@@ -4542,8 +4623,8 @@ function MergeRequestStatusCard({
|
|
|
4542
4623
|
const createdIso = toIsoString(mergeRequest.createdAt ?? null);
|
|
4543
4624
|
const headerTimeAgo = updatedIso ? formatTimeAgo(updatedIso) : "";
|
|
4544
4625
|
const createdTimeAgo = createdIso ? formatTimeAgo(createdIso) : "";
|
|
4545
|
-
const rotate =
|
|
4546
|
-
|
|
4626
|
+
const rotate = React25.useRef(new Animated7.Value(expanded ? 1 : 0)).current;
|
|
4627
|
+
React25.useEffect(() => {
|
|
4547
4628
|
Animated7.timing(rotate, {
|
|
4548
4629
|
toValue: expanded ? 1 : 0,
|
|
4549
4630
|
duration: 200,
|
|
@@ -4634,16 +4715,16 @@ function MergeRequestStatusCard({
|
|
|
4634
4715
|
}
|
|
4635
4716
|
|
|
4636
4717
|
// src/components/merge-requests/ReviewMergeRequestCarousel.tsx
|
|
4637
|
-
import * as
|
|
4718
|
+
import * as React28 from "react";
|
|
4638
4719
|
import { Animated as Animated9, FlatList, View as View31, useWindowDimensions as useWindowDimensions3 } from "react-native";
|
|
4639
4720
|
|
|
4640
4721
|
// src/components/merge-requests/ReviewMergeRequestCard.tsx
|
|
4641
|
-
import * as
|
|
4722
|
+
import * as React27 from "react";
|
|
4642
4723
|
import { ActivityIndicator as ActivityIndicator5, Animated as Animated8, Pressable as Pressable11, View as View30 } from "react-native";
|
|
4643
4724
|
import { Check as Check4, ChevronDown as ChevronDown3, Play as Play3, X as X3 } from "lucide-react-native";
|
|
4644
4725
|
|
|
4645
4726
|
// src/components/merge-requests/ReviewMergeRequestActionButton.tsx
|
|
4646
|
-
import * as
|
|
4727
|
+
import * as React26 from "react";
|
|
4647
4728
|
import { Pressable as Pressable10, View as View29 } from "react-native";
|
|
4648
4729
|
import { jsx as jsx39 } from "react/jsx-runtime";
|
|
4649
4730
|
function ReviewMergeRequestActionButton({
|
|
@@ -4654,7 +4735,7 @@ function ReviewMergeRequestActionButton({
|
|
|
4654
4735
|
children,
|
|
4655
4736
|
iconOnly
|
|
4656
4737
|
}) {
|
|
4657
|
-
const [pressed, setPressed] =
|
|
4738
|
+
const [pressed, setPressed] = React26.useState(false);
|
|
4658
4739
|
const height = iconOnly ? 36 : 40;
|
|
4659
4740
|
const width = iconOnly ? 36 : void 0;
|
|
4660
4741
|
const paddingHorizontal = iconOnly ? 0 : 16;
|
|
@@ -4716,10 +4797,10 @@ function ReviewMergeRequestCard({
|
|
|
4716
4797
|
onTest
|
|
4717
4798
|
}) {
|
|
4718
4799
|
const theme = useTheme();
|
|
4719
|
-
const status =
|
|
4800
|
+
const status = React27.useMemo(() => getMergeRequestStatusDisplay(mr.status), [mr.status]);
|
|
4720
4801
|
const canAct = mr.status === "open";
|
|
4721
|
-
const rotate =
|
|
4722
|
-
|
|
4802
|
+
const rotate = React27.useRef(new Animated8.Value(isExpanded ? 1 : 0)).current;
|
|
4803
|
+
React27.useEffect(() => {
|
|
4723
4804
|
Animated8.timing(rotate, { toValue: isExpanded ? 1 : 0, duration: 200, useNativeDriver: true }).start();
|
|
4724
4805
|
}, [isExpanded, rotate]);
|
|
4725
4806
|
const position = total > 1 ? `${index + 1}/${total}` : "Merge request";
|
|
@@ -4851,11 +4932,11 @@ function ReviewMergeRequestCarousel({
|
|
|
4851
4932
|
}) {
|
|
4852
4933
|
const theme = useTheme();
|
|
4853
4934
|
const { width } = useWindowDimensions3();
|
|
4854
|
-
const [expanded, setExpanded] =
|
|
4855
|
-
const carouselScrollX =
|
|
4935
|
+
const [expanded, setExpanded] = React28.useState({});
|
|
4936
|
+
const carouselScrollX = React28.useRef(new Animated9.Value(0)).current;
|
|
4856
4937
|
const peekAmount = 24;
|
|
4857
4938
|
const gap = 16;
|
|
4858
|
-
const cardWidth =
|
|
4939
|
+
const cardWidth = React28.useMemo(() => Math.max(1, width - theme.spacing.lg * 2 - peekAmount), [peekAmount, theme.spacing.lg, width]);
|
|
4859
4940
|
const snapInterval = cardWidth + gap;
|
|
4860
4941
|
const dotColor = theme.scheme === "dark" ? "#FFFFFF" : "#000000";
|
|
4861
4942
|
if (mergeRequests.length === 0) return null;
|
|
@@ -4954,7 +5035,7 @@ function PreviewCollaborateSection({
|
|
|
4954
5035
|
onTestMr
|
|
4955
5036
|
}) {
|
|
4956
5037
|
const theme = useTheme();
|
|
4957
|
-
const [submittingMr, setSubmittingMr] =
|
|
5038
|
+
const [submittingMr, setSubmittingMr] = React29.useState(false);
|
|
4958
5039
|
const hasSection = canSubmitMergeRequest || incomingMergeRequests.length > 0 || outgoingMergeRequests.length > 0;
|
|
4959
5040
|
if (!hasSection) return null;
|
|
4960
5041
|
const showActionsSubtitle = canSubmitMergeRequest && onSubmitMergeRequest || onTestMr && incomingMergeRequests.length > 0;
|
|
@@ -5062,7 +5143,7 @@ function PreviewCollaborateSection({
|
|
|
5062
5143
|
}
|
|
5063
5144
|
|
|
5064
5145
|
// src/studio/ui/preview-panel/usePreviewPanelData.ts
|
|
5065
|
-
import * as
|
|
5146
|
+
import * as React31 from "react";
|
|
5066
5147
|
|
|
5067
5148
|
// src/data/apps/images/remote.ts
|
|
5068
5149
|
var AppImagesRemoteDataSourceImpl = class extends BaseRemote {
|
|
@@ -5113,7 +5194,7 @@ var AppImagesRepositoryImpl = class extends BaseRepository {
|
|
|
5113
5194
|
var appImagesRepository = new AppImagesRepositoryImpl(appImagesRemoteDataSource);
|
|
5114
5195
|
|
|
5115
5196
|
// src/studio/hooks/useAppStats.ts
|
|
5116
|
-
import * as
|
|
5197
|
+
import * as React30 from "react";
|
|
5117
5198
|
import * as Haptics2 from "expo-haptics";
|
|
5118
5199
|
|
|
5119
5200
|
// src/data/likes/remote.ts
|
|
@@ -5182,34 +5263,34 @@ function useAppStats({
|
|
|
5182
5263
|
initialIsLiked = false,
|
|
5183
5264
|
onOpenComments
|
|
5184
5265
|
}) {
|
|
5185
|
-
const [likeCount, setLikeCount] =
|
|
5186
|
-
const [commentCount, setCommentCount] =
|
|
5187
|
-
const [forkCount, setForkCount] =
|
|
5188
|
-
const [isLiked, setIsLiked] =
|
|
5189
|
-
const didMutateRef =
|
|
5190
|
-
const lastAppIdRef =
|
|
5191
|
-
|
|
5266
|
+
const [likeCount, setLikeCount] = React30.useState(initialLikes);
|
|
5267
|
+
const [commentCount, setCommentCount] = React30.useState(initialComments);
|
|
5268
|
+
const [forkCount, setForkCount] = React30.useState(initialForks);
|
|
5269
|
+
const [isLiked, setIsLiked] = React30.useState(initialIsLiked);
|
|
5270
|
+
const didMutateRef = React30.useRef(false);
|
|
5271
|
+
const lastAppIdRef = React30.useRef("");
|
|
5272
|
+
React30.useEffect(() => {
|
|
5192
5273
|
if (lastAppIdRef.current === appId) return;
|
|
5193
5274
|
lastAppIdRef.current = appId;
|
|
5194
5275
|
didMutateRef.current = false;
|
|
5195
5276
|
}, [appId]);
|
|
5196
|
-
|
|
5277
|
+
React30.useEffect(() => {
|
|
5197
5278
|
if (didMutateRef.current) return;
|
|
5198
5279
|
setLikeCount(initialLikes);
|
|
5199
5280
|
}, [appId, initialLikes]);
|
|
5200
|
-
|
|
5281
|
+
React30.useEffect(() => {
|
|
5201
5282
|
if (didMutateRef.current) return;
|
|
5202
5283
|
setCommentCount(initialComments);
|
|
5203
5284
|
}, [appId, initialComments]);
|
|
5204
|
-
|
|
5285
|
+
React30.useEffect(() => {
|
|
5205
5286
|
if (didMutateRef.current) return;
|
|
5206
5287
|
setForkCount(initialForks);
|
|
5207
5288
|
}, [appId, initialForks]);
|
|
5208
|
-
|
|
5289
|
+
React30.useEffect(() => {
|
|
5209
5290
|
if (didMutateRef.current) return;
|
|
5210
5291
|
setIsLiked(initialIsLiked);
|
|
5211
5292
|
}, [appId, initialIsLiked]);
|
|
5212
|
-
const handleLike =
|
|
5293
|
+
const handleLike = React30.useCallback(async () => {
|
|
5213
5294
|
var _a, _b;
|
|
5214
5295
|
if (!appId) return;
|
|
5215
5296
|
didMutateRef.current = true;
|
|
@@ -5233,7 +5314,7 @@ function useAppStats({
|
|
|
5233
5314
|
setLikeCount((prev) => Math.max(0, prev + (newIsLiked ? -1 : 1)));
|
|
5234
5315
|
}
|
|
5235
5316
|
}, [appId, isLiked, likeCount]);
|
|
5236
|
-
const handleOpenComments =
|
|
5317
|
+
const handleOpenComments = React30.useCallback(() => {
|
|
5237
5318
|
if (!appId) return;
|
|
5238
5319
|
try {
|
|
5239
5320
|
void Haptics2.impactAsync(Haptics2.ImpactFeedbackStyle.Light);
|
|
@@ -5248,11 +5329,11 @@ function useAppStats({
|
|
|
5248
5329
|
var LIKE_DEBUG_PREFIX = "[COMERGE_LIKE_DEBUG]";
|
|
5249
5330
|
function usePreviewPanelData(params) {
|
|
5250
5331
|
const { app, isOwner, outgoingMergeRequests, onOpenComments, commentCountOverride } = params;
|
|
5251
|
-
const [imageUrl, setImageUrl] =
|
|
5252
|
-
const [imageLoaded, setImageLoaded] =
|
|
5253
|
-
const [insights, setInsights] =
|
|
5254
|
-
const [creator, setCreator] =
|
|
5255
|
-
|
|
5332
|
+
const [imageUrl, setImageUrl] = React31.useState(null);
|
|
5333
|
+
const [imageLoaded, setImageLoaded] = React31.useState(false);
|
|
5334
|
+
const [insights, setInsights] = React31.useState({ likes: 0, comments: 0, forks: 0, downloads: 0 });
|
|
5335
|
+
const [creator, setCreator] = React31.useState(null);
|
|
5336
|
+
React31.useEffect(() => {
|
|
5256
5337
|
if (!(app == null ? void 0 : app.id)) return;
|
|
5257
5338
|
let cancelled = false;
|
|
5258
5339
|
(async () => {
|
|
@@ -5267,7 +5348,7 @@ function usePreviewPanelData(params) {
|
|
|
5267
5348
|
cancelled = true;
|
|
5268
5349
|
};
|
|
5269
5350
|
}, [app == null ? void 0 : app.id]);
|
|
5270
|
-
|
|
5351
|
+
React31.useEffect(() => {
|
|
5271
5352
|
if (!(app == null ? void 0 : app.createdBy)) return;
|
|
5272
5353
|
let cancelled = false;
|
|
5273
5354
|
(async () => {
|
|
@@ -5283,10 +5364,10 @@ function usePreviewPanelData(params) {
|
|
|
5283
5364
|
cancelled = true;
|
|
5284
5365
|
};
|
|
5285
5366
|
}, [app == null ? void 0 : app.createdBy]);
|
|
5286
|
-
|
|
5367
|
+
React31.useEffect(() => {
|
|
5287
5368
|
setImageLoaded(false);
|
|
5288
5369
|
}, [app == null ? void 0 : app.id]);
|
|
5289
|
-
|
|
5370
|
+
React31.useEffect(() => {
|
|
5290
5371
|
if (!(app == null ? void 0 : app.id)) return;
|
|
5291
5372
|
let cancelled = false;
|
|
5292
5373
|
(async () => {
|
|
@@ -5311,7 +5392,7 @@ function usePreviewPanelData(params) {
|
|
|
5311
5392
|
cancelled = true;
|
|
5312
5393
|
};
|
|
5313
5394
|
}, [app == null ? void 0 : app.id]);
|
|
5314
|
-
|
|
5395
|
+
React31.useEffect(() => {
|
|
5315
5396
|
if (!(app == null ? void 0 : app.id)) return;
|
|
5316
5397
|
log.debug(
|
|
5317
5398
|
`${LIKE_DEBUG_PREFIX} usePreviewPanelData.appChanged appId=${app.id} app.isLiked=${String(app.isLiked)}`
|
|
@@ -5325,7 +5406,7 @@ function usePreviewPanelData(params) {
|
|
|
5325
5406
|
initialIsLiked: Boolean(app == null ? void 0 : app.isLiked),
|
|
5326
5407
|
onOpenComments
|
|
5327
5408
|
});
|
|
5328
|
-
const canSubmitMergeRequest =
|
|
5409
|
+
const canSubmitMergeRequest = React31.useMemo(() => {
|
|
5329
5410
|
if (!isOwner) return false;
|
|
5330
5411
|
if (!app) return false;
|
|
5331
5412
|
if (!app.forkedFromAppId) return false;
|
|
@@ -5438,17 +5519,17 @@ function PreviewPanel({
|
|
|
5438
5519
|
}
|
|
5439
5520
|
|
|
5440
5521
|
// src/studio/ui/ChatPanel.tsx
|
|
5441
|
-
import * as
|
|
5522
|
+
import * as React36 from "react";
|
|
5442
5523
|
import { ActivityIndicator as ActivityIndicator8, View as View41 } from "react-native";
|
|
5443
5524
|
|
|
5444
5525
|
// src/components/chat/ChatPage.tsx
|
|
5445
|
-
import * as
|
|
5526
|
+
import * as React34 from "react";
|
|
5446
5527
|
import { Keyboard as Keyboard4, Platform as Platform6, View as View37 } from "react-native";
|
|
5447
5528
|
import { useSafeAreaInsets as useSafeAreaInsets4 } from "react-native-safe-area-context";
|
|
5448
5529
|
import Animated11, { useAnimatedKeyboard, useAnimatedStyle as useAnimatedStyle2 } from "react-native-reanimated";
|
|
5449
5530
|
|
|
5450
5531
|
// src/components/chat/ChatMessageList.tsx
|
|
5451
|
-
import * as
|
|
5532
|
+
import * as React33 from "react";
|
|
5452
5533
|
import { View as View36 } from "react-native";
|
|
5453
5534
|
import { BottomSheetFlatList } from "@gorhom/bottom-sheet";
|
|
5454
5535
|
|
|
@@ -5494,17 +5575,17 @@ function ChatMessageBubble({ message, renderContent, style }) {
|
|
|
5494
5575
|
}
|
|
5495
5576
|
|
|
5496
5577
|
// src/components/chat/TypingIndicator.tsx
|
|
5497
|
-
import * as
|
|
5578
|
+
import * as React32 from "react";
|
|
5498
5579
|
import { Animated as Animated10, View as View35 } from "react-native";
|
|
5499
5580
|
import { jsx as jsx45 } from "react/jsx-runtime";
|
|
5500
5581
|
function TypingIndicator({ style }) {
|
|
5501
5582
|
const theme = useTheme();
|
|
5502
5583
|
const dotColor = theme.colors.textSubtle;
|
|
5503
|
-
const anims =
|
|
5584
|
+
const anims = React32.useMemo(
|
|
5504
5585
|
() => [new Animated10.Value(0.3), new Animated10.Value(0.3), new Animated10.Value(0.3)],
|
|
5505
5586
|
[]
|
|
5506
5587
|
);
|
|
5507
|
-
|
|
5588
|
+
React32.useEffect(() => {
|
|
5508
5589
|
const loops = [];
|
|
5509
5590
|
anims.forEach((a, idx) => {
|
|
5510
5591
|
const seq = Animated10.sequence([
|
|
@@ -5537,40 +5618,44 @@ function TypingIndicator({ style }) {
|
|
|
5537
5618
|
}
|
|
5538
5619
|
|
|
5539
5620
|
// src/components/chat/ChatMessageList.tsx
|
|
5540
|
-
import { jsx as jsx46 } from "react/jsx-runtime";
|
|
5541
|
-
var ChatMessageList =
|
|
5621
|
+
import { jsx as jsx46, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
5622
|
+
var ChatMessageList = React33.forwardRef(
|
|
5542
5623
|
({
|
|
5543
5624
|
messages,
|
|
5544
5625
|
showTypingIndicator = false,
|
|
5545
5626
|
renderMessageContent,
|
|
5546
5627
|
contentStyle,
|
|
5628
|
+
bottomInset = 0,
|
|
5547
5629
|
onNearBottomChange,
|
|
5548
5630
|
nearBottomThreshold = 200
|
|
5549
5631
|
}, ref) => {
|
|
5550
5632
|
const theme = useTheme();
|
|
5551
|
-
const listRef =
|
|
5552
|
-
const nearBottomRef =
|
|
5553
|
-
const initialScrollDoneRef =
|
|
5554
|
-
const lastMessageIdRef =
|
|
5555
|
-
const scrollToBottom =
|
|
5633
|
+
const listRef = React33.useRef(null);
|
|
5634
|
+
const nearBottomRef = React33.useRef(true);
|
|
5635
|
+
const initialScrollDoneRef = React33.useRef(false);
|
|
5636
|
+
const lastMessageIdRef = React33.useRef(null);
|
|
5637
|
+
const scrollToBottom = React33.useCallback((options) => {
|
|
5556
5638
|
var _a;
|
|
5557
5639
|
const animated = (options == null ? void 0 : options.animated) ?? true;
|
|
5558
5640
|
(_a = listRef.current) == null ? void 0 : _a.scrollToEnd({ animated });
|
|
5559
5641
|
}, []);
|
|
5560
|
-
|
|
5561
|
-
const handleScroll =
|
|
5642
|
+
React33.useImperativeHandle(ref, () => ({ scrollToBottom }), [scrollToBottom]);
|
|
5643
|
+
const handleScroll = React33.useCallback(
|
|
5562
5644
|
(e) => {
|
|
5563
5645
|
const { contentOffset, contentSize, layoutMeasurement } = e.nativeEvent;
|
|
5564
|
-
const distanceFromBottom = Math.max(
|
|
5646
|
+
const distanceFromBottom = Math.max(
|
|
5647
|
+
contentSize.height - Math.max(bottomInset, 0) - (contentOffset.y + layoutMeasurement.height),
|
|
5648
|
+
0
|
|
5649
|
+
);
|
|
5565
5650
|
const isNear = distanceFromBottom <= nearBottomThreshold;
|
|
5566
5651
|
if (nearBottomRef.current !== isNear) {
|
|
5567
5652
|
nearBottomRef.current = isNear;
|
|
5568
5653
|
onNearBottomChange == null ? void 0 : onNearBottomChange(isNear);
|
|
5569
5654
|
}
|
|
5570
5655
|
},
|
|
5571
|
-
[nearBottomThreshold, onNearBottomChange]
|
|
5656
|
+
[bottomInset, nearBottomThreshold, onNearBottomChange]
|
|
5572
5657
|
);
|
|
5573
|
-
|
|
5658
|
+
React33.useEffect(() => {
|
|
5574
5659
|
var _a;
|
|
5575
5660
|
if (initialScrollDoneRef.current) return;
|
|
5576
5661
|
if (messages.length === 0) return;
|
|
@@ -5579,7 +5664,7 @@ var ChatMessageList = React32.forwardRef(
|
|
|
5579
5664
|
const id = requestAnimationFrame(() => scrollToBottom({ animated: false }));
|
|
5580
5665
|
return () => cancelAnimationFrame(id);
|
|
5581
5666
|
}, [messages, scrollToBottom]);
|
|
5582
|
-
|
|
5667
|
+
React33.useEffect(() => {
|
|
5583
5668
|
if (!initialScrollDoneRef.current) return;
|
|
5584
5669
|
const lastId = messages.length > 0 ? messages[messages.length - 1].id : null;
|
|
5585
5670
|
const prevLastId = lastMessageIdRef.current;
|
|
@@ -5589,13 +5674,19 @@ var ChatMessageList = React32.forwardRef(
|
|
|
5589
5674
|
const id = requestAnimationFrame(() => scrollToBottom({ animated: true }));
|
|
5590
5675
|
return () => cancelAnimationFrame(id);
|
|
5591
5676
|
}, [messages, scrollToBottom]);
|
|
5592
|
-
|
|
5677
|
+
React33.useEffect(() => {
|
|
5593
5678
|
if (showTypingIndicator && nearBottomRef.current) {
|
|
5594
5679
|
const id = requestAnimationFrame(() => scrollToBottom({ animated: true }));
|
|
5595
5680
|
return () => cancelAnimationFrame(id);
|
|
5596
5681
|
}
|
|
5597
5682
|
return void 0;
|
|
5598
5683
|
}, [showTypingIndicator, scrollToBottom]);
|
|
5684
|
+
React33.useEffect(() => {
|
|
5685
|
+
if (!initialScrollDoneRef.current) return;
|
|
5686
|
+
if (!nearBottomRef.current) return;
|
|
5687
|
+
const id = requestAnimationFrame(() => scrollToBottom({ animated: false }));
|
|
5688
|
+
return () => cancelAnimationFrame(id);
|
|
5689
|
+
}, [bottomInset, scrollToBottom]);
|
|
5599
5690
|
return /* @__PURE__ */ jsx46(
|
|
5600
5691
|
BottomSheetFlatList,
|
|
5601
5692
|
{
|
|
@@ -5609,13 +5700,15 @@ var ChatMessageList = React32.forwardRef(
|
|
|
5609
5700
|
{
|
|
5610
5701
|
paddingHorizontal: theme.spacing.lg,
|
|
5611
5702
|
paddingTop: theme.spacing.sm,
|
|
5612
|
-
paddingBottom: theme.spacing.
|
|
5703
|
+
paddingBottom: theme.spacing.sm
|
|
5613
5704
|
},
|
|
5614
5705
|
contentStyle
|
|
5615
5706
|
],
|
|
5616
5707
|
renderItem: ({ item, index }) => /* @__PURE__ */ jsx46(View36, { style: { marginTop: index === 0 ? 0 : theme.spacing.sm }, children: /* @__PURE__ */ jsx46(ChatMessageBubble, { message: item, renderContent: renderMessageContent }) }),
|
|
5617
|
-
ListFooterComponent:
|
|
5618
|
-
|
|
5708
|
+
ListFooterComponent: /* @__PURE__ */ jsxs28(View36, { children: [
|
|
5709
|
+
showTypingIndicator ? /* @__PURE__ */ jsx46(View36, { style: { marginTop: theme.spacing.sm, alignSelf: "flex-start", paddingHorizontal: theme.spacing.lg }, children: /* @__PURE__ */ jsx46(TypingIndicator, {}) }) : null,
|
|
5710
|
+
bottomInset > 0 ? /* @__PURE__ */ jsx46(View36, { style: { height: bottomInset } }) : null
|
|
5711
|
+
] })
|
|
5619
5712
|
}
|
|
5620
5713
|
);
|
|
5621
5714
|
}
|
|
@@ -5623,7 +5716,7 @@ var ChatMessageList = React32.forwardRef(
|
|
|
5623
5716
|
ChatMessageList.displayName = "ChatMessageList";
|
|
5624
5717
|
|
|
5625
5718
|
// src/components/chat/ChatPage.tsx
|
|
5626
|
-
import { jsx as jsx47, jsxs as
|
|
5719
|
+
import { jsx as jsx47, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
5627
5720
|
function ChatPage({
|
|
5628
5721
|
header,
|
|
5629
5722
|
messages,
|
|
@@ -5638,10 +5731,10 @@ function ChatPage({
|
|
|
5638
5731
|
}) {
|
|
5639
5732
|
const theme = useTheme();
|
|
5640
5733
|
const insets = useSafeAreaInsets4();
|
|
5641
|
-
const [composerHeight, setComposerHeight] =
|
|
5642
|
-
const [keyboardVisible, setKeyboardVisible] =
|
|
5734
|
+
const [composerHeight, setComposerHeight] = React34.useState(0);
|
|
5735
|
+
const [keyboardVisible, setKeyboardVisible] = React34.useState(false);
|
|
5643
5736
|
const animatedKeyboard = useAnimatedKeyboard();
|
|
5644
|
-
|
|
5737
|
+
React34.useEffect(() => {
|
|
5645
5738
|
if (Platform6.OS !== "ios") return;
|
|
5646
5739
|
const show = Keyboard4.addListener("keyboardWillShow", () => setKeyboardVisible(true));
|
|
5647
5740
|
const hide = Keyboard4.addListener("keyboardWillHide", () => setKeyboardVisible(false));
|
|
@@ -5656,19 +5749,20 @@ function ChatPage({
|
|
|
5656
5749
|
return { paddingBottom: animatedKeyboard.height.value > 0 ? 0 : insets.bottom };
|
|
5657
5750
|
});
|
|
5658
5751
|
const overlayBottom = composerHeight + footerBottomPadding + theme.spacing.lg;
|
|
5659
|
-
const
|
|
5752
|
+
const bottomInset = composerHeight + footerBottomPadding + theme.spacing.xl;
|
|
5753
|
+
const resolvedOverlay = React34.useMemo(() => {
|
|
5660
5754
|
var _a;
|
|
5661
5755
|
if (!overlay) return null;
|
|
5662
|
-
if (!
|
|
5756
|
+
if (!React34.isValidElement(overlay)) return overlay;
|
|
5663
5757
|
const prevStyle = (_a = overlay.props) == null ? void 0 : _a.style;
|
|
5664
|
-
return
|
|
5758
|
+
return React34.cloneElement(overlay, {
|
|
5665
5759
|
style: [prevStyle, { bottom: overlayBottom }]
|
|
5666
5760
|
});
|
|
5667
5761
|
}, [overlay, overlayBottom]);
|
|
5668
|
-
return /* @__PURE__ */
|
|
5762
|
+
return /* @__PURE__ */ jsxs29(View37, { style: [{ flex: 1 }, style], children: [
|
|
5669
5763
|
header ? /* @__PURE__ */ jsx47(View37, { children: header }) : null,
|
|
5670
5764
|
topBanner ? /* @__PURE__ */ jsx47(View37, { style: { paddingHorizontal: theme.spacing.lg, paddingTop: theme.spacing.sm }, children: topBanner }) : null,
|
|
5671
|
-
/* @__PURE__ */
|
|
5765
|
+
/* @__PURE__ */ jsxs29(View37, { style: { flex: 1 }, children: [
|
|
5672
5766
|
/* @__PURE__ */ jsx47(
|
|
5673
5767
|
ChatMessageList,
|
|
5674
5768
|
{
|
|
@@ -5677,7 +5771,7 @@ function ChatPage({
|
|
|
5677
5771
|
showTypingIndicator,
|
|
5678
5772
|
renderMessageContent,
|
|
5679
5773
|
onNearBottomChange,
|
|
5680
|
-
|
|
5774
|
+
bottomInset
|
|
5681
5775
|
}
|
|
5682
5776
|
),
|
|
5683
5777
|
resolvedOverlay,
|
|
@@ -5710,15 +5804,15 @@ function ChatPage({
|
|
|
5710
5804
|
}
|
|
5711
5805
|
|
|
5712
5806
|
// src/components/chat/ScrollToBottomButton.tsx
|
|
5713
|
-
import * as
|
|
5807
|
+
import * as React35 from "react";
|
|
5714
5808
|
import { Pressable as Pressable12, View as View38 } from "react-native";
|
|
5715
5809
|
import Animated12, { Easing as Easing2, useAnimatedStyle as useAnimatedStyle3, useSharedValue as useSharedValue2, withTiming as withTiming2 } from "react-native-reanimated";
|
|
5716
5810
|
import { jsx as jsx48 } from "react/jsx-runtime";
|
|
5717
5811
|
function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
5718
5812
|
const theme = useTheme();
|
|
5719
5813
|
const progress = useSharedValue2(visible ? 1 : 0);
|
|
5720
|
-
const [pressed, setPressed] =
|
|
5721
|
-
|
|
5814
|
+
const [pressed, setPressed] = React35.useState(false);
|
|
5815
|
+
React35.useEffect(() => {
|
|
5722
5816
|
progress.value = withTiming2(visible ? 1 : 0, { duration: 200, easing: Easing2.out(Easing2.ease) });
|
|
5723
5817
|
}, [progress, visible]);
|
|
5724
5818
|
const animStyle = useAnimatedStyle3(() => ({
|
|
@@ -5800,7 +5894,7 @@ function ChatHeader({ left, right, center, style }) {
|
|
|
5800
5894
|
|
|
5801
5895
|
// src/components/chat/ForkNoticeBanner.tsx
|
|
5802
5896
|
import { View as View40 } from "react-native";
|
|
5803
|
-
import { jsx as jsx50, jsxs as
|
|
5897
|
+
import { jsx as jsx50, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
5804
5898
|
function ForkNoticeBanner({ isOwner = true, title, description, style }) {
|
|
5805
5899
|
const theme = useTheme();
|
|
5806
5900
|
const resolvedTitle = title ?? (isOwner ? "Remixed app" : "Remix app");
|
|
@@ -5820,7 +5914,7 @@ function ForkNoticeBanner({ isOwner = true, title, description, style }) {
|
|
|
5820
5914
|
},
|
|
5821
5915
|
style
|
|
5822
5916
|
],
|
|
5823
|
-
children: /* @__PURE__ */
|
|
5917
|
+
children: /* @__PURE__ */ jsxs30(View40, { style: { minWidth: 0 }, children: [
|
|
5824
5918
|
/* @__PURE__ */ jsx50(
|
|
5825
5919
|
Text,
|
|
5826
5920
|
{
|
|
@@ -5853,7 +5947,7 @@ function ForkNoticeBanner({ isOwner = true, title, description, style }) {
|
|
|
5853
5947
|
}
|
|
5854
5948
|
|
|
5855
5949
|
// src/studio/ui/ChatPanel.tsx
|
|
5856
|
-
import { jsx as jsx51, jsxs as
|
|
5950
|
+
import { jsx as jsx51, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
5857
5951
|
function ChatPanel({
|
|
5858
5952
|
title = "Chat",
|
|
5859
5953
|
autoFocusComposer = false,
|
|
@@ -5873,32 +5967,34 @@ function ChatPanel({
|
|
|
5873
5967
|
onStartDraw,
|
|
5874
5968
|
onSend
|
|
5875
5969
|
}) {
|
|
5876
|
-
const listRef =
|
|
5877
|
-
const [nearBottom, setNearBottom] =
|
|
5878
|
-
const handleSend =
|
|
5970
|
+
const listRef = React36.useRef(null);
|
|
5971
|
+
const [nearBottom, setNearBottom] = React36.useState(true);
|
|
5972
|
+
const handleSend = React36.useCallback(
|
|
5879
5973
|
async (text, composerAttachments) => {
|
|
5880
5974
|
const all = composerAttachments ?? attachments;
|
|
5881
5975
|
await onSend(text, all.length > 0 ? all : void 0);
|
|
5882
5976
|
onClearAttachments == null ? void 0 : onClearAttachments();
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5977
|
+
if (!nearBottom) {
|
|
5978
|
+
requestAnimationFrame(() => {
|
|
5979
|
+
var _a;
|
|
5980
|
+
return (_a = listRef.current) == null ? void 0 : _a.scrollToBottom({ animated: true });
|
|
5981
|
+
});
|
|
5982
|
+
}
|
|
5887
5983
|
},
|
|
5888
|
-
[attachments, onClearAttachments, onSend]
|
|
5984
|
+
[attachments, nearBottom, onClearAttachments, onSend]
|
|
5889
5985
|
);
|
|
5890
|
-
const handleScrollToBottom =
|
|
5986
|
+
const handleScrollToBottom = React36.useCallback(() => {
|
|
5891
5987
|
var _a;
|
|
5892
5988
|
(_a = listRef.current) == null ? void 0 : _a.scrollToBottom({ animated: true });
|
|
5893
5989
|
}, []);
|
|
5894
5990
|
const header = /* @__PURE__ */ jsx51(
|
|
5895
5991
|
ChatHeader,
|
|
5896
5992
|
{
|
|
5897
|
-
left: /* @__PURE__ */
|
|
5993
|
+
left: /* @__PURE__ */ jsxs31(View41, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
5898
5994
|
/* @__PURE__ */ jsx51(StudioSheetHeaderIconButton, { onPress: onBack, accessibilityLabel: "Back", style: { marginRight: 8 }, children: /* @__PURE__ */ jsx51(IconBack, { size: 20, colorToken: "floatingContent" }) }),
|
|
5899
5995
|
onNavigateHome ? /* @__PURE__ */ jsx51(StudioSheetHeaderIconButton, { onPress: onNavigateHome, accessibilityLabel: "Home", children: /* @__PURE__ */ jsx51(IconHome, { size: 20, colorToken: "floatingContent" }) }) : null
|
|
5900
5996
|
] }),
|
|
5901
|
-
right: /* @__PURE__ */
|
|
5997
|
+
right: /* @__PURE__ */ jsxs31(View41, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
5902
5998
|
onStartDraw ? /* @__PURE__ */ jsx51(StudioSheetHeaderIconButton, { onPress: onStartDraw, accessibilityLabel: "Draw", intent: "danger", style: { marginRight: 8 }, children: /* @__PURE__ */ jsx51(IconDraw, { size: 20, colorToken: "onDanger" }) }) : null,
|
|
5903
5999
|
/* @__PURE__ */ jsx51(StudioSheetHeaderIconButton, { onPress: onClose, accessibilityLabel: "Close", children: /* @__PURE__ */ jsx51(IconClose, { size: 20, colorToken: "floatingContent" }) })
|
|
5904
6000
|
] }),
|
|
@@ -5914,10 +6010,10 @@ function ChatPanel({
|
|
|
5914
6010
|
) : null;
|
|
5915
6011
|
const showMessagesLoading = Boolean(loading) && messages.length === 0 || forking;
|
|
5916
6012
|
if (showMessagesLoading) {
|
|
5917
|
-
return /* @__PURE__ */
|
|
6013
|
+
return /* @__PURE__ */ jsxs31(View41, { style: { flex: 1 }, children: [
|
|
5918
6014
|
/* @__PURE__ */ jsx51(View41, { children: header }),
|
|
5919
6015
|
topBanner ? /* @__PURE__ */ jsx51(View41, { style: { paddingHorizontal: 16, paddingTop: 8 }, children: topBanner }) : null,
|
|
5920
|
-
/* @__PURE__ */
|
|
6016
|
+
/* @__PURE__ */ jsxs31(View41, { style: { flex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 24, paddingVertical: 12 }, children: [
|
|
5921
6017
|
/* @__PURE__ */ jsx51(ActivityIndicator8, {}),
|
|
5922
6018
|
/* @__PURE__ */ jsx51(View41, { style: { height: 12 } }),
|
|
5923
6019
|
/* @__PURE__ */ jsx51(Text, { variant: "bodyMuted", children: forking ? "Creating your copy\u2026" : "Loading messages\u2026" })
|
|
@@ -5943,7 +6039,10 @@ function ChatPanel({
|
|
|
5943
6039
|
}
|
|
5944
6040
|
),
|
|
5945
6041
|
composer: {
|
|
5946
|
-
|
|
6042
|
+
// Keep the input editable even when sending is disallowed (e.g. agent still working),
|
|
6043
|
+
// otherwise iOS will drop focus/keyboard and BottomSheet can get "stuck" with a keyboard-sized gap.
|
|
6044
|
+
disabled: Boolean(loading) || Boolean(forking),
|
|
6045
|
+
sendDisabled: Boolean(sendDisabled) || Boolean(loading) || Boolean(forking),
|
|
5947
6046
|
sending: Boolean(sending),
|
|
5948
6047
|
autoFocus: autoFocusComposer,
|
|
5949
6048
|
onSend: handleSend,
|
|
@@ -5957,7 +6056,7 @@ function ChatPanel({
|
|
|
5957
6056
|
}
|
|
5958
6057
|
|
|
5959
6058
|
// src/components/dialogs/ConfirmMergeRequestDialog.tsx
|
|
5960
|
-
import * as
|
|
6059
|
+
import * as React37 from "react";
|
|
5961
6060
|
import { Pressable as Pressable14, View as View43 } from "react-native";
|
|
5962
6061
|
|
|
5963
6062
|
// src/components/primitives/Modal.tsx
|
|
@@ -5966,7 +6065,7 @@ import {
|
|
|
5966
6065
|
Pressable as Pressable13,
|
|
5967
6066
|
View as View42
|
|
5968
6067
|
} from "react-native";
|
|
5969
|
-
import { jsx as jsx52, jsxs as
|
|
6068
|
+
import { jsx as jsx52, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
5970
6069
|
function Modal({
|
|
5971
6070
|
visible,
|
|
5972
6071
|
onRequestClose,
|
|
@@ -5982,7 +6081,7 @@ function Modal({
|
|
|
5982
6081
|
transparent: true,
|
|
5983
6082
|
animationType: "fade",
|
|
5984
6083
|
onRequestClose,
|
|
5985
|
-
children: /* @__PURE__ */
|
|
6084
|
+
children: /* @__PURE__ */ jsxs32(View42, { style: { flex: 1, backgroundColor: theme.colors.backdrop, justifyContent: "center", padding: theme.spacing.lg }, children: [
|
|
5986
6085
|
/* @__PURE__ */ jsx52(
|
|
5987
6086
|
Pressable13,
|
|
5988
6087
|
{
|
|
@@ -5998,7 +6097,7 @@ function Modal({
|
|
|
5998
6097
|
}
|
|
5999
6098
|
|
|
6000
6099
|
// src/components/dialogs/ConfirmMergeRequestDialog.tsx
|
|
6001
|
-
import { jsx as jsx53, jsxs as
|
|
6100
|
+
import { jsx as jsx53, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
6002
6101
|
function ConfirmMergeRequestDialog({
|
|
6003
6102
|
visible,
|
|
6004
6103
|
onOpenChange,
|
|
@@ -6009,14 +6108,14 @@ function ConfirmMergeRequestDialog({
|
|
|
6009
6108
|
onTestFirst
|
|
6010
6109
|
}) {
|
|
6011
6110
|
const theme = useTheme();
|
|
6012
|
-
const close =
|
|
6111
|
+
const close = React37.useCallback(() => onOpenChange(false), [onOpenChange]);
|
|
6013
6112
|
const canConfirm = Boolean(mergeRequest) && !approveDisabled;
|
|
6014
|
-
const handleConfirm =
|
|
6113
|
+
const handleConfirm = React37.useCallback(() => {
|
|
6015
6114
|
if (!mergeRequest) return;
|
|
6016
6115
|
onOpenChange(false);
|
|
6017
6116
|
void onConfirm();
|
|
6018
6117
|
}, [mergeRequest, onConfirm, onOpenChange]);
|
|
6019
|
-
const handleTestFirst =
|
|
6118
|
+
const handleTestFirst = React37.useCallback(() => {
|
|
6020
6119
|
if (!mergeRequest) return;
|
|
6021
6120
|
onOpenChange(false);
|
|
6022
6121
|
void onTestFirst(mergeRequest);
|
|
@@ -6028,7 +6127,7 @@ function ConfirmMergeRequestDialog({
|
|
|
6028
6127
|
justifyContent: "center",
|
|
6029
6128
|
alignSelf: "stretch"
|
|
6030
6129
|
};
|
|
6031
|
-
return /* @__PURE__ */
|
|
6130
|
+
return /* @__PURE__ */ jsxs33(
|
|
6032
6131
|
Modal,
|
|
6033
6132
|
{
|
|
6034
6133
|
visible,
|
|
@@ -6051,7 +6150,7 @@ function ConfirmMergeRequestDialog({
|
|
|
6051
6150
|
children: "Are you sure you want to approve this merge request?"
|
|
6052
6151
|
}
|
|
6053
6152
|
) }),
|
|
6054
|
-
/* @__PURE__ */
|
|
6153
|
+
/* @__PURE__ */ jsxs33(View43, { style: { marginTop: 16 }, children: [
|
|
6055
6154
|
/* @__PURE__ */ jsx53(
|
|
6056
6155
|
View43,
|
|
6057
6156
|
{
|
|
@@ -6165,7 +6264,7 @@ function ConfirmMergeFlow({
|
|
|
6165
6264
|
}
|
|
6166
6265
|
|
|
6167
6266
|
// src/studio/ui/StudioOverlay.tsx
|
|
6168
|
-
import { Fragment as Fragment6, jsx as jsx55, jsxs as
|
|
6267
|
+
import { Fragment as Fragment6, jsx as jsx55, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
6169
6268
|
function StudioOverlay({
|
|
6170
6269
|
captureTargetRef,
|
|
6171
6270
|
app,
|
|
@@ -6196,27 +6295,27 @@ function StudioOverlay({
|
|
|
6196
6295
|
}) {
|
|
6197
6296
|
const theme = useTheme();
|
|
6198
6297
|
const { width } = useWindowDimensions4();
|
|
6199
|
-
const [sheetOpen, setSheetOpen] =
|
|
6200
|
-
const [activePage, setActivePage] =
|
|
6201
|
-
const [drawing, setDrawing] =
|
|
6202
|
-
const [chatAttachments, setChatAttachments] =
|
|
6203
|
-
const [commentsAppId, setCommentsAppId] =
|
|
6204
|
-
const [commentsCount, setCommentsCount] =
|
|
6205
|
-
const [confirmMrId, setConfirmMrId] =
|
|
6206
|
-
const confirmMr =
|
|
6298
|
+
const [sheetOpen, setSheetOpen] = React38.useState(false);
|
|
6299
|
+
const [activePage, setActivePage] = React38.useState("preview");
|
|
6300
|
+
const [drawing, setDrawing] = React38.useState(false);
|
|
6301
|
+
const [chatAttachments, setChatAttachments] = React38.useState([]);
|
|
6302
|
+
const [commentsAppId, setCommentsAppId] = React38.useState(null);
|
|
6303
|
+
const [commentsCount, setCommentsCount] = React38.useState(null);
|
|
6304
|
+
const [confirmMrId, setConfirmMrId] = React38.useState(null);
|
|
6305
|
+
const confirmMr = React38.useMemo(
|
|
6207
6306
|
() => confirmMrId ? incomingMergeRequests.find((m) => m.id === confirmMrId) ?? null : null,
|
|
6208
6307
|
[confirmMrId, incomingMergeRequests]
|
|
6209
6308
|
);
|
|
6210
|
-
const closeSheet =
|
|
6309
|
+
const closeSheet = React38.useCallback(() => {
|
|
6211
6310
|
setSheetOpen(false);
|
|
6212
6311
|
Keyboard5.dismiss();
|
|
6213
6312
|
}, []);
|
|
6214
|
-
const openSheet =
|
|
6215
|
-
const goToChat =
|
|
6313
|
+
const openSheet = React38.useCallback(() => setSheetOpen(true), []);
|
|
6314
|
+
const goToChat = React38.useCallback(() => {
|
|
6216
6315
|
setActivePage("chat");
|
|
6217
6316
|
openSheet();
|
|
6218
6317
|
}, [openSheet]);
|
|
6219
|
-
const backToPreview =
|
|
6318
|
+
const backToPreview = React38.useCallback(() => {
|
|
6220
6319
|
if (Platform7.OS !== "ios") {
|
|
6221
6320
|
Keyboard5.dismiss();
|
|
6222
6321
|
setActivePage("preview");
|
|
@@ -6234,11 +6333,11 @@ function StudioOverlay({
|
|
|
6234
6333
|
const t = setTimeout(finalize, 350);
|
|
6235
6334
|
Keyboard5.dismiss();
|
|
6236
6335
|
}, []);
|
|
6237
|
-
const startDraw =
|
|
6336
|
+
const startDraw = React38.useCallback(() => {
|
|
6238
6337
|
setDrawing(true);
|
|
6239
6338
|
closeSheet();
|
|
6240
6339
|
}, [closeSheet]);
|
|
6241
|
-
const handleDrawCapture =
|
|
6340
|
+
const handleDrawCapture = React38.useCallback(
|
|
6242
6341
|
(dataUrl) => {
|
|
6243
6342
|
setChatAttachments((prev) => [...prev, dataUrl]);
|
|
6244
6343
|
setDrawing(false);
|
|
@@ -6247,7 +6346,7 @@ function StudioOverlay({
|
|
|
6247
6346
|
},
|
|
6248
6347
|
[openSheet]
|
|
6249
6348
|
);
|
|
6250
|
-
const toggleSheet =
|
|
6349
|
+
const toggleSheet = React38.useCallback(async () => {
|
|
6251
6350
|
if (!sheetOpen) {
|
|
6252
6351
|
const shouldExitTest = Boolean(testingMrId) || isTesting;
|
|
6253
6352
|
if (shouldExitTest) {
|
|
@@ -6259,7 +6358,7 @@ function StudioOverlay({
|
|
|
6259
6358
|
closeSheet();
|
|
6260
6359
|
}
|
|
6261
6360
|
}, [closeSheet, isTesting, onRestoreBase, sheetOpen, testingMrId]);
|
|
6262
|
-
const handleTestMr =
|
|
6361
|
+
const handleTestMr = React38.useCallback(
|
|
6263
6362
|
async (mr) => {
|
|
6264
6363
|
if (!onTestMr) return;
|
|
6265
6364
|
await onTestMr(mr);
|
|
@@ -6267,7 +6366,7 @@ function StudioOverlay({
|
|
|
6267
6366
|
},
|
|
6268
6367
|
[closeSheet, onTestMr]
|
|
6269
6368
|
);
|
|
6270
|
-
return /* @__PURE__ */
|
|
6369
|
+
return /* @__PURE__ */ jsxs34(Fragment6, { children: [
|
|
6271
6370
|
/* @__PURE__ */ jsx55(EdgeGlowFrame, { visible: isTesting, role: "accent", thickness: 40, intensity: 1 }),
|
|
6272
6371
|
/* @__PURE__ */ jsx55(StudioBottomSheet, { open: sheetOpen, onOpenChange: setSheetOpen, children: /* @__PURE__ */ jsx55(
|
|
6273
6372
|
StudioSheetPager,
|
|
@@ -6369,7 +6468,7 @@ function StudioOverlay({
|
|
|
6369
6468
|
}
|
|
6370
6469
|
|
|
6371
6470
|
// src/studio/ComergeStudio.tsx
|
|
6372
|
-
import { jsx as jsx56, jsxs as
|
|
6471
|
+
import { jsx as jsx56, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
6373
6472
|
function ComergeStudio({
|
|
6374
6473
|
appId,
|
|
6375
6474
|
apiKey,
|
|
@@ -6377,16 +6476,16 @@ function ComergeStudio({
|
|
|
6377
6476
|
onNavigateHome,
|
|
6378
6477
|
style
|
|
6379
6478
|
}) {
|
|
6380
|
-
const [activeAppId, setActiveAppId] =
|
|
6381
|
-
const [runtimeAppId, setRuntimeAppId] =
|
|
6382
|
-
const [pendingRuntimeTargetAppId, setPendingRuntimeTargetAppId] =
|
|
6383
|
-
const platform =
|
|
6384
|
-
|
|
6479
|
+
const [activeAppId, setActiveAppId] = React39.useState(appId);
|
|
6480
|
+
const [runtimeAppId, setRuntimeAppId] = React39.useState(appId);
|
|
6481
|
+
const [pendingRuntimeTargetAppId, setPendingRuntimeTargetAppId] = React39.useState(null);
|
|
6482
|
+
const platform = React39.useMemo(() => RNPlatform.OS === "ios" ? "ios" : "android", []);
|
|
6483
|
+
React39.useEffect(() => {
|
|
6385
6484
|
setActiveAppId(appId);
|
|
6386
6485
|
setRuntimeAppId(appId);
|
|
6387
6486
|
setPendingRuntimeTargetAppId(null);
|
|
6388
6487
|
}, [appId]);
|
|
6389
|
-
const captureTargetRef =
|
|
6488
|
+
const captureTargetRef = React39.useRef(null);
|
|
6390
6489
|
return /* @__PURE__ */ jsx56(StudioBootstrap, { apiKey, children: ({ userId }) => /* @__PURE__ */ jsx56(BottomSheetModalProvider, { children: /* @__PURE__ */ jsx56(
|
|
6391
6490
|
ComergeStudioInner,
|
|
6392
6491
|
{
|
|
@@ -6422,11 +6521,11 @@ function ComergeStudioInner({
|
|
|
6422
6521
|
const { app, loading: appLoading } = useApp(activeAppId);
|
|
6423
6522
|
const { app: runtimeAppFromHook } = useApp(runtimeAppId, { enabled: runtimeAppId !== activeAppId });
|
|
6424
6523
|
const runtimeApp = runtimeAppId === activeAppId ? app : runtimeAppFromHook;
|
|
6425
|
-
const sawEditingOnPendingTargetRef =
|
|
6426
|
-
|
|
6524
|
+
const sawEditingOnPendingTargetRef = React39.useRef(false);
|
|
6525
|
+
React39.useEffect(() => {
|
|
6427
6526
|
sawEditingOnPendingTargetRef.current = false;
|
|
6428
6527
|
}, [pendingRuntimeTargetAppId]);
|
|
6429
|
-
|
|
6528
|
+
React39.useEffect(() => {
|
|
6430
6529
|
if (!pendingRuntimeTargetAppId) return;
|
|
6431
6530
|
if (activeAppId !== pendingRuntimeTargetAppId) return;
|
|
6432
6531
|
if ((app == null ? void 0 : app.status) === "editing") {
|
|
@@ -6446,10 +6545,10 @@ function ComergeStudioInner({
|
|
|
6446
6545
|
const threadId = (app == null ? void 0 : app.threadId) ?? "";
|
|
6447
6546
|
const thread = useThreadMessages(threadId);
|
|
6448
6547
|
const mergeRequests = useMergeRequests({ appId: activeAppId });
|
|
6449
|
-
const hasOpenOutgoingMr =
|
|
6548
|
+
const hasOpenOutgoingMr = React39.useMemo(() => {
|
|
6450
6549
|
return mergeRequests.lists.outgoing.some((mr) => mr.status === "open");
|
|
6451
6550
|
}, [mergeRequests.lists.outgoing]);
|
|
6452
|
-
const incomingReviewMrs =
|
|
6551
|
+
const incomingReviewMrs = React39.useMemo(() => {
|
|
6453
6552
|
if (!userId) return mergeRequests.lists.incoming;
|
|
6454
6553
|
return mergeRequests.lists.incoming.filter((mr) => mr.createdBy !== userId);
|
|
6455
6554
|
}, [mergeRequests.lists.incoming, userId]);
|
|
@@ -6471,16 +6570,16 @@ function ComergeStudioInner({
|
|
|
6471
6570
|
uploadAttachments: uploader.uploadBase64Images
|
|
6472
6571
|
});
|
|
6473
6572
|
const chatSendDisabled = hasNoOutcomeAfterLastHuman(thread.raw);
|
|
6474
|
-
const [processingMrId, setProcessingMrId] =
|
|
6475
|
-
const [testingMrId, setTestingMrId] =
|
|
6476
|
-
const chatShowTypingIndicator =
|
|
6573
|
+
const [processingMrId, setProcessingMrId] = React39.useState(null);
|
|
6574
|
+
const [testingMrId, setTestingMrId] = React39.useState(null);
|
|
6575
|
+
const chatShowTypingIndicator = React39.useMemo(() => {
|
|
6477
6576
|
var _a;
|
|
6478
6577
|
if (!thread.raw || thread.raw.length === 0) return false;
|
|
6479
6578
|
const last = thread.raw[thread.raw.length - 1];
|
|
6480
6579
|
const payloadType = typeof ((_a = last.payload) == null ? void 0 : _a.type) === "string" ? String(last.payload.type) : void 0;
|
|
6481
6580
|
return payloadType !== "outcome";
|
|
6482
6581
|
}, [thread.raw]);
|
|
6483
|
-
return /* @__PURE__ */ jsx56(View45, { style: [{ flex: 1 }, style], children: /* @__PURE__ */
|
|
6582
|
+
return /* @__PURE__ */ jsx56(View45, { style: [{ flex: 1 }, style], children: /* @__PURE__ */ jsxs35(View45, { ref: captureTargetRef, style: { flex: 1 }, collapsable: false, children: [
|
|
6484
6583
|
/* @__PURE__ */ jsx56(RuntimeRenderer, { appKey, bundlePath: bundle.bundlePath, renderToken: bundle.renderToken }),
|
|
6485
6584
|
/* @__PURE__ */ jsx56(
|
|
6486
6585
|
StudioOverlay,
|