@comergehq/studio 0.1.23 → 0.1.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +694 -306
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +721 -330
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/bubble/Bubble.tsx +9 -0
- package/src/components/bubble/types.ts +2 -0
- package/src/components/chat/ChatComposer.tsx +4 -21
- package/src/components/chat/ChatMessageBubble.tsx +33 -2
- package/src/components/chat/ChatMessageList.tsx +12 -1
- package/src/components/chat/ChatPage.tsx +8 -14
- package/src/components/merge-requests/ReviewMergeRequestCard.tsx +1 -1
- package/src/components/primitives/MarkdownText.tsx +134 -35
- package/src/components/studio-sheet/StudioBottomSheet.tsx +26 -29
- package/src/core/services/http/index.ts +64 -1
- package/src/core/services/supabase/realtimeManager.ts +55 -1
- package/src/data/agent/types.ts +1 -0
- package/src/data/apps/bundles/remote.ts +4 -3
- package/src/data/users/types.ts +1 -1
- package/src/index.ts +1 -0
- package/src/studio/ComergeStudio.tsx +6 -2
- package/src/studio/hooks/useApp.ts +24 -6
- package/src/studio/hooks/useBundleManager.ts +12 -1
- package/src/studio/hooks/useForegroundSignal.ts +2 -4
- package/src/studio/hooks/useMergeRequests.ts +6 -1
- package/src/studio/hooks/useOptimisticChatMessages.ts +55 -3
- package/src/studio/hooks/useStudioActions.ts +60 -6
- package/src/studio/hooks/useThreadMessages.ts +26 -5
- package/src/studio/ui/ChatPanel.tsx +6 -3
- package/src/studio/ui/StudioOverlay.tsx +7 -2
package/dist/index.mjs
CHANGED
|
@@ -363,6 +363,41 @@ var log = logger.createLogger(
|
|
|
363
363
|
);
|
|
364
364
|
|
|
365
365
|
// src/core/services/http/index.ts
|
|
366
|
+
var RETRYABLE_MAX_ATTEMPTS = 3;
|
|
367
|
+
var RETRYABLE_BASE_DELAY_MS = 500;
|
|
368
|
+
var RETRYABLE_MAX_DELAY_MS = 4e3;
|
|
369
|
+
var RETRYABLE_JITTER_MS = 250;
|
|
370
|
+
function sleep(ms) {
|
|
371
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
372
|
+
}
|
|
373
|
+
function isRetryableNetworkError(e) {
|
|
374
|
+
var _a;
|
|
375
|
+
const err = e;
|
|
376
|
+
const code = typeof (err == null ? void 0 : err.code) === "string" ? err.code : "";
|
|
377
|
+
const message = typeof (err == null ? void 0 : err.message) === "string" ? err.message : "";
|
|
378
|
+
if (code === "ERR_NETWORK" || code === "ECONNABORTED") return true;
|
|
379
|
+
if (message.toLowerCase().includes("network error")) return true;
|
|
380
|
+
if (message.toLowerCase().includes("timeout")) return true;
|
|
381
|
+
const status = typeof ((_a = err == null ? void 0 : err.response) == null ? void 0 : _a.status) === "number" ? err.response.status : void 0;
|
|
382
|
+
if (status && (status === 429 || status >= 500)) return true;
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
function computeBackoffDelay(attempt) {
|
|
386
|
+
const exp = Math.min(RETRYABLE_MAX_DELAY_MS, RETRYABLE_BASE_DELAY_MS * Math.pow(2, attempt - 1));
|
|
387
|
+
const jitter = Math.floor(Math.random() * RETRYABLE_JITTER_MS);
|
|
388
|
+
return exp + jitter;
|
|
389
|
+
}
|
|
390
|
+
function parseRetryAfterMs(value) {
|
|
391
|
+
if (typeof value !== "string") return null;
|
|
392
|
+
const trimmed = value.trim();
|
|
393
|
+
if (!trimmed) return null;
|
|
394
|
+
const seconds = Number(trimmed);
|
|
395
|
+
if (!Number.isNaN(seconds) && seconds >= 0) return seconds * 1e3;
|
|
396
|
+
const parsed = Date.parse(trimmed);
|
|
397
|
+
if (Number.isNaN(parsed)) return null;
|
|
398
|
+
const delta = parsed - Date.now();
|
|
399
|
+
return delta > 0 ? delta : 0;
|
|
400
|
+
}
|
|
366
401
|
var createApiClient = (baseURL) => {
|
|
367
402
|
const apiClient = axios2.create({
|
|
368
403
|
baseURL,
|
|
@@ -420,7 +455,7 @@ var createApiClient = (baseURL) => {
|
|
|
420
455
|
return response;
|
|
421
456
|
},
|
|
422
457
|
async (error) => {
|
|
423
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
458
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
424
459
|
const originalRequest = error.config;
|
|
425
460
|
log.error("Response Error:", {
|
|
426
461
|
message: error.message,
|
|
@@ -456,6 +491,23 @@ var createApiClient = (baseURL) => {
|
|
|
456
491
|
return Promise.reject(refreshErr);
|
|
457
492
|
}
|
|
458
493
|
}
|
|
494
|
+
const method = ((_h = originalRequest.method) == null ? void 0 : _h.toLowerCase()) ?? "";
|
|
495
|
+
const isGet = method === "get";
|
|
496
|
+
const retryable = isRetryableNetworkError(error);
|
|
497
|
+
const retryCount = originalRequest._retryCount ?? 0;
|
|
498
|
+
const skipRetry = originalRequest.skipRetry === true;
|
|
499
|
+
if (isGet && retryable && !skipRetry && retryCount < RETRYABLE_MAX_ATTEMPTS) {
|
|
500
|
+
const retryAfterMs = parseRetryAfterMs((_j = (_i = error.response) == null ? void 0 : _i.headers) == null ? void 0 : _j["retry-after"]);
|
|
501
|
+
originalRequest._retryCount = retryCount + 1;
|
|
502
|
+
const delayMs = retryAfterMs ?? computeBackoffDelay(retryCount + 1);
|
|
503
|
+
log.warn("Retrying GET request after transient error", {
|
|
504
|
+
url: originalRequest.url,
|
|
505
|
+
attempt: originalRequest._retryCount,
|
|
506
|
+
delayMs
|
|
507
|
+
});
|
|
508
|
+
await sleep(delayMs);
|
|
509
|
+
return apiClient(originalRequest);
|
|
510
|
+
}
|
|
459
511
|
return Promise.reject(error);
|
|
460
512
|
}
|
|
461
513
|
);
|
|
@@ -590,6 +642,25 @@ function subscribeChannel(entry) {
|
|
|
590
642
|
scheduleResubscribe(entry, "SUBSCRIBE_FAILED");
|
|
591
643
|
}
|
|
592
644
|
}
|
|
645
|
+
function unsubscribeChannel(entry) {
|
|
646
|
+
var _a, _b;
|
|
647
|
+
if (!entry.channel) return;
|
|
648
|
+
try {
|
|
649
|
+
(_b = (_a = entry.channel).unsubscribe) == null ? void 0 : _b.call(_a);
|
|
650
|
+
} catch (error) {
|
|
651
|
+
realtimeLog.warn("[realtime] unsubscribe failed", error);
|
|
652
|
+
}
|
|
653
|
+
entry.channel = null;
|
|
654
|
+
}
|
|
655
|
+
function resetRealtimeState(reason) {
|
|
656
|
+
realtimeLog.warn(`[realtime] reset state ${reason}`);
|
|
657
|
+
entries.forEach((entry) => {
|
|
658
|
+
clearTimer(entry);
|
|
659
|
+
entry.backoffMs = INITIAL_BACKOFF_MS;
|
|
660
|
+
unsubscribeChannel(entry);
|
|
661
|
+
});
|
|
662
|
+
entries.clear();
|
|
663
|
+
}
|
|
593
664
|
function subscribeManagedChannel(key, configure) {
|
|
594
665
|
let entry = entries.get(key);
|
|
595
666
|
if (!entry) {
|
|
@@ -747,14 +818,12 @@ function useForegroundSignal(enabled = true) {
|
|
|
747
818
|
React2.useEffect(() => {
|
|
748
819
|
if (!enabled) return;
|
|
749
820
|
const sub = AppState.addEventListener("change", (nextState) => {
|
|
750
|
-
var _a, _b;
|
|
751
821
|
const prevState = lastStateRef.current;
|
|
752
822
|
lastStateRef.current = nextState;
|
|
753
823
|
const didResume = (prevState === "background" || prevState === "inactive") && nextState === "active";
|
|
754
824
|
if (!didResume) return;
|
|
755
825
|
try {
|
|
756
|
-
|
|
757
|
-
(_b = (_a = supabase == null ? void 0 : supabase.realtime) == null ? void 0 : _a.connect) == null ? void 0 : _b.call(_a);
|
|
826
|
+
resetRealtimeState("APP_RESUME");
|
|
758
827
|
} catch {
|
|
759
828
|
}
|
|
760
829
|
setSignal((s) => s + 1);
|
|
@@ -769,8 +838,13 @@ function useApp(appId, options) {
|
|
|
769
838
|
const enabled = (options == null ? void 0 : options.enabled) ?? true;
|
|
770
839
|
const [app, setApp] = React3.useState(null);
|
|
771
840
|
const [loading, setLoading] = React3.useState(false);
|
|
841
|
+
const [refreshing, setRefreshing] = React3.useState(false);
|
|
772
842
|
const [error, setError] = React3.useState(null);
|
|
773
843
|
const foregroundSignal = useForegroundSignal(enabled && Boolean(appId));
|
|
844
|
+
const hasLoadedOnceRef = React3.useRef(false);
|
|
845
|
+
React3.useEffect(() => {
|
|
846
|
+
hasLoadedOnceRef.current = false;
|
|
847
|
+
}, [appId]);
|
|
774
848
|
const mergeApp = React3.useCallback((prev, next) => {
|
|
775
849
|
const merged = {
|
|
776
850
|
...prev ?? {},
|
|
@@ -780,21 +854,32 @@ function useApp(appId, options) {
|
|
|
780
854
|
};
|
|
781
855
|
return merged;
|
|
782
856
|
}, []);
|
|
783
|
-
const fetchOnce = React3.useCallback(async () => {
|
|
857
|
+
const fetchOnce = React3.useCallback(async (opts) => {
|
|
784
858
|
if (!enabled) return;
|
|
785
859
|
if (!appId) return;
|
|
786
|
-
|
|
860
|
+
const isBackground = Boolean(opts == null ? void 0 : opts.background);
|
|
861
|
+
const useBackgroundRefresh = isBackground && hasLoadedOnceRef.current;
|
|
862
|
+
if (useBackgroundRefresh) {
|
|
863
|
+
setRefreshing(true);
|
|
864
|
+
} else {
|
|
865
|
+
setLoading(true);
|
|
866
|
+
}
|
|
787
867
|
setError(null);
|
|
788
868
|
try {
|
|
789
869
|
const next = await appsRepository.getById(appId);
|
|
870
|
+
hasLoadedOnceRef.current = true;
|
|
790
871
|
setApp((prev) => mergeApp(prev, next));
|
|
791
872
|
} catch (e) {
|
|
792
873
|
setError(e instanceof Error ? e : new Error(String(e)));
|
|
793
874
|
setApp(null);
|
|
794
875
|
} finally {
|
|
795
|
-
|
|
876
|
+
if (useBackgroundRefresh) {
|
|
877
|
+
setRefreshing(false);
|
|
878
|
+
} else {
|
|
879
|
+
setLoading(false);
|
|
880
|
+
}
|
|
796
881
|
}
|
|
797
|
-
}, [appId, enabled]);
|
|
882
|
+
}, [appId, enabled, mergeApp]);
|
|
798
883
|
React3.useEffect(() => {
|
|
799
884
|
if (!enabled) return;
|
|
800
885
|
void fetchOnce();
|
|
@@ -819,9 +904,9 @@ function useApp(appId, options) {
|
|
|
819
904
|
if (!enabled) return;
|
|
820
905
|
if (!appId) return;
|
|
821
906
|
if (foregroundSignal <= 0) return;
|
|
822
|
-
void fetchOnce();
|
|
907
|
+
void fetchOnce({ background: true });
|
|
823
908
|
}, [appId, enabled, fetchOnce, foregroundSignal]);
|
|
824
|
-
return { app, loading, error, refetch: fetchOnce };
|
|
909
|
+
return { app, loading, refreshing, error, refetch: fetchOnce };
|
|
825
910
|
}
|
|
826
911
|
|
|
827
912
|
// src/studio/hooks/useThreadMessages.ts
|
|
@@ -955,33 +1040,52 @@ function mapMessageToChatMessage(m) {
|
|
|
955
1040
|
function useThreadMessages(threadId) {
|
|
956
1041
|
const [raw, setRaw] = React4.useState([]);
|
|
957
1042
|
const [loading, setLoading] = React4.useState(false);
|
|
1043
|
+
const [refreshing, setRefreshing] = React4.useState(false);
|
|
958
1044
|
const [error, setError] = React4.useState(null);
|
|
959
1045
|
const activeRequestIdRef = React4.useRef(0);
|
|
960
1046
|
const foregroundSignal = useForegroundSignal(Boolean(threadId));
|
|
1047
|
+
const hasLoadedOnceRef = React4.useRef(false);
|
|
1048
|
+
React4.useEffect(() => {
|
|
1049
|
+
hasLoadedOnceRef.current = false;
|
|
1050
|
+
}, [threadId]);
|
|
961
1051
|
const upsertSorted = React4.useCallback((prev, m) => {
|
|
962
1052
|
const next = prev.filter((x) => x.id !== m.id);
|
|
963
1053
|
next.push(m);
|
|
964
1054
|
next.sort(compareMessages);
|
|
965
1055
|
return next;
|
|
966
1056
|
}, []);
|
|
967
|
-
const refetch = React4.useCallback(async () => {
|
|
1057
|
+
const refetch = React4.useCallback(async (opts) => {
|
|
968
1058
|
if (!threadId) {
|
|
969
1059
|
setRaw([]);
|
|
1060
|
+
setLoading(false);
|
|
1061
|
+
setRefreshing(false);
|
|
970
1062
|
return;
|
|
971
1063
|
}
|
|
972
1064
|
const requestId = ++activeRequestIdRef.current;
|
|
973
|
-
|
|
1065
|
+
const isBackground = Boolean(opts == null ? void 0 : opts.background);
|
|
1066
|
+
const useBackgroundRefresh = isBackground && hasLoadedOnceRef.current;
|
|
1067
|
+
if (useBackgroundRefresh) {
|
|
1068
|
+
setRefreshing(true);
|
|
1069
|
+
} else {
|
|
1070
|
+
setLoading(true);
|
|
1071
|
+
}
|
|
974
1072
|
setError(null);
|
|
975
1073
|
try {
|
|
976
1074
|
const list = await messagesRepository.list(threadId);
|
|
977
1075
|
if (activeRequestIdRef.current !== requestId) return;
|
|
1076
|
+
hasLoadedOnceRef.current = true;
|
|
978
1077
|
setRaw([...list].sort(compareMessages));
|
|
979
1078
|
} catch (e) {
|
|
980
1079
|
if (activeRequestIdRef.current !== requestId) return;
|
|
981
1080
|
setError(e instanceof Error ? e : new Error(String(e)));
|
|
982
1081
|
setRaw([]);
|
|
983
1082
|
} finally {
|
|
984
|
-
if (activeRequestIdRef.current
|
|
1083
|
+
if (activeRequestIdRef.current !== requestId) return;
|
|
1084
|
+
if (useBackgroundRefresh) {
|
|
1085
|
+
setRefreshing(false);
|
|
1086
|
+
} else {
|
|
1087
|
+
setLoading(false);
|
|
1088
|
+
}
|
|
985
1089
|
}
|
|
986
1090
|
}, [threadId]);
|
|
987
1091
|
React4.useEffect(() => {
|
|
@@ -999,14 +1103,14 @@ function useThreadMessages(threadId) {
|
|
|
999
1103
|
React4.useEffect(() => {
|
|
1000
1104
|
if (!threadId) return;
|
|
1001
1105
|
if (foregroundSignal <= 0) return;
|
|
1002
|
-
void refetch();
|
|
1106
|
+
void refetch({ background: true });
|
|
1003
1107
|
}, [foregroundSignal, refetch, threadId]);
|
|
1004
1108
|
const messages = React4.useMemo(() => {
|
|
1005
1109
|
const visible = raw.filter((m) => !isQueuedHiddenMessage(m));
|
|
1006
1110
|
const resolved = visible.length > 0 ? visible : raw;
|
|
1007
1111
|
return resolved.map(mapMessageToChatMessage);
|
|
1008
1112
|
}, [raw]);
|
|
1009
|
-
return { raw, messages, loading, error, refetch };
|
|
1113
|
+
return { raw, messages, loading, refreshing, error, refetch };
|
|
1010
1114
|
}
|
|
1011
1115
|
|
|
1012
1116
|
// src/studio/hooks/useBundleManager.ts
|
|
@@ -1026,21 +1130,22 @@ var BundlesRemoteDataSourceImpl = class extends BaseRemote {
|
|
|
1026
1130
|
}
|
|
1027
1131
|
async getById(appId, bundleId) {
|
|
1028
1132
|
const { data } = await api.get(
|
|
1029
|
-
`/v1/apps/${encodeURIComponent(appId)}/bundles/${encodeURIComponent(bundleId)}
|
|
1133
|
+
`/v1/apps/${encodeURIComponent(appId)}/bundles/${encodeURIComponent(bundleId)}`,
|
|
1134
|
+
{ skipRetry: true }
|
|
1030
1135
|
);
|
|
1031
1136
|
return data;
|
|
1032
1137
|
}
|
|
1033
1138
|
async getSignedDownloadUrl(appId, bundleId, options) {
|
|
1034
1139
|
const { data } = await api.get(
|
|
1035
1140
|
`/v1/apps/${encodeURIComponent(appId)}/bundles/${encodeURIComponent(bundleId)}/download`,
|
|
1036
|
-
{ params: { redirect: (options == null ? void 0 : options.redirect) ?? false } }
|
|
1141
|
+
{ params: { redirect: (options == null ? void 0 : options.redirect) ?? false }, skipRetry: true }
|
|
1037
1142
|
);
|
|
1038
1143
|
return data;
|
|
1039
1144
|
}
|
|
1040
1145
|
async getSignedAssetsDownloadUrl(appId, bundleId, options) {
|
|
1041
1146
|
const { data } = await api.get(
|
|
1042
1147
|
`/v1/apps/${encodeURIComponent(appId)}/bundles/${encodeURIComponent(bundleId)}/assets/download`,
|
|
1043
|
-
{ params: { redirect: (options == null ? void 0 : options.redirect) ?? false, kind: options == null ? void 0 : options.kind } }
|
|
1148
|
+
{ params: { redirect: (options == null ? void 0 : options.redirect) ?? false, kind: options == null ? void 0 : options.kind }, skipRetry: true }
|
|
1044
1149
|
);
|
|
1045
1150
|
return data;
|
|
1046
1151
|
}
|
|
@@ -1073,10 +1178,10 @@ var BundlesRepositoryImpl = class extends BaseRepository {
|
|
|
1073
1178
|
var bundlesRepository = new BundlesRepositoryImpl(bundlesRemoteDataSource);
|
|
1074
1179
|
|
|
1075
1180
|
// src/studio/hooks/useBundleManager.ts
|
|
1076
|
-
function
|
|
1181
|
+
function sleep2(ms) {
|
|
1077
1182
|
return new Promise((r) => setTimeout(r, ms));
|
|
1078
1183
|
}
|
|
1079
|
-
function
|
|
1184
|
+
function isRetryableNetworkError2(e) {
|
|
1080
1185
|
var _a;
|
|
1081
1186
|
const err = e;
|
|
1082
1187
|
const code = typeof (err == null ? void 0 : err.code) === "string" ? err.code : "";
|
|
@@ -1095,13 +1200,13 @@ async function withRetry(fn, opts) {
|
|
|
1095
1200
|
return await fn();
|
|
1096
1201
|
} catch (e) {
|
|
1097
1202
|
lastErr = e;
|
|
1098
|
-
const retryable =
|
|
1203
|
+
const retryable = isRetryableNetworkError2(e);
|
|
1099
1204
|
if (!retryable || attempt >= opts.attempts) {
|
|
1100
1205
|
throw e;
|
|
1101
1206
|
}
|
|
1102
1207
|
const exp = Math.min(opts.maxDelayMs, opts.baseDelayMs * Math.pow(2, attempt - 1));
|
|
1103
1208
|
const jitter = Math.floor(Math.random() * 250);
|
|
1104
|
-
await
|
|
1209
|
+
await sleep2(exp + jitter);
|
|
1105
1210
|
}
|
|
1106
1211
|
}
|
|
1107
1212
|
throw lastErr;
|
|
@@ -1378,14 +1483,14 @@ async function pollBundle(appId, bundleId, opts) {
|
|
|
1378
1483
|
const bundle = await bundlesRepository.getById(appId, bundleId);
|
|
1379
1484
|
if (bundle.status === "succeeded" || bundle.status === "failed") return bundle;
|
|
1380
1485
|
} catch (e) {
|
|
1381
|
-
if (!
|
|
1486
|
+
if (!isRetryableNetworkError2(e)) {
|
|
1382
1487
|
throw e;
|
|
1383
1488
|
}
|
|
1384
1489
|
}
|
|
1385
1490
|
if (Date.now() - start > opts.timeoutMs) {
|
|
1386
1491
|
throw new Error("Bundle build timed out.");
|
|
1387
1492
|
}
|
|
1388
|
-
await
|
|
1493
|
+
await sleep2(opts.intervalMs);
|
|
1389
1494
|
}
|
|
1390
1495
|
}
|
|
1391
1496
|
async function resolveBundlePath(src, platform, mode) {
|
|
@@ -1454,6 +1559,7 @@ function useBundleManager({
|
|
|
1454
1559
|
const baseOpIdRef = React5.useRef(0);
|
|
1455
1560
|
const testOpIdRef = React5.useRef(0);
|
|
1456
1561
|
const activeLoadModeRef = React5.useRef(null);
|
|
1562
|
+
const desiredModeRef = React5.useRef("base");
|
|
1457
1563
|
const canRequestLatestRef = React5.useRef(canRequestLatest);
|
|
1458
1564
|
React5.useEffect(() => {
|
|
1459
1565
|
canRequestLatestRef.current = canRequestLatest;
|
|
@@ -1541,6 +1647,10 @@ function useBundleManager({
|
|
|
1541
1647
|
);
|
|
1542
1648
|
const load = React5.useCallback(async (src, mode) => {
|
|
1543
1649
|
if (!src.appId) return;
|
|
1650
|
+
if (mode === "test") {
|
|
1651
|
+
desiredModeRef.current = "test";
|
|
1652
|
+
baseOpIdRef.current += 1;
|
|
1653
|
+
}
|
|
1544
1654
|
const canRequestLatest2 = canRequestLatestRef.current;
|
|
1545
1655
|
if (mode === "base" && !canRequestLatest2) {
|
|
1546
1656
|
await activateCachedBase(src.appId);
|
|
@@ -1552,13 +1662,14 @@ function useBundleManager({
|
|
|
1552
1662
|
setLoadingMode(mode);
|
|
1553
1663
|
setError(null);
|
|
1554
1664
|
setStatusLabel(mode === "test" ? "Loading test bundle\u2026" : "Loading latest build\u2026");
|
|
1555
|
-
if (mode === "base") {
|
|
1665
|
+
if (mode === "base" && desiredModeRef.current === "base") {
|
|
1556
1666
|
void activateCachedBase(src.appId);
|
|
1557
1667
|
}
|
|
1558
1668
|
try {
|
|
1559
1669
|
const { bundlePath: path, bundle } = await resolveBundlePath(src, platform, mode);
|
|
1560
1670
|
if (mode === "base" && opId !== baseOpIdRef.current) return;
|
|
1561
1671
|
if (mode === "test" && opId !== testOpIdRef.current) return;
|
|
1672
|
+
if (desiredModeRef.current !== mode) return;
|
|
1562
1673
|
setBundlePath(path);
|
|
1563
1674
|
const fingerprint = bundle.checksumSha256 ?? `id:${bundle.id}`;
|
|
1564
1675
|
const shouldSkipInitialBaseRemount = mode === "base" && initialHydratedBaseFromDiskRef.current && !hasCompletedFirstNetworkBaseLoadRef.current && Boolean(lastBaseFingerprintRef.current) && lastBaseFingerprintRef.current === fingerprint;
|
|
@@ -1614,6 +1725,8 @@ function useBundleManager({
|
|
|
1614
1725
|
const restoreBase = React5.useCallback(async () => {
|
|
1615
1726
|
const src = baseRef.current;
|
|
1616
1727
|
if (!src.appId) return;
|
|
1728
|
+
desiredModeRef.current = "base";
|
|
1729
|
+
testOpIdRef.current += 1;
|
|
1617
1730
|
await activateCachedBase(src.appId);
|
|
1618
1731
|
if (canRequestLatestRef.current) {
|
|
1619
1732
|
await load(src, "base");
|
|
@@ -1775,9 +1888,12 @@ function useMergeRequests(params) {
|
|
|
1775
1888
|
const { appId } = params;
|
|
1776
1889
|
const [incoming, setIncoming] = React6.useState([]);
|
|
1777
1890
|
const [outgoing, setOutgoing] = React6.useState([]);
|
|
1778
|
-
const [loading, setLoading] = React6.useState(
|
|
1891
|
+
const [loading, setLoading] = React6.useState(() => Boolean(appId));
|
|
1779
1892
|
const [error, setError] = React6.useState(null);
|
|
1780
1893
|
const [creatorStatsById, setCreatorStatsById] = React6.useState({});
|
|
1894
|
+
React6.useEffect(() => {
|
|
1895
|
+
setLoading(Boolean(appId));
|
|
1896
|
+
}, [appId]);
|
|
1781
1897
|
const pollUntilMerged = React6.useCallback(async (mrId) => {
|
|
1782
1898
|
const startedAt = Date.now();
|
|
1783
1899
|
const timeoutMs = 2 * 60 * 1e3;
|
|
@@ -1793,6 +1909,7 @@ function useMergeRequests(params) {
|
|
|
1793
1909
|
setIncoming([]);
|
|
1794
1910
|
setOutgoing([]);
|
|
1795
1911
|
setCreatorStatsById({});
|
|
1912
|
+
setLoading(false);
|
|
1796
1913
|
return;
|
|
1797
1914
|
}
|
|
1798
1915
|
setLoading(true);
|
|
@@ -2027,6 +2144,45 @@ var AgentRepositoryImpl = class extends BaseRepository {
|
|
|
2027
2144
|
var agentRepository = new AgentRepositoryImpl(agentRemoteDataSource);
|
|
2028
2145
|
|
|
2029
2146
|
// src/studio/hooks/useStudioActions.ts
|
|
2147
|
+
function sleep3(ms) {
|
|
2148
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2149
|
+
}
|
|
2150
|
+
function isRetryableNetworkError3(e) {
|
|
2151
|
+
var _a;
|
|
2152
|
+
const err = e;
|
|
2153
|
+
const code = typeof (err == null ? void 0 : err.code) === "string" ? err.code : "";
|
|
2154
|
+
const message = typeof (err == null ? void 0 : err.message) === "string" ? err.message : "";
|
|
2155
|
+
if (code === "ERR_NETWORK" || code === "ECONNABORTED") return true;
|
|
2156
|
+
if (message.toLowerCase().includes("network error")) return true;
|
|
2157
|
+
if (message.toLowerCase().includes("timeout")) return true;
|
|
2158
|
+
const status = typeof ((_a = err == null ? void 0 : err.response) == null ? void 0 : _a.status) === "number" ? err.response.status : void 0;
|
|
2159
|
+
if (status && (status === 429 || status >= 500)) return true;
|
|
2160
|
+
return false;
|
|
2161
|
+
}
|
|
2162
|
+
async function withRetry2(fn, opts) {
|
|
2163
|
+
let lastErr = null;
|
|
2164
|
+
for (let attempt = 1; attempt <= opts.attempts; attempt += 1) {
|
|
2165
|
+
try {
|
|
2166
|
+
return await fn();
|
|
2167
|
+
} catch (e) {
|
|
2168
|
+
lastErr = e;
|
|
2169
|
+
const retryable = isRetryableNetworkError3(e);
|
|
2170
|
+
if (!retryable || attempt >= opts.attempts) {
|
|
2171
|
+
throw e;
|
|
2172
|
+
}
|
|
2173
|
+
const exp = Math.min(opts.maxDelayMs, opts.baseDelayMs * Math.pow(2, attempt - 1));
|
|
2174
|
+
const jitter = Math.floor(Math.random() * 250);
|
|
2175
|
+
await sleep3(exp + jitter);
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
throw lastErr;
|
|
2179
|
+
}
|
|
2180
|
+
function generateIdempotencyKey() {
|
|
2181
|
+
var _a, _b;
|
|
2182
|
+
const rnd = (_b = (_a = globalThis.crypto) == null ? void 0 : _a.randomUUID) == null ? void 0 : _b.call(_a);
|
|
2183
|
+
if (rnd) return `edit:${rnd}`;
|
|
2184
|
+
return `edit:${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
2185
|
+
}
|
|
2030
2186
|
function useStudioActions({
|
|
2031
2187
|
userId,
|
|
2032
2188
|
app,
|
|
@@ -2065,12 +2221,19 @@ function useStudioActions({
|
|
|
2065
2221
|
if (attachments && attachments.length > 0 && uploadAttachments) {
|
|
2066
2222
|
attachmentMetas = await uploadAttachments({ threadId, appId: targetApp.id, dataUrls: attachments });
|
|
2067
2223
|
}
|
|
2068
|
-
const
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2224
|
+
const idempotencyKey = generateIdempotencyKey();
|
|
2225
|
+
const editResult = await withRetry2(
|
|
2226
|
+
async () => {
|
|
2227
|
+
return await agentRepository.editApp({
|
|
2228
|
+
prompt,
|
|
2229
|
+
thread_id: threadId,
|
|
2230
|
+
app_id: targetApp.id,
|
|
2231
|
+
attachments: attachmentMetas && attachmentMetas.length > 0 ? attachmentMetas : void 0,
|
|
2232
|
+
idempotencyKey
|
|
2233
|
+
});
|
|
2234
|
+
},
|
|
2235
|
+
{ attempts: 3, baseDelayMs: 500, maxDelayMs: 4e3 }
|
|
2236
|
+
);
|
|
2074
2237
|
onEditQueued == null ? void 0 : onEditQueued({
|
|
2075
2238
|
queueItemId: editResult.queueItemId ?? null,
|
|
2076
2239
|
queuePosition: editResult.queuePosition ?? null
|
|
@@ -2128,12 +2291,14 @@ function RuntimeRenderer({
|
|
|
2128
2291
|
|
|
2129
2292
|
// src/studio/ui/StudioOverlay.tsx
|
|
2130
2293
|
import * as React44 from "react";
|
|
2131
|
-
import { Keyboard as
|
|
2294
|
+
import { Keyboard as Keyboard4, Platform as Platform10, View as View45, useWindowDimensions as useWindowDimensions4 } from "react-native";
|
|
2132
2295
|
|
|
2133
2296
|
// src/components/studio-sheet/StudioBottomSheet.tsx
|
|
2134
2297
|
import * as React12 from "react";
|
|
2135
2298
|
import { AppState as AppState3, Keyboard, View as View4 } from "react-native";
|
|
2136
|
-
import
|
|
2299
|
+
import {
|
|
2300
|
+
BottomSheetModal
|
|
2301
|
+
} from "@gorhom/bottom-sheet";
|
|
2137
2302
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
2138
2303
|
|
|
2139
2304
|
// src/components/studio-sheet/StudioSheetBackground.tsx
|
|
@@ -2252,25 +2417,16 @@ function StudioBottomSheet({
|
|
|
2252
2417
|
const insets = useSafeAreaInsets();
|
|
2253
2418
|
const internalSheetRef = React12.useRef(null);
|
|
2254
2419
|
const resolvedSheetRef = sheetRef ?? internalSheetRef;
|
|
2255
|
-
const
|
|
2420
|
+
const resolvedSnapPoints = React12.useMemo(() => [...snapPoints], [snapPoints]);
|
|
2421
|
+
const currentIndexRef = React12.useRef(open ? resolvedSnapPoints.length - 1 : -1);
|
|
2256
2422
|
const lastAppStateRef = React12.useRef(AppState3.currentState);
|
|
2257
2423
|
React12.useEffect(() => {
|
|
2258
2424
|
const sub = AppState3.addEventListener("change", (state) => {
|
|
2259
|
-
const prev = lastAppStateRef.current;
|
|
2260
2425
|
lastAppStateRef.current = state;
|
|
2261
2426
|
if (state === "background" || state === "inactive") {
|
|
2262
2427
|
Keyboard.dismiss();
|
|
2263
2428
|
return;
|
|
2264
2429
|
}
|
|
2265
|
-
if (state !== "active") return;
|
|
2266
|
-
const sheet = resolvedSheetRef.current;
|
|
2267
|
-
if (!sheet) return;
|
|
2268
|
-
const idx = currentIndexRef.current;
|
|
2269
|
-
if (open && idx >= 0) {
|
|
2270
|
-
Keyboard.dismiss();
|
|
2271
|
-
requestAnimationFrame(() => sheet.snapToIndex(idx));
|
|
2272
|
-
setTimeout(() => sheet.snapToIndex(idx), 120);
|
|
2273
|
-
}
|
|
2274
2430
|
});
|
|
2275
2431
|
return () => sub.remove();
|
|
2276
2432
|
}, [open, resolvedSheetRef]);
|
|
@@ -2278,11 +2434,11 @@ function StudioBottomSheet({
|
|
|
2278
2434
|
const sheet = resolvedSheetRef.current;
|
|
2279
2435
|
if (!sheet) return;
|
|
2280
2436
|
if (open) {
|
|
2281
|
-
sheet.
|
|
2437
|
+
sheet.present();
|
|
2282
2438
|
} else {
|
|
2283
|
-
sheet.
|
|
2439
|
+
sheet.dismiss();
|
|
2284
2440
|
}
|
|
2285
|
-
}, [open, resolvedSheetRef,
|
|
2441
|
+
}, [open, resolvedSheetRef, resolvedSnapPoints.length]);
|
|
2286
2442
|
const handleChange = React12.useCallback(
|
|
2287
2443
|
(index) => {
|
|
2288
2444
|
currentIndexRef.current = index;
|
|
@@ -2291,21 +2447,24 @@ function StudioBottomSheet({
|
|
|
2291
2447
|
[onOpenChange]
|
|
2292
2448
|
);
|
|
2293
2449
|
return /* @__PURE__ */ jsx7(
|
|
2294
|
-
|
|
2450
|
+
BottomSheetModal,
|
|
2295
2451
|
{
|
|
2296
2452
|
ref: resolvedSheetRef,
|
|
2297
|
-
index:
|
|
2298
|
-
snapPoints,
|
|
2453
|
+
index: resolvedSnapPoints.length - 1,
|
|
2454
|
+
snapPoints: resolvedSnapPoints,
|
|
2299
2455
|
enableDynamicSizing: false,
|
|
2300
2456
|
enablePanDownToClose: true,
|
|
2301
2457
|
enableContentPanningGesture: false,
|
|
2458
|
+
keyboardBehavior: "interactive",
|
|
2459
|
+
keyboardBlurBehavior: "restore",
|
|
2302
2460
|
android_keyboardInputMode: "adjustResize",
|
|
2303
2461
|
backgroundComponent: (props) => /* @__PURE__ */ jsx7(StudioSheetBackground, { ...props, renderBackground: background == null ? void 0 : background.renderBackground }),
|
|
2304
2462
|
topInset: insets.top,
|
|
2305
2463
|
bottomInset: 0,
|
|
2306
2464
|
handleIndicatorStyle: { backgroundColor: theme.colors.handleIndicator },
|
|
2307
|
-
onChange: handleChange,
|
|
2308
2465
|
...bottomSheetProps,
|
|
2466
|
+
onChange: handleChange,
|
|
2467
|
+
onDismiss: () => onOpenChange == null ? void 0 : onOpenChange(false),
|
|
2309
2468
|
children: /* @__PURE__ */ jsx7(View4, { style: { flex: 1, overflow: "hidden" }, children })
|
|
2310
2469
|
}
|
|
2311
2470
|
);
|
|
@@ -2366,7 +2525,7 @@ function StudioSheetPager({ activePage, width, preview, chat, style }) {
|
|
|
2366
2525
|
}
|
|
2367
2526
|
|
|
2368
2527
|
// src/components/bubble/Bubble.tsx
|
|
2369
|
-
import { useCallback as useCallback8, useEffect as useEffect11, useMemo as
|
|
2528
|
+
import { useCallback as useCallback8, useEffect as useEffect11, useMemo as useMemo4, useRef as useRef8 } from "react";
|
|
2370
2529
|
import {
|
|
2371
2530
|
PanResponder,
|
|
2372
2531
|
Pressable,
|
|
@@ -2400,6 +2559,21 @@ var ENTER_SCALE_FROM = 0.3;
|
|
|
2400
2559
|
var ENTER_ROTATION_FROM_DEG = -180;
|
|
2401
2560
|
var PULSE_DURATION_MS = 900;
|
|
2402
2561
|
|
|
2562
|
+
// src/components/utils/color.ts
|
|
2563
|
+
function withAlpha(color, alpha) {
|
|
2564
|
+
const a = Math.max(0, Math.min(1, alpha));
|
|
2565
|
+
const hex = color.trim();
|
|
2566
|
+
if (!hex.startsWith("#")) return color;
|
|
2567
|
+
const raw = hex.slice(1);
|
|
2568
|
+
const expanded = raw.length === 3 ? raw.split("").map((c) => c + c).join("") : raw;
|
|
2569
|
+
if (expanded.length !== 6) return color;
|
|
2570
|
+
const r = Number.parseInt(expanded.slice(0, 2), 16);
|
|
2571
|
+
const g = Number.parseInt(expanded.slice(2, 4), 16);
|
|
2572
|
+
const b = Number.parseInt(expanded.slice(4, 6), 16);
|
|
2573
|
+
if ([r, g, b].some((n) => Number.isNaN(n))) return color;
|
|
2574
|
+
return `rgba(${r}, ${g}, ${b}, ${a})`;
|
|
2575
|
+
}
|
|
2576
|
+
|
|
2403
2577
|
// src/components/bubble/Bubble.tsx
|
|
2404
2578
|
import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
2405
2579
|
var HIDDEN_OFFSET_X = 20;
|
|
@@ -2428,6 +2602,7 @@ function Bubble({
|
|
|
2428
2602
|
disabled = false,
|
|
2429
2603
|
ariaLabel,
|
|
2430
2604
|
isLoading = false,
|
|
2605
|
+
loadingBorderTone = "default",
|
|
2431
2606
|
visible = true,
|
|
2432
2607
|
badgeCount = 0,
|
|
2433
2608
|
offset = DEFAULT_OFFSET,
|
|
@@ -2442,22 +2617,26 @@ function Bubble({
|
|
|
2442
2617
|
const theme = useTheme();
|
|
2443
2618
|
const { width, height } = useWindowDimensions();
|
|
2444
2619
|
const isDanger = variant === "danger";
|
|
2445
|
-
const onPressRef =
|
|
2620
|
+
const onPressRef = useRef8(onPress);
|
|
2446
2621
|
useEffect11(() => {
|
|
2447
2622
|
onPressRef.current = onPress;
|
|
2448
2623
|
}, [onPress]);
|
|
2449
|
-
const fallbackBgColor =
|
|
2624
|
+
const fallbackBgColor = useMemo4(() => {
|
|
2450
2625
|
if (backgroundColor) return backgroundColor;
|
|
2451
2626
|
if (isDanger) return "rgba(239, 68, 68, 0.9)";
|
|
2452
2627
|
return theme.scheme === "dark" ? "rgba(0, 0, 0, 0.6)" : "rgba(255, 255, 255, 0.6)";
|
|
2453
2628
|
}, [backgroundColor, isDanger, theme.scheme]);
|
|
2629
|
+
const warningRingColors = useMemo4(
|
|
2630
|
+
() => [withAlpha(theme.colors.warning, 0.35), withAlpha(theme.colors.warning, 1)],
|
|
2631
|
+
[theme.colors.warning]
|
|
2632
|
+
);
|
|
2454
2633
|
const translateX = useSharedValue(getHiddenTranslateX(size));
|
|
2455
2634
|
const translateY = useSharedValue(getHiddenTranslateY(height));
|
|
2456
2635
|
const scale = useSharedValue(ENTER_SCALE_FROM);
|
|
2457
2636
|
const rotation = useSharedValue(ENTER_ROTATION_FROM_DEG);
|
|
2458
2637
|
const borderPulse = useSharedValue(0);
|
|
2459
|
-
const startPos =
|
|
2460
|
-
const isAnimatingOut =
|
|
2638
|
+
const startPos = useRef8({ x: 0, y: 0 });
|
|
2639
|
+
const isAnimatingOut = useRef8(false);
|
|
2461
2640
|
const animateToHidden = useCallback8(
|
|
2462
2641
|
(options) => {
|
|
2463
2642
|
const finish = options == null ? void 0 : options.onFinish;
|
|
@@ -2528,7 +2707,7 @@ function Bubble({
|
|
|
2528
2707
|
animateIn();
|
|
2529
2708
|
}
|
|
2530
2709
|
}, [forceShowTrigger, visible, animateIn]);
|
|
2531
|
-
const panResponder =
|
|
2710
|
+
const panResponder = useRef8(
|
|
2532
2711
|
PanResponder.create({
|
|
2533
2712
|
onStartShouldSetPanResponder: () => true,
|
|
2534
2713
|
onMoveShouldSetPanResponder: () => true,
|
|
@@ -2564,10 +2743,11 @@ function Bubble({
|
|
|
2564
2743
|
]
|
|
2565
2744
|
}));
|
|
2566
2745
|
const borderAnimatedStyle = useAnimatedStyle(() => {
|
|
2746
|
+
const isWarning = loadingBorderTone === "warning";
|
|
2567
2747
|
const borderColor = interpolateColor(
|
|
2568
2748
|
borderPulse.value,
|
|
2569
2749
|
[0, 1],
|
|
2570
|
-
isDanger ? ["rgba(239,68,68,0.4)", "rgba(239,68,68,1)"] : theme.scheme === "dark" ? ["rgba(255,255,255,0.2)", "rgba(255,255,255,0.9)"] : ["rgba(55,0,179,0.2)", "rgba(55,0,179,0.9)"]
|
|
2750
|
+
isDanger ? ["rgba(239,68,68,0.4)", "rgba(239,68,68,1)"] : isWarning ? warningRingColors : theme.scheme === "dark" ? ["rgba(255,255,255,0.2)", "rgba(255,255,255,0.9)"] : ["rgba(55,0,179,0.2)", "rgba(55,0,179,0.9)"]
|
|
2571
2751
|
);
|
|
2572
2752
|
return {
|
|
2573
2753
|
borderWidth: isLoading ? 2 : 0,
|
|
@@ -2647,23 +2827,6 @@ var styles = StyleSheet.create({
|
|
|
2647
2827
|
import * as React14 from "react";
|
|
2648
2828
|
import { Animated as Animated3, View as View6 } from "react-native";
|
|
2649
2829
|
import { LinearGradient } from "expo-linear-gradient";
|
|
2650
|
-
|
|
2651
|
-
// src/components/utils/color.ts
|
|
2652
|
-
function withAlpha(color, alpha) {
|
|
2653
|
-
const a = Math.max(0, Math.min(1, alpha));
|
|
2654
|
-
const hex = color.trim();
|
|
2655
|
-
if (!hex.startsWith("#")) return color;
|
|
2656
|
-
const raw = hex.slice(1);
|
|
2657
|
-
const expanded = raw.length === 3 ? raw.split("").map((c) => c + c).join("") : raw;
|
|
2658
|
-
if (expanded.length !== 6) return color;
|
|
2659
|
-
const r = Number.parseInt(expanded.slice(0, 2), 16);
|
|
2660
|
-
const g = Number.parseInt(expanded.slice(2, 4), 16);
|
|
2661
|
-
const b = Number.parseInt(expanded.slice(4, 6), 16);
|
|
2662
|
-
if ([r, g, b].some((n) => Number.isNaN(n))) return color;
|
|
2663
|
-
return `rgba(${r}, ${g}, ${b}, ${a})`;
|
|
2664
|
-
}
|
|
2665
|
-
|
|
2666
|
-
// src/components/overlays/EdgeGlowFrame.tsx
|
|
2667
2830
|
import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2668
2831
|
function baseColor(role, theme) {
|
|
2669
2832
|
switch (role) {
|
|
@@ -3258,10 +3421,10 @@ var styles3 = StyleSheet3.create({
|
|
|
3258
3421
|
|
|
3259
3422
|
// src/components/comments/AppCommentsSheet.tsx
|
|
3260
3423
|
import * as React24 from "react";
|
|
3261
|
-
import { ActivityIndicator as ActivityIndicator3, Keyboard as Keyboard3, Platform as
|
|
3424
|
+
import { ActivityIndicator as ActivityIndicator3, Keyboard as Keyboard3, Platform as Platform5, Pressable as Pressable5, View as View14 } from "react-native";
|
|
3262
3425
|
import {
|
|
3263
3426
|
BottomSheetBackdrop,
|
|
3264
|
-
BottomSheetModal,
|
|
3427
|
+
BottomSheetModal as BottomSheetModal2,
|
|
3265
3428
|
BottomSheetScrollView
|
|
3266
3429
|
} from "@gorhom/bottom-sheet";
|
|
3267
3430
|
import { useSafeAreaInsets as useSafeAreaInsets3 } from "react-native-safe-area-context";
|
|
@@ -3279,7 +3442,7 @@ import {
|
|
|
3279
3442
|
ScrollView,
|
|
3280
3443
|
View as View11
|
|
3281
3444
|
} from "react-native";
|
|
3282
|
-
import { isLiquidGlassSupported as isLiquidGlassSupported3 } from "@callstack/liquid-glass";
|
|
3445
|
+
import { isLiquidGlassSupported as isLiquidGlassSupported3, LiquidGlassView as LiquidGlassView2 } from "@callstack/liquid-glass";
|
|
3283
3446
|
import { Plus } from "lucide-react-native";
|
|
3284
3447
|
|
|
3285
3448
|
// src/components/chat/MultilineTextInput.tsx
|
|
@@ -3417,7 +3580,6 @@ function ChatComposer({
|
|
|
3417
3580
|
disabled = false,
|
|
3418
3581
|
sendDisabled = false,
|
|
3419
3582
|
sending = false,
|
|
3420
|
-
autoFocus = false,
|
|
3421
3583
|
onSend,
|
|
3422
3584
|
attachments = [],
|
|
3423
3585
|
onRemoveAttachment,
|
|
@@ -3440,18 +3602,6 @@ function ChatComposer({
|
|
|
3440
3602
|
const maxInputHeight = React19.useMemo(() => Dimensions.get("window").height * 0.5, []);
|
|
3441
3603
|
const shakeAnim = React19.useRef(new Animated5.Value(0)).current;
|
|
3442
3604
|
const [sendPressed, setSendPressed] = React19.useState(false);
|
|
3443
|
-
const inputRef = React19.useRef(null);
|
|
3444
|
-
const prevAutoFocusRef = React19.useRef(false);
|
|
3445
|
-
React19.useEffect(() => {
|
|
3446
|
-
const shouldFocus = autoFocus && !prevAutoFocusRef.current && !disabled && !sending;
|
|
3447
|
-
prevAutoFocusRef.current = autoFocus;
|
|
3448
|
-
if (!shouldFocus) return;
|
|
3449
|
-
const t = setTimeout(() => {
|
|
3450
|
-
var _a;
|
|
3451
|
-
(_a = inputRef.current) == null ? void 0 : _a.focus();
|
|
3452
|
-
}, 75);
|
|
3453
|
-
return () => clearTimeout(t);
|
|
3454
|
-
}, [autoFocus, disabled, sending]);
|
|
3455
3605
|
const triggerShake = React19.useCallback(() => {
|
|
3456
3606
|
shakeAnim.setValue(0);
|
|
3457
3607
|
Animated5.sequence([
|
|
@@ -3482,7 +3632,7 @@ function ChatComposer({
|
|
|
3482
3632
|
onLayout: (e) => onLayout == null ? void 0 : onLayout({ height: e.nativeEvent.layout.height }),
|
|
3483
3633
|
children: /* @__PURE__ */ jsxs8(View11, { style: { flexDirection: "row", alignItems: "flex-end", gap: 8 }, children: [
|
|
3484
3634
|
/* @__PURE__ */ jsx17(Animated5.View, { style: { flex: 1, transform: [{ translateX: shakeAnim }] }, children: /* @__PURE__ */ jsxs8(
|
|
3485
|
-
|
|
3635
|
+
LiquidGlassView2,
|
|
3486
3636
|
{
|
|
3487
3637
|
style: [
|
|
3488
3638
|
// LiquidGlassView doesn't reliably auto-size to children; ensure enough height for the
|
|
@@ -3534,13 +3684,12 @@ function ChatComposer({
|
|
|
3534
3684
|
/* @__PURE__ */ jsx17(
|
|
3535
3685
|
MultilineTextInput,
|
|
3536
3686
|
{
|
|
3537
|
-
ref: inputRef,
|
|
3538
3687
|
value: text,
|
|
3539
3688
|
onChangeText: setText,
|
|
3540
3689
|
placeholder,
|
|
3541
3690
|
editable: !disabled && !sending,
|
|
3542
3691
|
useBottomSheetTextInput,
|
|
3543
|
-
autoFocus,
|
|
3692
|
+
autoFocus: false,
|
|
3544
3693
|
placeholderTextColor,
|
|
3545
3694
|
scrollEnabled: true,
|
|
3546
3695
|
style: {
|
|
@@ -3865,11 +4014,11 @@ function useAppDetails(appId) {
|
|
|
3865
4014
|
|
|
3866
4015
|
// src/components/comments/useIosKeyboardSnapFix.ts
|
|
3867
4016
|
import * as React23 from "react";
|
|
3868
|
-
import { Keyboard as Keyboard2, Platform as
|
|
4017
|
+
import { Keyboard as Keyboard2, Platform as Platform4 } from "react-native";
|
|
3869
4018
|
function useIosKeyboardSnapFix(sheetRef, options) {
|
|
3870
4019
|
const [keyboardVisible, setKeyboardVisible] = React23.useState(false);
|
|
3871
4020
|
React23.useEffect(() => {
|
|
3872
|
-
if (
|
|
4021
|
+
if (Platform4.OS !== "ios") return;
|
|
3873
4022
|
const show = Keyboard2.addListener("keyboardWillShow", () => setKeyboardVisible(true));
|
|
3874
4023
|
const hide = Keyboard2.addListener("keyboardWillHide", () => {
|
|
3875
4024
|
var _a;
|
|
@@ -3937,7 +4086,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
3937
4086
|
onClose();
|
|
3938
4087
|
}, [appId, onClose, onPlayApp]);
|
|
3939
4088
|
return /* @__PURE__ */ jsx20(
|
|
3940
|
-
|
|
4089
|
+
BottomSheetModal2,
|
|
3941
4090
|
{
|
|
3942
4091
|
ref: sheetRef,
|
|
3943
4092
|
index: 1,
|
|
@@ -3947,8 +4096,8 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
3947
4096
|
onChange: handleChange,
|
|
3948
4097
|
backgroundStyle: {
|
|
3949
4098
|
backgroundColor: theme.scheme === "dark" ? "#0B080F" : "#FFFFFF",
|
|
3950
|
-
borderTopLeftRadius:
|
|
3951
|
-
borderTopRightRadius:
|
|
4099
|
+
borderTopLeftRadius: Platform5.OS === "ios" ? 39 : 16,
|
|
4100
|
+
borderTopRightRadius: Platform5.OS === "ios" ? 39 : 16
|
|
3952
4101
|
},
|
|
3953
4102
|
handleIndicatorStyle: { backgroundColor: theme.colors.handleIndicator },
|
|
3954
4103
|
keyboardBehavior: "interactive",
|
|
@@ -4054,7 +4203,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
4054
4203
|
bottom: 0,
|
|
4055
4204
|
paddingHorizontal: theme.spacing.lg,
|
|
4056
4205
|
paddingTop: theme.spacing.sm,
|
|
4057
|
-
paddingBottom:
|
|
4206
|
+
paddingBottom: Platform5.OS === "ios" ? keyboardVisible ? theme.spacing.lg : insets.bottom : insets.bottom + 10,
|
|
4058
4207
|
borderTopWidth: 1,
|
|
4059
4208
|
borderTopColor: withAlpha(theme.colors.border, 0.1),
|
|
4060
4209
|
backgroundColor: withAlpha(theme.colors.background, 0.8)
|
|
@@ -4081,7 +4230,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
4081
4230
|
|
|
4082
4231
|
// src/studio/ui/PreviewPanel.tsx
|
|
4083
4232
|
import * as React35 from "react";
|
|
4084
|
-
import { ActivityIndicator as ActivityIndicator7, Platform as
|
|
4233
|
+
import { ActivityIndicator as ActivityIndicator7, Platform as Platform7, Share, View as View33 } from "react-native";
|
|
4085
4234
|
|
|
4086
4235
|
// src/components/preview/PreviewPage.tsx
|
|
4087
4236
|
import { View as View15 } from "react-native";
|
|
@@ -4968,16 +5117,48 @@ import { RefreshCw, Send as Send2 } from "lucide-react-native";
|
|
|
4968
5117
|
|
|
4969
5118
|
// src/components/merge-requests/MergeRequestStatusCard.tsx
|
|
4970
5119
|
import * as React28 from "react";
|
|
4971
|
-
import { Animated as Animated7, Pressable as
|
|
5120
|
+
import { Animated as Animated7, Pressable as Pressable10, View as View28 } from "react-native";
|
|
4972
5121
|
import { Ban, Check as Check3, CheckCheck, ChevronDown as ChevronDown2 } from "lucide-react-native";
|
|
4973
5122
|
|
|
4974
5123
|
// src/components/primitives/MarkdownText.tsx
|
|
4975
|
-
import { Platform as
|
|
5124
|
+
import { Platform as Platform6, Pressable as Pressable9, Text as Text3, View as View27 } from "react-native";
|
|
4976
5125
|
import Markdown from "react-native-markdown-display";
|
|
4977
|
-
import {
|
|
5126
|
+
import { useEffect as useEffect22, useRef as useRef15, useState as useState21 } from "react";
|
|
5127
|
+
import { jsx as jsx39, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
5128
|
+
function copyMarkdownToClipboard(markdown) {
|
|
5129
|
+
var _a;
|
|
5130
|
+
if (!markdown) {
|
|
5131
|
+
return;
|
|
5132
|
+
}
|
|
5133
|
+
const navigatorClipboard = (_a = globalThis == null ? void 0 : globalThis.navigator) == null ? void 0 : _a.clipboard;
|
|
5134
|
+
if (navigatorClipboard == null ? void 0 : navigatorClipboard.writeText) {
|
|
5135
|
+
void navigatorClipboard.writeText(markdown);
|
|
5136
|
+
return;
|
|
5137
|
+
}
|
|
5138
|
+
try {
|
|
5139
|
+
const expoClipboard = __require("expo-clipboard");
|
|
5140
|
+
if (expoClipboard == null ? void 0 : expoClipboard.setStringAsync) {
|
|
5141
|
+
void expoClipboard.setStringAsync(markdown);
|
|
5142
|
+
return;
|
|
5143
|
+
}
|
|
5144
|
+
} catch {
|
|
5145
|
+
}
|
|
5146
|
+
try {
|
|
5147
|
+
const rnClipboard = __require("@react-native-clipboard/clipboard");
|
|
5148
|
+
if (rnClipboard == null ? void 0 : rnClipboard.setString) {
|
|
5149
|
+
rnClipboard.setString(markdown);
|
|
5150
|
+
}
|
|
5151
|
+
} catch {
|
|
5152
|
+
}
|
|
5153
|
+
}
|
|
4978
5154
|
function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
|
|
4979
5155
|
const theme = useTheme();
|
|
4980
5156
|
const isDark = theme.scheme === "dark";
|
|
5157
|
+
const [showCopied, setShowCopied] = useState21(false);
|
|
5158
|
+
const [tooltipPosition, setTooltipPosition] = useState21(null);
|
|
5159
|
+
const [tooltipWidth, setTooltipWidth] = useState21(0);
|
|
5160
|
+
const hideTimerRef = useRef15(null);
|
|
5161
|
+
const containerRef = useRef15(null);
|
|
4981
5162
|
const baseBodyColor = variant === "mergeRequest" ? theme.colors.textMuted : theme.colors.text;
|
|
4982
5163
|
const linkColor = variant === "mergeRequest" ? isDark ? theme.colors.primary : "#3700B3" : theme.colors.link;
|
|
4983
5164
|
const linkWeight = variant === "mergeRequest" ? theme.typography.fontWeight.semibold : void 0;
|
|
@@ -4985,40 +5166,96 @@ function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
|
|
|
4985
5166
|
const codeTextColor = isDark ? "#FFFFFF" : theme.colors.text;
|
|
4986
5167
|
const paragraphBottom = variant === "mergeRequest" ? 8 : 6;
|
|
4987
5168
|
const baseLineHeight = variant === "mergeRequest" ? 22 : 20;
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5169
|
+
useEffect22(() => {
|
|
5170
|
+
return () => {
|
|
5171
|
+
if (hideTimerRef.current) {
|
|
5172
|
+
clearTimeout(hideTimerRef.current);
|
|
5173
|
+
}
|
|
5174
|
+
};
|
|
5175
|
+
}, []);
|
|
5176
|
+
const handleLongPress = (event) => {
|
|
5177
|
+
var _a;
|
|
5178
|
+
const { locationX, locationY, pageX, pageY } = event.nativeEvent;
|
|
5179
|
+
if ((_a = containerRef.current) == null ? void 0 : _a.measureInWindow) {
|
|
5180
|
+
containerRef.current.measureInWindow((x, y) => {
|
|
5181
|
+
setTooltipPosition({ x: pageX - x, y: pageY - y });
|
|
5182
|
+
});
|
|
5183
|
+
} else {
|
|
5184
|
+
setTooltipPosition({ x: locationX, y: locationY });
|
|
5185
|
+
}
|
|
5186
|
+
copyMarkdownToClipboard(markdown);
|
|
5187
|
+
setShowCopied(true);
|
|
5188
|
+
if (hideTimerRef.current) {
|
|
5189
|
+
clearTimeout(hideTimerRef.current);
|
|
5190
|
+
}
|
|
5191
|
+
hideTimerRef.current = setTimeout(() => {
|
|
5192
|
+
setShowCopied(false);
|
|
5193
|
+
}, 1200);
|
|
5194
|
+
};
|
|
5195
|
+
return /* @__PURE__ */ jsx39(Pressable9, { style, onLongPress: handleLongPress, children: /* @__PURE__ */ jsxs22(View27, { ref: containerRef, style: { position: "relative" }, children: [
|
|
5196
|
+
/* @__PURE__ */ jsx39(
|
|
5197
|
+
Markdown,
|
|
5198
|
+
{
|
|
5199
|
+
style: {
|
|
5200
|
+
body: { color: bodyColor ?? baseBodyColor, fontSize: 14, lineHeight: baseLineHeight },
|
|
5201
|
+
paragraph: { marginTop: 0, marginBottom: paragraphBottom },
|
|
5202
|
+
link: { color: linkColor, fontWeight: linkWeight },
|
|
5203
|
+
code_inline: {
|
|
5204
|
+
backgroundColor: codeBgColor,
|
|
5205
|
+
color: codeTextColor,
|
|
5206
|
+
paddingHorizontal: variant === "mergeRequest" ? 6 : 4,
|
|
5207
|
+
paddingVertical: variant === "mergeRequest" ? 2 : 0,
|
|
5208
|
+
borderRadius: variant === "mergeRequest" ? 6 : 4,
|
|
5209
|
+
fontFamily: Platform6.OS === "ios" ? "Menlo" : "monospace",
|
|
5210
|
+
fontSize: 13
|
|
5211
|
+
},
|
|
5212
|
+
code_block: {
|
|
5213
|
+
backgroundColor: codeBgColor,
|
|
5214
|
+
color: codeTextColor,
|
|
5215
|
+
padding: variant === "mergeRequest" ? 12 : 8,
|
|
5216
|
+
borderRadius: variant === "mergeRequest" ? 8 : 6,
|
|
5217
|
+
marginVertical: variant === "mergeRequest" ? 8 : 0
|
|
5218
|
+
},
|
|
5219
|
+
fence: {
|
|
5220
|
+
backgroundColor: codeBgColor,
|
|
5221
|
+
color: codeTextColor,
|
|
5222
|
+
padding: variant === "mergeRequest" ? 12 : 8,
|
|
5223
|
+
borderRadius: variant === "mergeRequest" ? 8 : 6,
|
|
5224
|
+
marginVertical: variant === "mergeRequest" ? 8 : 0
|
|
5225
|
+
}
|
|
5003
5226
|
},
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5227
|
+
children: markdown
|
|
5228
|
+
}
|
|
5229
|
+
),
|
|
5230
|
+
showCopied && tooltipPosition ? /* @__PURE__ */ jsx39(
|
|
5231
|
+
View27,
|
|
5232
|
+
{
|
|
5233
|
+
pointerEvents: "none",
|
|
5234
|
+
style: {
|
|
5235
|
+
position: "absolute",
|
|
5236
|
+
left: tooltipPosition.x,
|
|
5237
|
+
top: tooltipPosition.y - theme.spacing.lg - 32,
|
|
5238
|
+
backgroundColor: theme.colors.success,
|
|
5239
|
+
borderRadius: theme.radii.pill,
|
|
5240
|
+
paddingHorizontal: theme.spacing.sm,
|
|
5241
|
+
paddingVertical: theme.spacing.xs,
|
|
5242
|
+
transform: [{ translateX: tooltipWidth ? -tooltipWidth / 2 : 0 }]
|
|
5010
5243
|
},
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5244
|
+
onLayout: (event) => setTooltipWidth(event.nativeEvent.layout.width),
|
|
5245
|
+
children: /* @__PURE__ */ jsx39(
|
|
5246
|
+
Text3,
|
|
5247
|
+
{
|
|
5248
|
+
style: {
|
|
5249
|
+
color: theme.colors.onSuccess,
|
|
5250
|
+
fontSize: theme.typography.fontSize.xs,
|
|
5251
|
+
fontWeight: theme.typography.fontWeight.medium
|
|
5252
|
+
},
|
|
5253
|
+
children: "Copied"
|
|
5254
|
+
}
|
|
5255
|
+
)
|
|
5256
|
+
}
|
|
5257
|
+
) : null
|
|
5258
|
+
] }) });
|
|
5022
5259
|
}
|
|
5023
5260
|
|
|
5024
5261
|
// src/components/merge-requests/mergeRequestStatusDisplay.ts
|
|
@@ -5065,7 +5302,7 @@ function useControlledExpansion(props) {
|
|
|
5065
5302
|
}
|
|
5066
5303
|
|
|
5067
5304
|
// src/components/merge-requests/MergeRequestStatusCard.tsx
|
|
5068
|
-
import { jsx as jsx40, jsxs as
|
|
5305
|
+
import { jsx as jsx40, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
5069
5306
|
function MergeRequestStatusCard({
|
|
5070
5307
|
mergeRequest,
|
|
5071
5308
|
expanded: expandedProp,
|
|
@@ -5118,7 +5355,7 @@ function MergeRequestStatusCard({
|
|
|
5118
5355
|
useNativeDriver: true
|
|
5119
5356
|
}).start();
|
|
5120
5357
|
}, [expanded, rotate]);
|
|
5121
|
-
return /* @__PURE__ */ jsx40(
|
|
5358
|
+
return /* @__PURE__ */ jsx40(Pressable10, { onPress: () => setExpanded(!expanded), style: ({ pressed }) => [{ opacity: pressed ? 0.95 : 1 }], children: /* @__PURE__ */ jsxs23(
|
|
5122
5359
|
Card,
|
|
5123
5360
|
{
|
|
5124
5361
|
padded: false,
|
|
@@ -5131,10 +5368,10 @@ function MergeRequestStatusCard({
|
|
|
5131
5368
|
style
|
|
5132
5369
|
],
|
|
5133
5370
|
children: [
|
|
5134
|
-
/* @__PURE__ */
|
|
5371
|
+
/* @__PURE__ */ jsxs23(View28, { style: { flexDirection: "row", alignItems: "center", gap: theme.spacing.lg }, children: [
|
|
5135
5372
|
/* @__PURE__ */ jsx40(View28, { style: { width: 40, height: 40, borderRadius: 999, alignItems: "center", justifyContent: "center", backgroundColor: bgColor }, children: /* @__PURE__ */ jsx40(StatusIcon, { size: 20, color: iconColor }) }),
|
|
5136
|
-
/* @__PURE__ */
|
|
5137
|
-
/* @__PURE__ */
|
|
5373
|
+
/* @__PURE__ */ jsxs23(View28, { style: { flex: 1, minWidth: 0 }, children: [
|
|
5374
|
+
/* @__PURE__ */ jsxs23(View28, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
5138
5375
|
/* @__PURE__ */ jsx40(
|
|
5139
5376
|
Text,
|
|
5140
5377
|
{
|
|
@@ -5167,7 +5404,7 @@ function MergeRequestStatusCard({
|
|
|
5167
5404
|
}
|
|
5168
5405
|
)
|
|
5169
5406
|
] }),
|
|
5170
|
-
expanded ? /* @__PURE__ */
|
|
5407
|
+
expanded ? /* @__PURE__ */ jsxs23(View28, { style: { marginTop: 16, marginLeft: 56 }, children: [
|
|
5171
5408
|
/* @__PURE__ */ jsx40(
|
|
5172
5409
|
Text,
|
|
5173
5410
|
{
|
|
@@ -5207,12 +5444,12 @@ import { Animated as Animated9, FlatList, View as View31, useWindowDimensions as
|
|
|
5207
5444
|
|
|
5208
5445
|
// src/components/merge-requests/ReviewMergeRequestCard.tsx
|
|
5209
5446
|
import * as React30 from "react";
|
|
5210
|
-
import { ActivityIndicator as ActivityIndicator5, Animated as Animated8, Pressable as
|
|
5447
|
+
import { ActivityIndicator as ActivityIndicator5, Animated as Animated8, Pressable as Pressable12, View as View30 } from "react-native";
|
|
5211
5448
|
import { Check as Check4, ChevronDown as ChevronDown3, Play as Play3, X as X3 } from "lucide-react-native";
|
|
5212
5449
|
|
|
5213
5450
|
// src/components/merge-requests/ReviewMergeRequestActionButton.tsx
|
|
5214
5451
|
import * as React29 from "react";
|
|
5215
|
-
import { Pressable as
|
|
5452
|
+
import { Pressable as Pressable11, View as View29 } from "react-native";
|
|
5216
5453
|
import { jsx as jsx41 } from "react/jsx-runtime";
|
|
5217
5454
|
function ReviewMergeRequestActionButton({
|
|
5218
5455
|
accessibilityLabel,
|
|
@@ -5244,7 +5481,7 @@ function ReviewMergeRequestActionButton({
|
|
|
5244
5481
|
justifyContent: "center"
|
|
5245
5482
|
},
|
|
5246
5483
|
children: /* @__PURE__ */ jsx41(
|
|
5247
|
-
|
|
5484
|
+
Pressable11,
|
|
5248
5485
|
{
|
|
5249
5486
|
accessibilityRole: "button",
|
|
5250
5487
|
accessibilityLabel,
|
|
@@ -5267,7 +5504,7 @@ function ReviewMergeRequestActionButton({
|
|
|
5267
5504
|
}
|
|
5268
5505
|
|
|
5269
5506
|
// src/components/merge-requests/ReviewMergeRequestCard.tsx
|
|
5270
|
-
import { jsx as jsx42, jsxs as
|
|
5507
|
+
import { jsx as jsx42, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
5271
5508
|
function ReviewMergeRequestCard({
|
|
5272
5509
|
mr,
|
|
5273
5510
|
index,
|
|
@@ -5291,7 +5528,7 @@ function ReviewMergeRequestCard({
|
|
|
5291
5528
|
Animated8.timing(rotate, { toValue: isExpanded ? 1 : 0, duration: 200, useNativeDriver: true }).start();
|
|
5292
5529
|
}, [isExpanded, rotate]);
|
|
5293
5530
|
const position = total > 1 ? `${index + 1}/${total}` : "Merge request";
|
|
5294
|
-
return /* @__PURE__ */ jsx42(
|
|
5531
|
+
return /* @__PURE__ */ jsx42(Pressable12, { onPress: onToggle, style: ({ pressed }) => ({ opacity: pressed ? 0.95 : 1 }), children: /* @__PURE__ */ jsxs24(
|
|
5295
5532
|
Card,
|
|
5296
5533
|
{
|
|
5297
5534
|
padded: false,
|
|
@@ -5304,9 +5541,9 @@ function ReviewMergeRequestCard({
|
|
|
5304
5541
|
}
|
|
5305
5542
|
],
|
|
5306
5543
|
children: [
|
|
5307
|
-
/* @__PURE__ */
|
|
5544
|
+
/* @__PURE__ */ jsxs24(View30, { style: { flexDirection: "row", alignItems: "center", gap: 12 }, children: [
|
|
5308
5545
|
/* @__PURE__ */ jsx42(Avatar, { size: 40, uri: (creator == null ? void 0 : creator.avatar) ?? null, name: (creator == null ? void 0 : creator.name) ?? void 0 }),
|
|
5309
|
-
/* @__PURE__ */
|
|
5546
|
+
/* @__PURE__ */ jsxs24(View30, { style: { flex: 1, minWidth: 0 }, children: [
|
|
5310
5547
|
/* @__PURE__ */ jsx42(
|
|
5311
5548
|
Text,
|
|
5312
5549
|
{
|
|
@@ -5315,7 +5552,7 @@ function ReviewMergeRequestCard({
|
|
|
5315
5552
|
children: mr.title ?? "Untitled merge request"
|
|
5316
5553
|
}
|
|
5317
5554
|
),
|
|
5318
|
-
/* @__PURE__ */
|
|
5555
|
+
/* @__PURE__ */ jsxs24(Text, { style: { color: theme.colors.textMuted, fontSize: 12, lineHeight: 16 }, numberOfLines: 1, children: [
|
|
5319
5556
|
(creator == null ? void 0 : creator.name) ?? "Loading...",
|
|
5320
5557
|
" \xB7 ",
|
|
5321
5558
|
position
|
|
@@ -5331,7 +5568,7 @@ function ReviewMergeRequestCard({
|
|
|
5331
5568
|
}
|
|
5332
5569
|
)
|
|
5333
5570
|
] }),
|
|
5334
|
-
isExpanded ? /* @__PURE__ */
|
|
5571
|
+
isExpanded ? /* @__PURE__ */ jsxs24(View30, { style: { marginTop: 16 }, children: [
|
|
5335
5572
|
/* @__PURE__ */ jsx42(
|
|
5336
5573
|
Text,
|
|
5337
5574
|
{
|
|
@@ -5346,12 +5583,12 @@ function ReviewMergeRequestCard({
|
|
|
5346
5583
|
children: status.text
|
|
5347
5584
|
}
|
|
5348
5585
|
),
|
|
5349
|
-
/* @__PURE__ */ jsx42(Text, { style: { color: theme.colors.textMuted, fontSize: 12, lineHeight: 16, marginBottom: 12 }, children: creator ? `${creator.
|
|
5586
|
+
/* @__PURE__ */ jsx42(Text, { style: { color: theme.colors.textMuted, fontSize: 12, lineHeight: 16, marginBottom: 12 }, children: creator ? `${creator.approvedOrMergedMergeRequests} approved merge${creator.approvedOrMergedMergeRequests !== 1 ? "s" : ""}` : "Loading stats..." }),
|
|
5350
5587
|
mr.description ? /* @__PURE__ */ jsx42(MarkdownText, { markdown: mr.description, variant: "mergeRequest" }) : null
|
|
5351
5588
|
] }) : null,
|
|
5352
5589
|
/* @__PURE__ */ jsx42(View30, { style: { height: 1, backgroundColor: withAlpha(theme.colors.borderStrong, 0.5), marginTop: 12, marginBottom: 12 } }),
|
|
5353
|
-
/* @__PURE__ */
|
|
5354
|
-
/* @__PURE__ */
|
|
5590
|
+
/* @__PURE__ */ jsxs24(View30, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
5591
|
+
/* @__PURE__ */ jsxs24(View30, { style: { flexDirection: "row", gap: 8 }, children: [
|
|
5355
5592
|
/* @__PURE__ */ jsx42(
|
|
5356
5593
|
ReviewMergeRequestActionButton,
|
|
5357
5594
|
{
|
|
@@ -5360,7 +5597,7 @@ function ReviewMergeRequestCard({
|
|
|
5360
5597
|
disabled: !canAct || isAnyProcessing,
|
|
5361
5598
|
onPress: onReject,
|
|
5362
5599
|
iconOnly: !isExpanded,
|
|
5363
|
-
children: /* @__PURE__ */
|
|
5600
|
+
children: /* @__PURE__ */ jsxs24(View30, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
|
|
5364
5601
|
/* @__PURE__ */ jsx42(X3, { size: 18, color: "#FFFFFF" }),
|
|
5365
5602
|
isExpanded ? /* @__PURE__ */ jsx42(Text, { style: { fontSize: 13, color: "#FFFFFF", fontWeight: theme.typography.fontWeight.semibold }, children: "Reject" }) : null
|
|
5366
5603
|
] })
|
|
@@ -5374,10 +5611,10 @@ function ReviewMergeRequestCard({
|
|
|
5374
5611
|
disabled: !canAct || isAnyProcessing,
|
|
5375
5612
|
onPress: onApprove,
|
|
5376
5613
|
iconOnly: !isExpanded,
|
|
5377
|
-
children: isProcessing ? /* @__PURE__ */
|
|
5614
|
+
children: isProcessing ? /* @__PURE__ */ jsxs24(View30, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
|
|
5378
5615
|
/* @__PURE__ */ jsx42(ActivityIndicator5, { size: "small", color: "#FFFFFF" }),
|
|
5379
5616
|
isExpanded ? /* @__PURE__ */ jsx42(Text, { style: { fontSize: 13, color: "#FFFFFF", fontWeight: theme.typography.fontWeight.semibold }, children: "Processing" }) : null
|
|
5380
|
-
] }) : /* @__PURE__ */
|
|
5617
|
+
] }) : /* @__PURE__ */ jsxs24(View30, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
|
|
5381
5618
|
/* @__PURE__ */ jsx42(Check4, { size: 18, color: "#FFFFFF" }),
|
|
5382
5619
|
isExpanded ? /* @__PURE__ */ jsx42(Text, { style: { fontSize: 13, color: "#FFFFFF", fontWeight: theme.typography.fontWeight.semibold }, children: "Approve" }) : null
|
|
5383
5620
|
] })
|
|
@@ -5392,7 +5629,7 @@ function ReviewMergeRequestCard({
|
|
|
5392
5629
|
disabled: isBuilding || isTestingThis,
|
|
5393
5630
|
onPress: onTest,
|
|
5394
5631
|
iconOnly: !isExpanded,
|
|
5395
|
-
children: isTestingThis ? /* @__PURE__ */ jsx42(ActivityIndicator5, { size: "small", color: "#888" }) : /* @__PURE__ */
|
|
5632
|
+
children: isTestingThis ? /* @__PURE__ */ jsx42(ActivityIndicator5, { size: "small", color: "#888" }) : /* @__PURE__ */ jsxs24(View30, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
|
|
5396
5633
|
/* @__PURE__ */ jsx42(Play3, { size: 14, color: theme.colors.text }),
|
|
5397
5634
|
isExpanded ? /* @__PURE__ */ jsx42(Text, { style: { fontSize: 13, color: theme.colors.text, fontWeight: theme.typography.fontWeight.semibold }, children: "Test" }) : null
|
|
5398
5635
|
] })
|
|
@@ -5405,7 +5642,7 @@ function ReviewMergeRequestCard({
|
|
|
5405
5642
|
}
|
|
5406
5643
|
|
|
5407
5644
|
// src/components/merge-requests/ReviewMergeRequestCarousel.tsx
|
|
5408
|
-
import { jsx as jsx43, jsxs as
|
|
5645
|
+
import { jsx as jsx43, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
5409
5646
|
function ReviewMergeRequestCarousel({
|
|
5410
5647
|
mergeRequests,
|
|
5411
5648
|
creatorStatsById,
|
|
@@ -5427,7 +5664,7 @@ function ReviewMergeRequestCarousel({
|
|
|
5427
5664
|
const snapInterval = cardWidth + gap;
|
|
5428
5665
|
const dotColor = theme.scheme === "dark" ? "#FFFFFF" : "#000000";
|
|
5429
5666
|
if (mergeRequests.length === 0) return null;
|
|
5430
|
-
return /* @__PURE__ */
|
|
5667
|
+
return /* @__PURE__ */ jsxs25(View31, { style: [{ marginHorizontal: -theme.spacing.lg }, style], children: [
|
|
5431
5668
|
/* @__PURE__ */ jsx43(
|
|
5432
5669
|
FlatList,
|
|
5433
5670
|
{
|
|
@@ -5506,7 +5743,7 @@ function ReviewMergeRequestCarousel({
|
|
|
5506
5743
|
}
|
|
5507
5744
|
|
|
5508
5745
|
// src/studio/ui/preview-panel/PreviewCollaborateSection.tsx
|
|
5509
|
-
import { Fragment as Fragment5, jsx as jsx44, jsxs as
|
|
5746
|
+
import { Fragment as Fragment5, jsx as jsx44, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
5510
5747
|
function PreviewCollaborateSection({
|
|
5511
5748
|
canSubmitMergeRequest,
|
|
5512
5749
|
canSyncUpstream,
|
|
@@ -5532,7 +5769,7 @@ function PreviewCollaborateSection({
|
|
|
5532
5769
|
if (!hasSection) return null;
|
|
5533
5770
|
const isSyncing = Boolean(syncingUpstream || syncingLocal);
|
|
5534
5771
|
const showActionsSubtitle = canSubmitMergeRequest && onSubmitMergeRequest || canSyncUpstream && onSyncUpstream || onTestMr && incomingMergeRequests.length > 0;
|
|
5535
|
-
return /* @__PURE__ */
|
|
5772
|
+
return /* @__PURE__ */ jsxs26(Fragment5, { children: [
|
|
5536
5773
|
/* @__PURE__ */ jsx44(SectionTitle, { marginTop: theme.spacing.xl, children: "Collaborate" }),
|
|
5537
5774
|
showActionsSubtitle ? /* @__PURE__ */ jsx44(
|
|
5538
5775
|
Text,
|
|
@@ -5671,7 +5908,7 @@ function PreviewCollaborateSection({
|
|
|
5671
5908
|
onTest: (mr) => onTestMr ? onTestMr(mr) : void 0
|
|
5672
5909
|
}
|
|
5673
5910
|
) : null,
|
|
5674
|
-
outgoingMergeRequests.length > 0 ? /* @__PURE__ */
|
|
5911
|
+
outgoingMergeRequests.length > 0 ? /* @__PURE__ */ jsxs26(Fragment5, { children: [
|
|
5675
5912
|
/* @__PURE__ */ jsx44(
|
|
5676
5913
|
Text,
|
|
5677
5914
|
{
|
|
@@ -5986,7 +6223,7 @@ function usePreviewPanelData(params) {
|
|
|
5986
6223
|
}
|
|
5987
6224
|
|
|
5988
6225
|
// src/studio/ui/PreviewPanel.tsx
|
|
5989
|
-
import { jsx as jsx45, jsxs as
|
|
6226
|
+
import { jsx as jsx45, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
5990
6227
|
function PreviewPanel({
|
|
5991
6228
|
app,
|
|
5992
6229
|
loading,
|
|
@@ -6021,7 +6258,7 @@ ${shareUrl}` : `Check out this app on Remix
|
|
|
6021
6258
|
${shareUrl}`;
|
|
6022
6259
|
try {
|
|
6023
6260
|
const title = app.name ?? "Remix app";
|
|
6024
|
-
const payload =
|
|
6261
|
+
const payload = Platform7.OS === "ios" ? {
|
|
6025
6262
|
title,
|
|
6026
6263
|
message
|
|
6027
6264
|
} : {
|
|
@@ -6063,13 +6300,13 @@ ${shareUrl}`;
|
|
|
6063
6300
|
}
|
|
6064
6301
|
);
|
|
6065
6302
|
if (loading || !app) {
|
|
6066
|
-
return /* @__PURE__ */ jsx45(PreviewPage, { header, children: /* @__PURE__ */
|
|
6303
|
+
return /* @__PURE__ */ jsx45(PreviewPage, { header, children: /* @__PURE__ */ jsxs27(View33, { style: { flex: 1, justifyContent: "center", alignItems: "center", padding: 24 }, children: [
|
|
6067
6304
|
/* @__PURE__ */ jsx45(ActivityIndicator7, {}),
|
|
6068
6305
|
/* @__PURE__ */ jsx45(View33, { style: { height: 12 } }),
|
|
6069
6306
|
/* @__PURE__ */ jsx45(Text, { variant: "bodyMuted", children: "Loading app\u2026" })
|
|
6070
6307
|
] }) });
|
|
6071
6308
|
}
|
|
6072
|
-
return /* @__PURE__ */
|
|
6309
|
+
return /* @__PURE__ */ jsxs27(PreviewPage, { header, children: [
|
|
6073
6310
|
/* @__PURE__ */ jsx45(
|
|
6074
6311
|
PreviewHeroSection,
|
|
6075
6312
|
{
|
|
@@ -6130,7 +6367,7 @@ import { ActivityIndicator as ActivityIndicator9, View as View42 } from "react-n
|
|
|
6130
6367
|
|
|
6131
6368
|
// src/components/chat/ChatPage.tsx
|
|
6132
6369
|
import * as React38 from "react";
|
|
6133
|
-
import {
|
|
6370
|
+
import { Platform as Platform9, View as View37 } from "react-native";
|
|
6134
6371
|
import { useSafeAreaInsets as useSafeAreaInsets4 } from "react-native-safe-area-context";
|
|
6135
6372
|
|
|
6136
6373
|
// src/components/chat/ChatMessageList.tsx
|
|
@@ -6140,9 +6377,76 @@ import { BottomSheetFlatList } from "@gorhom/bottom-sheet";
|
|
|
6140
6377
|
|
|
6141
6378
|
// src/components/chat/ChatMessageBubble.tsx
|
|
6142
6379
|
import { View as View34 } from "react-native";
|
|
6143
|
-
import { CheckCheck as CheckCheck2, GitMerge as GitMerge2 } from "lucide-react-native";
|
|
6144
|
-
|
|
6145
|
-
|
|
6380
|
+
import { CheckCheck as CheckCheck2, GitMerge as GitMerge2, RotateCcw } from "lucide-react-native";
|
|
6381
|
+
|
|
6382
|
+
// src/components/primitives/Button.tsx
|
|
6383
|
+
import {
|
|
6384
|
+
Pressable as Pressable13
|
|
6385
|
+
} from "react-native";
|
|
6386
|
+
import { jsx as jsx46 } from "react/jsx-runtime";
|
|
6387
|
+
function backgroundFor2(variant, theme, pressed, disabled) {
|
|
6388
|
+
const { colors } = theme;
|
|
6389
|
+
if (variant === "ghost") return "transparent";
|
|
6390
|
+
if (disabled) {
|
|
6391
|
+
return colors.neutral;
|
|
6392
|
+
}
|
|
6393
|
+
const base = variant === "primary" ? colors.primary : variant === "danger" ? colors.danger : colors.neutral;
|
|
6394
|
+
if (!pressed) return base;
|
|
6395
|
+
return base;
|
|
6396
|
+
}
|
|
6397
|
+
function borderFor(variant, theme) {
|
|
6398
|
+
if (variant !== "ghost") return {};
|
|
6399
|
+
return { borderWidth: 1, borderColor: theme.colors.border };
|
|
6400
|
+
}
|
|
6401
|
+
function paddingFor(size, theme) {
|
|
6402
|
+
switch (size) {
|
|
6403
|
+
case "sm":
|
|
6404
|
+
return { paddingHorizontal: theme.spacing.md, paddingVertical: theme.spacing.sm, minHeight: 36 };
|
|
6405
|
+
case "icon":
|
|
6406
|
+
return { paddingHorizontal: 0, paddingVertical: 0, minHeight: 44, minWidth: 44 };
|
|
6407
|
+
case "md":
|
|
6408
|
+
default:
|
|
6409
|
+
return { paddingHorizontal: theme.spacing.lg, paddingVertical: theme.spacing.md, minHeight: 44 };
|
|
6410
|
+
}
|
|
6411
|
+
}
|
|
6412
|
+
function Button({
|
|
6413
|
+
variant = "neutral",
|
|
6414
|
+
size = "md",
|
|
6415
|
+
disabled,
|
|
6416
|
+
style,
|
|
6417
|
+
children,
|
|
6418
|
+
...props
|
|
6419
|
+
}) {
|
|
6420
|
+
const theme = useTheme();
|
|
6421
|
+
const isDisabled = disabled ?? void 0;
|
|
6422
|
+
return /* @__PURE__ */ jsx46(
|
|
6423
|
+
Pressable13,
|
|
6424
|
+
{
|
|
6425
|
+
...props,
|
|
6426
|
+
disabled: isDisabled,
|
|
6427
|
+
style: (state) => {
|
|
6428
|
+
const pressed = state.pressed;
|
|
6429
|
+
const base = {
|
|
6430
|
+
alignItems: "center",
|
|
6431
|
+
justifyContent: "center",
|
|
6432
|
+
flexDirection: "row",
|
|
6433
|
+
borderRadius: size === "icon" ? theme.radii.pill : theme.radii.pill,
|
|
6434
|
+
backgroundColor: backgroundFor2(variant, theme, pressed, isDisabled),
|
|
6435
|
+
opacity: pressed && !isDisabled ? 0.92 : 1,
|
|
6436
|
+
...paddingFor(size, theme),
|
|
6437
|
+
...borderFor(variant, theme)
|
|
6438
|
+
};
|
|
6439
|
+
const resolved = typeof style === "function" ? style({ pressed, disabled: isDisabled }) : style;
|
|
6440
|
+
return [base, resolved];
|
|
6441
|
+
},
|
|
6442
|
+
children
|
|
6443
|
+
}
|
|
6444
|
+
);
|
|
6445
|
+
}
|
|
6446
|
+
|
|
6447
|
+
// src/components/chat/ChatMessageBubble.tsx
|
|
6448
|
+
import { jsx as jsx47, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
6449
|
+
function ChatMessageBubble({ message, renderContent, isLast, retrying, onRetry, style }) {
|
|
6146
6450
|
var _a, _b;
|
|
6147
6451
|
const theme = useTheme();
|
|
6148
6452
|
const metaEvent = ((_a = message.meta) == null ? void 0 : _a.event) ?? null;
|
|
@@ -6157,34 +6461,62 @@ function ChatMessageBubble({ message, renderContent, style }) {
|
|
|
6157
6461
|
const bubbleVariant = isHuman ? "surface" : "surfaceRaised";
|
|
6158
6462
|
const cornerStyle = isHuman ? { borderTopRightRadius: 0 } : { borderTopLeftRadius: 0 };
|
|
6159
6463
|
const bodyColor = metaStatus === "success" ? theme.colors.success : metaStatus === "error" ? theme.colors.danger : void 0;
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
/* @__PURE__ */
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6464
|
+
const showRetry = Boolean(onRetry) && isLast && metaStatus === "error" && message.author === "human";
|
|
6465
|
+
const retryLabel = retrying ? "Retrying..." : "Retry";
|
|
6466
|
+
return /* @__PURE__ */ jsxs28(View34, { style: [align, style], children: [
|
|
6467
|
+
/* @__PURE__ */ jsx47(
|
|
6468
|
+
Surface,
|
|
6469
|
+
{
|
|
6470
|
+
variant: bubbleVariant,
|
|
6471
|
+
style: [
|
|
6472
|
+
{
|
|
6473
|
+
maxWidth: "85%",
|
|
6474
|
+
borderRadius: theme.radii.lg,
|
|
6475
|
+
paddingHorizontal: theme.spacing.lg,
|
|
6476
|
+
paddingVertical: theme.spacing.md,
|
|
6477
|
+
borderWidth: 1,
|
|
6478
|
+
borderColor: theme.colors.border
|
|
6479
|
+
},
|
|
6480
|
+
cornerStyle
|
|
6481
|
+
],
|
|
6482
|
+
children: /* @__PURE__ */ jsxs28(View34, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
6483
|
+
isMergeCompleted || isSyncCompleted ? /* @__PURE__ */ jsx47(CheckCheck2, { size: 16, color: theme.colors.success, style: { marginRight: theme.spacing.sm } }) : null,
|
|
6484
|
+
isMergeApproved || isSyncStarted ? /* @__PURE__ */ jsx47(GitMerge2, { size: 16, color: theme.colors.text, style: { marginRight: theme.spacing.sm } }) : null,
|
|
6485
|
+
/* @__PURE__ */ jsx47(View34, { style: { flexShrink: 1, minWidth: 0 }, children: renderContent ? renderContent(message) : /* @__PURE__ */ jsx47(MarkdownText, { markdown: message.content, variant: "chat", bodyColor }) })
|
|
6486
|
+
] })
|
|
6487
|
+
}
|
|
6488
|
+
),
|
|
6489
|
+
showRetry ? /* @__PURE__ */ jsx47(View34, { style: { marginTop: theme.spacing.xs, alignSelf: align.alignSelf }, children: /* @__PURE__ */ jsx47(
|
|
6490
|
+
Button,
|
|
6491
|
+
{
|
|
6492
|
+
variant: "ghost",
|
|
6493
|
+
size: "sm",
|
|
6494
|
+
onPress: onRetry,
|
|
6495
|
+
disabled: retrying,
|
|
6496
|
+
style: { borderColor: theme.colors.danger },
|
|
6497
|
+
accessibilityLabel: "Retry send",
|
|
6498
|
+
children: /* @__PURE__ */ jsxs28(View34, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
6499
|
+
!retrying ? /* @__PURE__ */ jsx47(RotateCcw, { size: 14, color: theme.colors.danger }) : null,
|
|
6500
|
+
/* @__PURE__ */ jsx47(
|
|
6501
|
+
Text,
|
|
6502
|
+
{
|
|
6503
|
+
variant: "caption",
|
|
6504
|
+
color: theme.colors.danger,
|
|
6505
|
+
style: { marginLeft: retrying ? 0 : theme.spacing.xs },
|
|
6506
|
+
numberOfLines: 1,
|
|
6507
|
+
children: retryLabel
|
|
6508
|
+
}
|
|
6509
|
+
)
|
|
6510
|
+
] })
|
|
6511
|
+
}
|
|
6512
|
+
) }) : null
|
|
6513
|
+
] });
|
|
6182
6514
|
}
|
|
6183
6515
|
|
|
6184
6516
|
// src/components/chat/TypingIndicator.tsx
|
|
6185
6517
|
import * as React36 from "react";
|
|
6186
6518
|
import { Animated as Animated10, View as View35 } from "react-native";
|
|
6187
|
-
import { jsx as
|
|
6519
|
+
import { jsx as jsx48 } from "react/jsx-runtime";
|
|
6188
6520
|
function TypingIndicator({ style }) {
|
|
6189
6521
|
const theme = useTheme();
|
|
6190
6522
|
const dotColor = theme.colors.textSubtle;
|
|
@@ -6207,7 +6539,7 @@ function TypingIndicator({ style }) {
|
|
|
6207
6539
|
loops.forEach((l) => l.stop());
|
|
6208
6540
|
};
|
|
6209
6541
|
}, [anims]);
|
|
6210
|
-
return /* @__PURE__ */
|
|
6542
|
+
return /* @__PURE__ */ jsx48(View35, { style: [{ flexDirection: "row", alignItems: "center" }, style], children: anims.map((a, i) => /* @__PURE__ */ jsx48(
|
|
6211
6543
|
Animated10.View,
|
|
6212
6544
|
{
|
|
6213
6545
|
style: {
|
|
@@ -6225,12 +6557,14 @@ function TypingIndicator({ style }) {
|
|
|
6225
6557
|
}
|
|
6226
6558
|
|
|
6227
6559
|
// src/components/chat/ChatMessageList.tsx
|
|
6228
|
-
import { jsx as
|
|
6560
|
+
import { jsx as jsx49, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
6229
6561
|
var ChatMessageList = React37.forwardRef(
|
|
6230
6562
|
({
|
|
6231
6563
|
messages,
|
|
6232
6564
|
showTypingIndicator = false,
|
|
6233
6565
|
renderMessageContent,
|
|
6566
|
+
onRetryMessage,
|
|
6567
|
+
isRetryingMessage,
|
|
6234
6568
|
contentStyle,
|
|
6235
6569
|
bottomInset = 0,
|
|
6236
6570
|
onNearBottomChange,
|
|
@@ -6244,6 +6578,7 @@ var ChatMessageList = React37.forwardRef(
|
|
|
6244
6578
|
const data = React37.useMemo(() => {
|
|
6245
6579
|
return [...messages].reverse();
|
|
6246
6580
|
}, [messages]);
|
|
6581
|
+
const lastMessageId = messages.length > 0 ? messages[messages.length - 1].id : null;
|
|
6247
6582
|
const scrollToBottom = React37.useCallback((options) => {
|
|
6248
6583
|
var _a;
|
|
6249
6584
|
const animated = (options == null ? void 0 : options.animated) ?? true;
|
|
@@ -6279,7 +6614,7 @@ var ChatMessageList = React37.forwardRef(
|
|
|
6279
6614
|
}
|
|
6280
6615
|
return void 0;
|
|
6281
6616
|
}, [showTypingIndicator, scrollToBottom]);
|
|
6282
|
-
return /* @__PURE__ */
|
|
6617
|
+
return /* @__PURE__ */ jsx49(
|
|
6283
6618
|
BottomSheetFlatList,
|
|
6284
6619
|
{
|
|
6285
6620
|
ref: listRef,
|
|
@@ -6305,11 +6640,20 @@ var ChatMessageList = React37.forwardRef(
|
|
|
6305
6640
|
},
|
|
6306
6641
|
contentStyle
|
|
6307
6642
|
],
|
|
6308
|
-
ItemSeparatorComponent: () => /* @__PURE__ */
|
|
6309
|
-
renderItem: ({ item }) => /* @__PURE__ */
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6643
|
+
ItemSeparatorComponent: () => /* @__PURE__ */ jsx49(View36, { style: { height: theme.spacing.sm } }),
|
|
6644
|
+
renderItem: ({ item }) => /* @__PURE__ */ jsx49(
|
|
6645
|
+
ChatMessageBubble,
|
|
6646
|
+
{
|
|
6647
|
+
message: item,
|
|
6648
|
+
renderContent: renderMessageContent,
|
|
6649
|
+
isLast: Boolean(lastMessageId && item.id === lastMessageId),
|
|
6650
|
+
retrying: (isRetryingMessage == null ? void 0 : isRetryingMessage(item.id)) ?? false,
|
|
6651
|
+
onRetry: onRetryMessage ? () => onRetryMessage(item.id) : void 0
|
|
6652
|
+
}
|
|
6653
|
+
),
|
|
6654
|
+
ListHeaderComponent: /* @__PURE__ */ jsxs29(View36, { children: [
|
|
6655
|
+
showTypingIndicator ? /* @__PURE__ */ jsx49(View36, { style: { marginTop: theme.spacing.sm, alignSelf: "flex-start", paddingHorizontal: theme.spacing.lg }, children: /* @__PURE__ */ jsx49(TypingIndicator, {}) }) : null,
|
|
6656
|
+
bottomInset > 0 ? /* @__PURE__ */ jsx49(View36, { style: { height: bottomInset } }) : null
|
|
6313
6657
|
] })
|
|
6314
6658
|
}
|
|
6315
6659
|
);
|
|
@@ -6318,12 +6662,14 @@ var ChatMessageList = React37.forwardRef(
|
|
|
6318
6662
|
ChatMessageList.displayName = "ChatMessageList";
|
|
6319
6663
|
|
|
6320
6664
|
// src/components/chat/ChatPage.tsx
|
|
6321
|
-
import { jsx as
|
|
6665
|
+
import { jsx as jsx50, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
6322
6666
|
function ChatPage({
|
|
6323
6667
|
header,
|
|
6324
6668
|
messages,
|
|
6325
6669
|
showTypingIndicator,
|
|
6326
6670
|
renderMessageContent,
|
|
6671
|
+
onRetryMessage,
|
|
6672
|
+
isRetryingMessage,
|
|
6327
6673
|
topBanner,
|
|
6328
6674
|
composerTop,
|
|
6329
6675
|
composer,
|
|
@@ -6337,17 +6683,7 @@ function ChatPage({
|
|
|
6337
6683
|
const insets = useSafeAreaInsets4();
|
|
6338
6684
|
const [composerHeight, setComposerHeight] = React38.useState(0);
|
|
6339
6685
|
const [composerTopHeight, setComposerTopHeight] = React38.useState(0);
|
|
6340
|
-
const
|
|
6341
|
-
React38.useEffect(() => {
|
|
6342
|
-
if (Platform10.OS !== "ios") return;
|
|
6343
|
-
const show = Keyboard4.addListener("keyboardWillShow", () => setKeyboardVisible(true));
|
|
6344
|
-
const hide = Keyboard4.addListener("keyboardWillHide", () => setKeyboardVisible(false));
|
|
6345
|
-
return () => {
|
|
6346
|
-
show.remove();
|
|
6347
|
-
hide.remove();
|
|
6348
|
-
};
|
|
6349
|
-
}, []);
|
|
6350
|
-
const footerBottomPadding = Platform10.OS === "ios" ? keyboardVisible ? 0 : insets.bottom : insets.bottom + 10;
|
|
6686
|
+
const footerBottomPadding = Platform9.OS === "ios" ? insets.bottom : insets.bottom + 10;
|
|
6351
6687
|
const totalComposerHeight = composerHeight + composerTopHeight;
|
|
6352
6688
|
const overlayBottom = totalComposerHeight + footerBottomPadding + theme.spacing.lg;
|
|
6353
6689
|
const bottomInset = totalComposerHeight + footerBottomPadding + theme.spacing.xl;
|
|
@@ -6364,22 +6700,24 @@ function ChatPage({
|
|
|
6364
6700
|
if (composerTop) return;
|
|
6365
6701
|
setComposerTopHeight(0);
|
|
6366
6702
|
}, [composerTop]);
|
|
6367
|
-
return /* @__PURE__ */
|
|
6368
|
-
header ? /* @__PURE__ */
|
|
6369
|
-
topBanner ? /* @__PURE__ */
|
|
6370
|
-
/* @__PURE__ */
|
|
6371
|
-
/* @__PURE__ */
|
|
6703
|
+
return /* @__PURE__ */ jsxs30(View37, { style: [{ flex: 1 }, style], children: [
|
|
6704
|
+
header ? /* @__PURE__ */ jsx50(View37, { children: header }) : null,
|
|
6705
|
+
topBanner ? /* @__PURE__ */ jsx50(View37, { style: { paddingHorizontal: theme.spacing.lg, paddingTop: theme.spacing.sm }, children: topBanner }) : null,
|
|
6706
|
+
/* @__PURE__ */ jsxs30(View37, { style: { flex: 1 }, children: [
|
|
6707
|
+
/* @__PURE__ */ jsxs30(
|
|
6372
6708
|
View37,
|
|
6373
6709
|
{
|
|
6374
6710
|
style: { flex: 1 },
|
|
6375
6711
|
children: [
|
|
6376
|
-
/* @__PURE__ */
|
|
6712
|
+
/* @__PURE__ */ jsx50(
|
|
6377
6713
|
ChatMessageList,
|
|
6378
6714
|
{
|
|
6379
6715
|
ref: listRef,
|
|
6380
6716
|
messages,
|
|
6381
6717
|
showTypingIndicator,
|
|
6382
6718
|
renderMessageContent,
|
|
6719
|
+
onRetryMessage,
|
|
6720
|
+
isRetryingMessage,
|
|
6383
6721
|
onNearBottomChange,
|
|
6384
6722
|
bottomInset
|
|
6385
6723
|
}
|
|
@@ -6388,7 +6726,7 @@ function ChatPage({
|
|
|
6388
6726
|
]
|
|
6389
6727
|
}
|
|
6390
6728
|
),
|
|
6391
|
-
/* @__PURE__ */
|
|
6729
|
+
/* @__PURE__ */ jsxs30(
|
|
6392
6730
|
View37,
|
|
6393
6731
|
{
|
|
6394
6732
|
style: {
|
|
@@ -6401,7 +6739,7 @@ function ChatPage({
|
|
|
6401
6739
|
paddingBottom: footerBottomPadding
|
|
6402
6740
|
},
|
|
6403
6741
|
children: [
|
|
6404
|
-
composerTop ? /* @__PURE__ */
|
|
6742
|
+
composerTop ? /* @__PURE__ */ jsx50(
|
|
6405
6743
|
View37,
|
|
6406
6744
|
{
|
|
6407
6745
|
style: { marginBottom: theme.spacing.sm },
|
|
@@ -6409,7 +6747,7 @@ function ChatPage({
|
|
|
6409
6747
|
children: composerTop
|
|
6410
6748
|
}
|
|
6411
6749
|
) : null,
|
|
6412
|
-
/* @__PURE__ */
|
|
6750
|
+
/* @__PURE__ */ jsx50(
|
|
6413
6751
|
ChatComposer,
|
|
6414
6752
|
{
|
|
6415
6753
|
...composer,
|
|
@@ -6426,9 +6764,9 @@ function ChatPage({
|
|
|
6426
6764
|
|
|
6427
6765
|
// src/components/chat/ScrollToBottomButton.tsx
|
|
6428
6766
|
import * as React39 from "react";
|
|
6429
|
-
import { Pressable as
|
|
6767
|
+
import { Pressable as Pressable14, View as View38 } from "react-native";
|
|
6430
6768
|
import Animated11, { Easing as Easing2, useAnimatedStyle as useAnimatedStyle2, useSharedValue as useSharedValue2, withTiming as withTiming2 } from "react-native-reanimated";
|
|
6431
|
-
import { jsx as
|
|
6769
|
+
import { jsx as jsx51 } from "react/jsx-runtime";
|
|
6432
6770
|
function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
6433
6771
|
const theme = useTheme();
|
|
6434
6772
|
const progress = useSharedValue2(visible ? 1 : 0);
|
|
@@ -6442,7 +6780,7 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
|
6442
6780
|
}));
|
|
6443
6781
|
const bg = theme.scheme === "dark" ? "rgba(39,39,42,0.9)" : "rgba(244,244,245,0.95)";
|
|
6444
6782
|
const border = theme.scheme === "dark" ? withAlpha("#FFFFFF", 0.12) : withAlpha("#000000", 0.08);
|
|
6445
|
-
return /* @__PURE__ */
|
|
6783
|
+
return /* @__PURE__ */ jsx51(
|
|
6446
6784
|
Animated11.View,
|
|
6447
6785
|
{
|
|
6448
6786
|
pointerEvents: visible ? "auto" : "none",
|
|
@@ -6456,7 +6794,7 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
|
6456
6794
|
style,
|
|
6457
6795
|
animStyle
|
|
6458
6796
|
],
|
|
6459
|
-
children: /* @__PURE__ */
|
|
6797
|
+
children: /* @__PURE__ */ jsx51(
|
|
6460
6798
|
View38,
|
|
6461
6799
|
{
|
|
6462
6800
|
style: {
|
|
@@ -6475,8 +6813,8 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
|
6475
6813
|
elevation: 5,
|
|
6476
6814
|
opacity: pressed ? 0.85 : 1
|
|
6477
6815
|
},
|
|
6478
|
-
children: /* @__PURE__ */
|
|
6479
|
-
|
|
6816
|
+
children: /* @__PURE__ */ jsx51(
|
|
6817
|
+
Pressable14,
|
|
6480
6818
|
{
|
|
6481
6819
|
onPress,
|
|
6482
6820
|
onPressIn: () => setPressed(true),
|
|
@@ -6494,7 +6832,7 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
|
6494
6832
|
|
|
6495
6833
|
// src/components/chat/ChatHeader.tsx
|
|
6496
6834
|
import { StyleSheet as StyleSheet4 } from "react-native";
|
|
6497
|
-
import { jsx as
|
|
6835
|
+
import { jsx as jsx52 } from "react/jsx-runtime";
|
|
6498
6836
|
function ChatHeader({ left, right, center, style }) {
|
|
6499
6837
|
const flattenedStyle = StyleSheet4.flatten([
|
|
6500
6838
|
{
|
|
@@ -6502,7 +6840,7 @@ function ChatHeader({ left, right, center, style }) {
|
|
|
6502
6840
|
},
|
|
6503
6841
|
style
|
|
6504
6842
|
]);
|
|
6505
|
-
return /* @__PURE__ */
|
|
6843
|
+
return /* @__PURE__ */ jsx52(
|
|
6506
6844
|
StudioSheetHeader,
|
|
6507
6845
|
{
|
|
6508
6846
|
left,
|
|
@@ -6515,12 +6853,12 @@ function ChatHeader({ left, right, center, style }) {
|
|
|
6515
6853
|
|
|
6516
6854
|
// src/components/chat/ForkNoticeBanner.tsx
|
|
6517
6855
|
import { View as View40 } from "react-native";
|
|
6518
|
-
import { jsx as
|
|
6856
|
+
import { jsx as jsx53, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
6519
6857
|
function ForkNoticeBanner({ isOwner = true, title, description, style }) {
|
|
6520
6858
|
const theme = useTheme();
|
|
6521
6859
|
const resolvedTitle = title ?? (isOwner ? "Remixed app" : "Remix app");
|
|
6522
6860
|
const resolvedDescription = description ?? (isOwner ? "Any changes you make will be a remix of the original app. You can view the edited version in the Remix tab in your apps page." : "Once you make edits, this remixed version will appear on your Remixed apps page.");
|
|
6523
|
-
return /* @__PURE__ */
|
|
6861
|
+
return /* @__PURE__ */ jsx53(
|
|
6524
6862
|
Card,
|
|
6525
6863
|
{
|
|
6526
6864
|
variant: "surfaceRaised",
|
|
@@ -6535,8 +6873,8 @@ function ForkNoticeBanner({ isOwner = true, title, description, style }) {
|
|
|
6535
6873
|
},
|
|
6536
6874
|
style
|
|
6537
6875
|
],
|
|
6538
|
-
children: /* @__PURE__ */
|
|
6539
|
-
/* @__PURE__ */
|
|
6876
|
+
children: /* @__PURE__ */ jsxs31(View40, { style: { minWidth: 0 }, children: [
|
|
6877
|
+
/* @__PURE__ */ jsx53(
|
|
6540
6878
|
Text,
|
|
6541
6879
|
{
|
|
6542
6880
|
style: {
|
|
@@ -6550,7 +6888,7 @@ function ForkNoticeBanner({ isOwner = true, title, description, style }) {
|
|
|
6550
6888
|
children: resolvedTitle
|
|
6551
6889
|
}
|
|
6552
6890
|
),
|
|
6553
|
-
/* @__PURE__ */
|
|
6891
|
+
/* @__PURE__ */ jsx53(
|
|
6554
6892
|
Text,
|
|
6555
6893
|
{
|
|
6556
6894
|
style: {
|
|
@@ -6569,8 +6907,8 @@ function ForkNoticeBanner({ isOwner = true, title, description, style }) {
|
|
|
6569
6907
|
|
|
6570
6908
|
// src/components/chat/ChatQueue.tsx
|
|
6571
6909
|
import * as React40 from "react";
|
|
6572
|
-
import { ActivityIndicator as ActivityIndicator8, Pressable as
|
|
6573
|
-
import { jsx as
|
|
6910
|
+
import { ActivityIndicator as ActivityIndicator8, Pressable as Pressable15, View as View41 } from "react-native";
|
|
6911
|
+
import { jsx as jsx54, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
6574
6912
|
function ChatQueue({ items, onRemove }) {
|
|
6575
6913
|
const theme = useTheme();
|
|
6576
6914
|
const [expanded, setExpanded] = React40.useState({});
|
|
@@ -6602,7 +6940,7 @@ ${trimmedLine2}\u2026 `;
|
|
|
6602
6940
|
setRemoving((prev) => Object.fromEntries(Object.entries(prev).filter(([id]) => ids.has(id))));
|
|
6603
6941
|
}, [items]);
|
|
6604
6942
|
if (items.length === 0) return null;
|
|
6605
|
-
return /* @__PURE__ */
|
|
6943
|
+
return /* @__PURE__ */ jsxs32(
|
|
6606
6944
|
View41,
|
|
6607
6945
|
{
|
|
6608
6946
|
style: {
|
|
@@ -6614,15 +6952,15 @@ ${trimmedLine2}\u2026 `;
|
|
|
6614
6952
|
backgroundColor: "transparent"
|
|
6615
6953
|
},
|
|
6616
6954
|
children: [
|
|
6617
|
-
/* @__PURE__ */
|
|
6618
|
-
/* @__PURE__ */
|
|
6955
|
+
/* @__PURE__ */ jsx54(Text, { variant: "caption", style: { marginBottom: theme.spacing.sm }, children: "Queue" }),
|
|
6956
|
+
/* @__PURE__ */ jsx54(View41, { style: { gap: theme.spacing.sm }, children: items.map((item) => {
|
|
6619
6957
|
const isExpanded = Boolean(expanded[item.id]);
|
|
6620
6958
|
const showToggle = Boolean(canExpand[item.id]);
|
|
6621
6959
|
const prompt = item.prompt ?? "";
|
|
6622
6960
|
const moreLabel = "more";
|
|
6623
6961
|
const displayPrompt = !isExpanded && showToggle && collapsedText[item.id] ? collapsedText[item.id] : prompt;
|
|
6624
6962
|
const isRemoving = Boolean(removing[item.id]);
|
|
6625
|
-
return /* @__PURE__ */
|
|
6963
|
+
return /* @__PURE__ */ jsxs32(
|
|
6626
6964
|
View41,
|
|
6627
6965
|
{
|
|
6628
6966
|
style: {
|
|
@@ -6635,8 +6973,8 @@ ${trimmedLine2}\u2026 `;
|
|
|
6635
6973
|
backgroundColor: withAlpha(theme.colors.surface, theme.scheme === "dark" ? 0.8 : 0.9)
|
|
6636
6974
|
},
|
|
6637
6975
|
children: [
|
|
6638
|
-
/* @__PURE__ */
|
|
6639
|
-
!canExpand[item.id] ? /* @__PURE__ */
|
|
6976
|
+
/* @__PURE__ */ jsxs32(View41, { style: { flex: 1 }, children: [
|
|
6977
|
+
!canExpand[item.id] ? /* @__PURE__ */ jsx54(
|
|
6640
6978
|
Text,
|
|
6641
6979
|
{
|
|
6642
6980
|
style: { position: "absolute", opacity: 0, zIndex: -1, width: "100%" },
|
|
@@ -6655,14 +6993,14 @@ ${trimmedLine2}\u2026 `;
|
|
|
6655
6993
|
children: prompt
|
|
6656
6994
|
}
|
|
6657
6995
|
) : null,
|
|
6658
|
-
/* @__PURE__ */
|
|
6996
|
+
/* @__PURE__ */ jsxs32(
|
|
6659
6997
|
Text,
|
|
6660
6998
|
{
|
|
6661
6999
|
variant: "bodyMuted",
|
|
6662
7000
|
numberOfLines: isExpanded ? void 0 : 2,
|
|
6663
7001
|
children: [
|
|
6664
7002
|
displayPrompt,
|
|
6665
|
-
!isExpanded && showToggle ? /* @__PURE__ */
|
|
7003
|
+
!isExpanded && showToggle ? /* @__PURE__ */ jsx54(
|
|
6666
7004
|
Text,
|
|
6667
7005
|
{
|
|
6668
7006
|
color: theme.colors.text,
|
|
@@ -6674,18 +7012,18 @@ ${trimmedLine2}\u2026 `;
|
|
|
6674
7012
|
]
|
|
6675
7013
|
}
|
|
6676
7014
|
),
|
|
6677
|
-
showToggle && isExpanded ? /* @__PURE__ */
|
|
6678
|
-
|
|
7015
|
+
showToggle && isExpanded ? /* @__PURE__ */ jsx54(
|
|
7016
|
+
Pressable15,
|
|
6679
7017
|
{
|
|
6680
7018
|
onPress: () => setExpanded((prev) => ({ ...prev, [item.id]: false })),
|
|
6681
7019
|
hitSlop: 6,
|
|
6682
7020
|
style: { alignSelf: "flex-start", marginTop: 4 },
|
|
6683
|
-
children: /* @__PURE__ */
|
|
7021
|
+
children: /* @__PURE__ */ jsx54(Text, { variant: "captionMuted", color: theme.colors.text, children: "less" })
|
|
6684
7022
|
}
|
|
6685
7023
|
) : null
|
|
6686
7024
|
] }),
|
|
6687
|
-
/* @__PURE__ */
|
|
6688
|
-
|
|
7025
|
+
/* @__PURE__ */ jsx54(
|
|
7026
|
+
Pressable15,
|
|
6689
7027
|
{
|
|
6690
7028
|
onPress: () => {
|
|
6691
7029
|
if (!onRemove || isRemoving) return;
|
|
@@ -6700,7 +7038,7 @@ ${trimmedLine2}\u2026 `;
|
|
|
6700
7038
|
},
|
|
6701
7039
|
hitSlop: 8,
|
|
6702
7040
|
style: { alignSelf: "center" },
|
|
6703
|
-
children: isRemoving ? /* @__PURE__ */
|
|
7041
|
+
children: isRemoving ? /* @__PURE__ */ jsx54(ActivityIndicator8, { size: "small", color: theme.colors.text }) : /* @__PURE__ */ jsx54(IconClose, { size: 14, colorToken: "text" })
|
|
6704
7042
|
}
|
|
6705
7043
|
)
|
|
6706
7044
|
]
|
|
@@ -6714,10 +7052,9 @@ ${trimmedLine2}\u2026 `;
|
|
|
6714
7052
|
}
|
|
6715
7053
|
|
|
6716
7054
|
// src/studio/ui/ChatPanel.tsx
|
|
6717
|
-
import { jsx as
|
|
7055
|
+
import { jsx as jsx55, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
6718
7056
|
function ChatPanel({
|
|
6719
7057
|
title = "Chat",
|
|
6720
|
-
autoFocusComposer = false,
|
|
6721
7058
|
messages,
|
|
6722
7059
|
showTypingIndicator,
|
|
6723
7060
|
loading,
|
|
@@ -6733,6 +7070,8 @@ function ChatPanel({
|
|
|
6733
7070
|
onNavigateHome,
|
|
6734
7071
|
onStartDraw,
|
|
6735
7072
|
onSend,
|
|
7073
|
+
onRetryMessage,
|
|
7074
|
+
isRetryingMessage,
|
|
6736
7075
|
queueItems = [],
|
|
6737
7076
|
onRemoveQueueItem
|
|
6738
7077
|
}) {
|
|
@@ -6756,21 +7095,21 @@ function ChatPanel({
|
|
|
6756
7095
|
var _a;
|
|
6757
7096
|
(_a = listRef.current) == null ? void 0 : _a.scrollToBottom({ animated: true });
|
|
6758
7097
|
}, []);
|
|
6759
|
-
const header = /* @__PURE__ */
|
|
7098
|
+
const header = /* @__PURE__ */ jsx55(
|
|
6760
7099
|
ChatHeader,
|
|
6761
7100
|
{
|
|
6762
|
-
left: /* @__PURE__ */
|
|
6763
|
-
/* @__PURE__ */
|
|
6764
|
-
onNavigateHome ? /* @__PURE__ */
|
|
7101
|
+
left: /* @__PURE__ */ jsxs33(View42, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
7102
|
+
/* @__PURE__ */ jsx55(StudioSheetHeaderIconButton, { onPress: onBack, accessibilityLabel: "Back", style: { marginRight: 8 }, children: /* @__PURE__ */ jsx55(IconBack, { size: 20, colorToken: "floatingContent" }) }),
|
|
7103
|
+
onNavigateHome ? /* @__PURE__ */ jsx55(StudioSheetHeaderIconButton, { onPress: onNavigateHome, accessibilityLabel: "Home", children: /* @__PURE__ */ jsx55(IconHome, { size: 20, colorToken: "floatingContent" }) }) : null
|
|
6765
7104
|
] }),
|
|
6766
|
-
right: /* @__PURE__ */
|
|
6767
|
-
onStartDraw ? /* @__PURE__ */
|
|
6768
|
-
/* @__PURE__ */
|
|
7105
|
+
right: /* @__PURE__ */ jsxs33(View42, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
7106
|
+
onStartDraw ? /* @__PURE__ */ jsx55(StudioSheetHeaderIconButton, { onPress: onStartDraw, accessibilityLabel: "Draw", intent: "danger", style: { marginRight: 8 }, children: /* @__PURE__ */ jsx55(IconDraw, { size: 20, colorToken: "onDanger" }) }) : null,
|
|
7107
|
+
/* @__PURE__ */ jsx55(StudioSheetHeaderIconButton, { onPress: onClose, accessibilityLabel: "Close", children: /* @__PURE__ */ jsx55(IconClose, { size: 20, colorToken: "floatingContent" }) })
|
|
6769
7108
|
] }),
|
|
6770
7109
|
center: null
|
|
6771
7110
|
}
|
|
6772
7111
|
);
|
|
6773
|
-
const topBanner = shouldForkOnEdit ? /* @__PURE__ */
|
|
7112
|
+
const topBanner = shouldForkOnEdit ? /* @__PURE__ */ jsx55(
|
|
6774
7113
|
ForkNoticeBanner,
|
|
6775
7114
|
{
|
|
6776
7115
|
isOwner: !shouldForkOnEdit,
|
|
@@ -6779,35 +7118,37 @@ function ChatPanel({
|
|
|
6779
7118
|
) : null;
|
|
6780
7119
|
const showMessagesLoading = Boolean(loading) && messages.length === 0 || forking;
|
|
6781
7120
|
if (showMessagesLoading) {
|
|
6782
|
-
return /* @__PURE__ */
|
|
6783
|
-
/* @__PURE__ */
|
|
6784
|
-
topBanner ? /* @__PURE__ */
|
|
6785
|
-
/* @__PURE__ */
|
|
6786
|
-
/* @__PURE__ */
|
|
6787
|
-
/* @__PURE__ */
|
|
6788
|
-
/* @__PURE__ */
|
|
7121
|
+
return /* @__PURE__ */ jsxs33(View42, { style: { flex: 1 }, children: [
|
|
7122
|
+
/* @__PURE__ */ jsx55(View42, { children: header }),
|
|
7123
|
+
topBanner ? /* @__PURE__ */ jsx55(View42, { style: { paddingHorizontal: 16, paddingTop: 8 }, children: topBanner }) : null,
|
|
7124
|
+
/* @__PURE__ */ jsxs33(View42, { style: { flex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 24, paddingVertical: 12 }, children: [
|
|
7125
|
+
/* @__PURE__ */ jsx55(ActivityIndicator9, {}),
|
|
7126
|
+
/* @__PURE__ */ jsx55(View42, { style: { height: 12 } }),
|
|
7127
|
+
/* @__PURE__ */ jsx55(Text, { variant: "bodyMuted", children: forking ? "Creating your copy\u2026" : "Loading messages\u2026" })
|
|
6789
7128
|
] })
|
|
6790
7129
|
] });
|
|
6791
7130
|
}
|
|
6792
|
-
const queueTop = queueItems.length > 0 ? /* @__PURE__ */
|
|
6793
|
-
return /* @__PURE__ */
|
|
7131
|
+
const queueTop = queueItems.length > 0 ? /* @__PURE__ */ jsx55(ChatQueue, { items: queueItems, onRemove: onRemoveQueueItem }) : null;
|
|
7132
|
+
return /* @__PURE__ */ jsx55(
|
|
6794
7133
|
ChatPage,
|
|
6795
7134
|
{
|
|
6796
7135
|
header,
|
|
6797
7136
|
messages,
|
|
6798
7137
|
showTypingIndicator,
|
|
7138
|
+
onRetryMessage,
|
|
7139
|
+
isRetryingMessage,
|
|
6799
7140
|
topBanner,
|
|
6800
7141
|
composerTop: queueTop,
|
|
6801
7142
|
composerHorizontalPadding: 0,
|
|
6802
7143
|
listRef,
|
|
6803
7144
|
onNearBottomChange: setNearBottom,
|
|
6804
|
-
overlay: /* @__PURE__ */
|
|
7145
|
+
overlay: /* @__PURE__ */ jsx55(
|
|
6805
7146
|
ScrollToBottomButton,
|
|
6806
7147
|
{
|
|
6807
7148
|
visible: !nearBottom,
|
|
6808
7149
|
onPress: handleScrollToBottom,
|
|
6809
7150
|
style: { bottom: 80 },
|
|
6810
|
-
children: /* @__PURE__ */
|
|
7151
|
+
children: /* @__PURE__ */ jsx55(IconArrowDown, { size: 20, colorToken: "floatingContent" })
|
|
6811
7152
|
}
|
|
6812
7153
|
),
|
|
6813
7154
|
composer: {
|
|
@@ -6816,7 +7157,6 @@ function ChatPanel({
|
|
|
6816
7157
|
disabled: Boolean(loading) || Boolean(forking),
|
|
6817
7158
|
sendDisabled: Boolean(sendDisabled) || Boolean(loading) || Boolean(forking),
|
|
6818
7159
|
sending: Boolean(sending),
|
|
6819
|
-
autoFocus: autoFocusComposer,
|
|
6820
7160
|
onSend: handleSend,
|
|
6821
7161
|
attachments,
|
|
6822
7162
|
onRemoveAttachment,
|
|
@@ -6829,15 +7169,15 @@ function ChatPanel({
|
|
|
6829
7169
|
|
|
6830
7170
|
// src/components/dialogs/ConfirmMergeRequestDialog.tsx
|
|
6831
7171
|
import * as React42 from "react";
|
|
6832
|
-
import { Pressable as
|
|
7172
|
+
import { Pressable as Pressable17, View as View44 } from "react-native";
|
|
6833
7173
|
|
|
6834
7174
|
// src/components/primitives/Modal.tsx
|
|
6835
7175
|
import {
|
|
6836
7176
|
Modal as RNModal,
|
|
6837
|
-
Pressable as
|
|
7177
|
+
Pressable as Pressable16,
|
|
6838
7178
|
View as View43
|
|
6839
7179
|
} from "react-native";
|
|
6840
|
-
import { jsx as
|
|
7180
|
+
import { jsx as jsx56, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
6841
7181
|
function Modal({
|
|
6842
7182
|
visible,
|
|
6843
7183
|
onRequestClose,
|
|
@@ -6846,30 +7186,30 @@ function Modal({
|
|
|
6846
7186
|
contentStyle
|
|
6847
7187
|
}) {
|
|
6848
7188
|
const theme = useTheme();
|
|
6849
|
-
return /* @__PURE__ */
|
|
7189
|
+
return /* @__PURE__ */ jsx56(
|
|
6850
7190
|
RNModal,
|
|
6851
7191
|
{
|
|
6852
7192
|
visible,
|
|
6853
7193
|
transparent: true,
|
|
6854
7194
|
animationType: "fade",
|
|
6855
7195
|
onRequestClose,
|
|
6856
|
-
children: /* @__PURE__ */
|
|
6857
|
-
/* @__PURE__ */
|
|
6858
|
-
|
|
7196
|
+
children: /* @__PURE__ */ jsxs34(View43, { style: { flex: 1, backgroundColor: theme.colors.backdrop, justifyContent: "center", padding: theme.spacing.lg }, children: [
|
|
7197
|
+
/* @__PURE__ */ jsx56(
|
|
7198
|
+
Pressable16,
|
|
6859
7199
|
{
|
|
6860
7200
|
accessibilityRole: "button",
|
|
6861
7201
|
onPress: dismissOnBackdropPress ? onRequestClose : void 0,
|
|
6862
7202
|
style: { position: "absolute", inset: 0 }
|
|
6863
7203
|
}
|
|
6864
7204
|
),
|
|
6865
|
-
/* @__PURE__ */
|
|
7205
|
+
/* @__PURE__ */ jsx56(Card, { variant: "surfaceRaised", padded: true, style: [{ borderRadius: theme.radii.xl }, contentStyle], children })
|
|
6866
7206
|
] })
|
|
6867
7207
|
}
|
|
6868
7208
|
);
|
|
6869
7209
|
}
|
|
6870
7210
|
|
|
6871
7211
|
// src/components/dialogs/ConfirmMergeRequestDialog.tsx
|
|
6872
|
-
import { jsx as
|
|
7212
|
+
import { jsx as jsx57, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
6873
7213
|
function ConfirmMergeRequestDialog({
|
|
6874
7214
|
visible,
|
|
6875
7215
|
onOpenChange,
|
|
@@ -6899,7 +7239,7 @@ function ConfirmMergeRequestDialog({
|
|
|
6899
7239
|
justifyContent: "center",
|
|
6900
7240
|
alignSelf: "stretch"
|
|
6901
7241
|
};
|
|
6902
|
-
return /* @__PURE__ */
|
|
7242
|
+
return /* @__PURE__ */ jsxs35(
|
|
6903
7243
|
Modal,
|
|
6904
7244
|
{
|
|
6905
7245
|
visible,
|
|
@@ -6910,7 +7250,7 @@ function ConfirmMergeRequestDialog({
|
|
|
6910
7250
|
backgroundColor: theme.colors.background
|
|
6911
7251
|
},
|
|
6912
7252
|
children: [
|
|
6913
|
-
/* @__PURE__ */
|
|
7253
|
+
/* @__PURE__ */ jsx57(View44, { children: /* @__PURE__ */ jsx57(
|
|
6914
7254
|
Text,
|
|
6915
7255
|
{
|
|
6916
7256
|
style: {
|
|
@@ -6922,8 +7262,8 @@ function ConfirmMergeRequestDialog({
|
|
|
6922
7262
|
children: "Are you sure you want to approve this merge request?"
|
|
6923
7263
|
}
|
|
6924
7264
|
) }),
|
|
6925
|
-
/* @__PURE__ */
|
|
6926
|
-
/* @__PURE__ */
|
|
7265
|
+
/* @__PURE__ */ jsxs35(View44, { style: { marginTop: 16 }, children: [
|
|
7266
|
+
/* @__PURE__ */ jsx57(
|
|
6927
7267
|
View44,
|
|
6928
7268
|
{
|
|
6929
7269
|
style: [
|
|
@@ -6933,21 +7273,21 @@ function ConfirmMergeRequestDialog({
|
|
|
6933
7273
|
opacity: canConfirm ? 1 : 0.5
|
|
6934
7274
|
}
|
|
6935
7275
|
],
|
|
6936
|
-
children: /* @__PURE__ */
|
|
6937
|
-
|
|
7276
|
+
children: /* @__PURE__ */ jsx57(
|
|
7277
|
+
Pressable17,
|
|
6938
7278
|
{
|
|
6939
7279
|
accessibilityRole: "button",
|
|
6940
7280
|
accessibilityLabel: "Approve Merge",
|
|
6941
7281
|
disabled: !canConfirm,
|
|
6942
7282
|
onPress: handleConfirm,
|
|
6943
7283
|
style: [fullWidthButtonBase, { flex: 1 }],
|
|
6944
|
-
children: /* @__PURE__ */
|
|
7284
|
+
children: /* @__PURE__ */ jsx57(Text, { style: { textAlign: "center", color: theme.colors.onPrimary }, children: "Approve Merge" })
|
|
6945
7285
|
}
|
|
6946
7286
|
)
|
|
6947
7287
|
}
|
|
6948
7288
|
),
|
|
6949
|
-
/* @__PURE__ */
|
|
6950
|
-
/* @__PURE__ */
|
|
7289
|
+
/* @__PURE__ */ jsx57(View44, { style: { height: 8 } }),
|
|
7290
|
+
/* @__PURE__ */ jsx57(
|
|
6951
7291
|
View44,
|
|
6952
7292
|
{
|
|
6953
7293
|
style: [
|
|
@@ -6959,21 +7299,21 @@ function ConfirmMergeRequestDialog({
|
|
|
6959
7299
|
opacity: isBuilding || !mergeRequest ? 0.5 : 1
|
|
6960
7300
|
}
|
|
6961
7301
|
],
|
|
6962
|
-
children: /* @__PURE__ */
|
|
6963
|
-
|
|
7302
|
+
children: /* @__PURE__ */ jsx57(
|
|
7303
|
+
Pressable17,
|
|
6964
7304
|
{
|
|
6965
7305
|
accessibilityRole: "button",
|
|
6966
7306
|
accessibilityLabel: isBuilding ? "Preparing\u2026" : "Test edits first",
|
|
6967
7307
|
disabled: isBuilding || !mergeRequest,
|
|
6968
7308
|
onPress: handleTestFirst,
|
|
6969
7309
|
style: [fullWidthButtonBase, { flex: 1 }],
|
|
6970
|
-
children: /* @__PURE__ */
|
|
7310
|
+
children: /* @__PURE__ */ jsx57(Text, { style: { textAlign: "center", color: theme.colors.text }, children: isBuilding ? "Preparing\u2026" : "Test edits first" })
|
|
6971
7311
|
}
|
|
6972
7312
|
)
|
|
6973
7313
|
}
|
|
6974
7314
|
),
|
|
6975
|
-
/* @__PURE__ */
|
|
6976
|
-
/* @__PURE__ */
|
|
7315
|
+
/* @__PURE__ */ jsx57(View44, { style: { height: 8 } }),
|
|
7316
|
+
/* @__PURE__ */ jsx57(
|
|
6977
7317
|
View44,
|
|
6978
7318
|
{
|
|
6979
7319
|
style: [
|
|
@@ -6984,14 +7324,14 @@ function ConfirmMergeRequestDialog({
|
|
|
6984
7324
|
borderColor: theme.colors.border
|
|
6985
7325
|
}
|
|
6986
7326
|
],
|
|
6987
|
-
children: /* @__PURE__ */
|
|
6988
|
-
|
|
7327
|
+
children: /* @__PURE__ */ jsx57(
|
|
7328
|
+
Pressable17,
|
|
6989
7329
|
{
|
|
6990
7330
|
accessibilityRole: "button",
|
|
6991
7331
|
accessibilityLabel: "Cancel",
|
|
6992
7332
|
onPress: close,
|
|
6993
7333
|
style: [fullWidthButtonBase, { flex: 1 }],
|
|
6994
|
-
children: /* @__PURE__ */
|
|
7334
|
+
children: /* @__PURE__ */ jsx57(Text, { style: { textAlign: "center", color: theme.colors.text }, children: "Cancel" })
|
|
6995
7335
|
}
|
|
6996
7336
|
)
|
|
6997
7337
|
}
|
|
@@ -7003,7 +7343,7 @@ function ConfirmMergeRequestDialog({
|
|
|
7003
7343
|
}
|
|
7004
7344
|
|
|
7005
7345
|
// src/studio/ui/ConfirmMergeFlow.tsx
|
|
7006
|
-
import { jsx as
|
|
7346
|
+
import { jsx as jsx58 } from "react/jsx-runtime";
|
|
7007
7347
|
function ConfirmMergeFlow({
|
|
7008
7348
|
visible,
|
|
7009
7349
|
onOpenChange,
|
|
@@ -7014,7 +7354,7 @@ function ConfirmMergeFlow({
|
|
|
7014
7354
|
onConfirm,
|
|
7015
7355
|
onTestFirst
|
|
7016
7356
|
}) {
|
|
7017
|
-
return /* @__PURE__ */
|
|
7357
|
+
return /* @__PURE__ */ jsx58(
|
|
7018
7358
|
ConfirmMergeRequestDialog,
|
|
7019
7359
|
{
|
|
7020
7360
|
visible,
|
|
@@ -7112,14 +7452,56 @@ function useOptimisticChatMessages({
|
|
|
7112
7452
|
const createdAtIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
7113
7453
|
const baseServerLastId = chatMessages.length > 0 ? chatMessages[chatMessages.length - 1].id : null;
|
|
7114
7454
|
const id = makeOptimisticId();
|
|
7115
|
-
|
|
7455
|
+
const normalizedAttachments = attachments && attachments.length > 0 ? [...attachments] : void 0;
|
|
7456
|
+
setOptimisticChat((prev) => [
|
|
7457
|
+
...prev,
|
|
7458
|
+
{
|
|
7459
|
+
id,
|
|
7460
|
+
content: text,
|
|
7461
|
+
attachments: normalizedAttachments,
|
|
7462
|
+
createdAtIso,
|
|
7463
|
+
baseServerLastId,
|
|
7464
|
+
failed: false,
|
|
7465
|
+
retrying: false
|
|
7466
|
+
}
|
|
7467
|
+
]);
|
|
7116
7468
|
void Promise.resolve(onSendChat(text, attachments)).catch(() => {
|
|
7117
7469
|
setOptimisticChat((prev) => prev.map((m) => m.id === id ? { ...m, failed: true } : m));
|
|
7118
7470
|
});
|
|
7119
7471
|
},
|
|
7120
7472
|
[chatMessages, disableOptimistic, onSendChat, shouldForkOnEdit]
|
|
7121
7473
|
);
|
|
7122
|
-
|
|
7474
|
+
const onRetry = React43.useCallback(
|
|
7475
|
+
async (messageId) => {
|
|
7476
|
+
if (shouldForkOnEdit || disableOptimistic) return;
|
|
7477
|
+
const target = optimisticChat.find((m) => m.id === messageId);
|
|
7478
|
+
if (!target || target.retrying) return;
|
|
7479
|
+
const baseServerLastId = chatMessages.length > 0 ? chatMessages[chatMessages.length - 1].id : null;
|
|
7480
|
+
setOptimisticChat(
|
|
7481
|
+
(prev) => prev.map(
|
|
7482
|
+
(m) => m.id === messageId ? { ...m, failed: false, retrying: true, baseServerLastId } : m
|
|
7483
|
+
)
|
|
7484
|
+
);
|
|
7485
|
+
try {
|
|
7486
|
+
await onSendChat(target.content, target.attachments);
|
|
7487
|
+
setOptimisticChat(
|
|
7488
|
+
(prev) => prev.map((m) => m.id === messageId ? { ...m, retrying: false } : m)
|
|
7489
|
+
);
|
|
7490
|
+
} catch {
|
|
7491
|
+
setOptimisticChat(
|
|
7492
|
+
(prev) => prev.map((m) => m.id === messageId ? { ...m, failed: true, retrying: false } : m)
|
|
7493
|
+
);
|
|
7494
|
+
}
|
|
7495
|
+
},
|
|
7496
|
+
[chatMessages, disableOptimistic, onSendChat, optimisticChat, shouldForkOnEdit]
|
|
7497
|
+
);
|
|
7498
|
+
const isRetrying = React43.useCallback(
|
|
7499
|
+
(messageId) => {
|
|
7500
|
+
return optimisticChat.some((m) => m.id === messageId && m.retrying);
|
|
7501
|
+
},
|
|
7502
|
+
[optimisticChat]
|
|
7503
|
+
);
|
|
7504
|
+
return { messages, onSend, onRetry, isRetrying };
|
|
7123
7505
|
}
|
|
7124
7506
|
|
|
7125
7507
|
// src/studio/ui/StudioOverlay.tsx
|
|
@@ -7127,7 +7509,7 @@ import {
|
|
|
7127
7509
|
publishComergeStudioUIState,
|
|
7128
7510
|
startStudioControlPolling
|
|
7129
7511
|
} from "@comergehq/studio-control";
|
|
7130
|
-
import { Fragment as Fragment6, jsx as
|
|
7512
|
+
import { Fragment as Fragment6, jsx as jsx59, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
7131
7513
|
function StudioOverlay({
|
|
7132
7514
|
captureTargetRef,
|
|
7133
7515
|
app,
|
|
@@ -7135,6 +7517,7 @@ function StudioOverlay({
|
|
|
7135
7517
|
isOwner,
|
|
7136
7518
|
shouldForkOnEdit,
|
|
7137
7519
|
isTesting,
|
|
7520
|
+
isBaseBundleDownloading = false,
|
|
7138
7521
|
onRestoreBase,
|
|
7139
7522
|
incomingMergeRequests,
|
|
7140
7523
|
outgoingMergeRequests,
|
|
@@ -7190,7 +7573,7 @@ function StudioOverlay({
|
|
|
7190
7573
|
);
|
|
7191
7574
|
const handleSheetOpenChange = React44.useCallback((open) => {
|
|
7192
7575
|
setSheetOpen(open);
|
|
7193
|
-
if (!open)
|
|
7576
|
+
if (!open) Keyboard4.dismiss();
|
|
7194
7577
|
}, []);
|
|
7195
7578
|
const closeSheet = React44.useCallback(() => {
|
|
7196
7579
|
handleSheetOpenChange(false);
|
|
@@ -7201,8 +7584,8 @@ function StudioOverlay({
|
|
|
7201
7584
|
openSheet();
|
|
7202
7585
|
}, [openSheet]);
|
|
7203
7586
|
const backToPreview = React44.useCallback(() => {
|
|
7204
|
-
if (
|
|
7205
|
-
|
|
7587
|
+
if (Platform10.OS !== "ios") {
|
|
7588
|
+
Keyboard4.dismiss();
|
|
7206
7589
|
setActivePage("preview");
|
|
7207
7590
|
return;
|
|
7208
7591
|
}
|
|
@@ -7214,9 +7597,9 @@ function StudioOverlay({
|
|
|
7214
7597
|
clearTimeout(t);
|
|
7215
7598
|
setActivePage("preview");
|
|
7216
7599
|
};
|
|
7217
|
-
const sub =
|
|
7600
|
+
const sub = Keyboard4.addListener("keyboardDidHide", finalize);
|
|
7218
7601
|
const t = setTimeout(finalize, 350);
|
|
7219
|
-
|
|
7602
|
+
Keyboard4.dismiss();
|
|
7220
7603
|
}, []);
|
|
7221
7604
|
const startDraw = React44.useCallback(() => {
|
|
7222
7605
|
setDrawing(true);
|
|
@@ -7265,14 +7648,14 @@ function StudioOverlay({
|
|
|
7265
7648
|
React44.useEffect(() => {
|
|
7266
7649
|
void publishComergeStudioUIState(sheetOpen, studioControlOptions);
|
|
7267
7650
|
}, [sheetOpen, studioControlOptions]);
|
|
7268
|
-
return /* @__PURE__ */
|
|
7269
|
-
/* @__PURE__ */
|
|
7270
|
-
/* @__PURE__ */
|
|
7651
|
+
return /* @__PURE__ */ jsxs36(Fragment6, { children: [
|
|
7652
|
+
/* @__PURE__ */ jsx59(EdgeGlowFrame, { visible: isTesting, role: "accent", thickness: 40, intensity: 1 }),
|
|
7653
|
+
/* @__PURE__ */ jsx59(StudioBottomSheet, { open: sheetOpen, onOpenChange: handleSheetOpenChange, children: /* @__PURE__ */ jsx59(
|
|
7271
7654
|
StudioSheetPager,
|
|
7272
7655
|
{
|
|
7273
7656
|
activePage,
|
|
7274
7657
|
width,
|
|
7275
|
-
preview: /* @__PURE__ */
|
|
7658
|
+
preview: /* @__PURE__ */ jsx59(
|
|
7276
7659
|
PreviewPanel,
|
|
7277
7660
|
{
|
|
7278
7661
|
app,
|
|
@@ -7301,7 +7684,7 @@ function StudioOverlay({
|
|
|
7301
7684
|
commentCountOverride: commentsCount ?? void 0
|
|
7302
7685
|
}
|
|
7303
7686
|
),
|
|
7304
|
-
chat: /* @__PURE__ */
|
|
7687
|
+
chat: /* @__PURE__ */ jsx59(
|
|
7305
7688
|
ChatPanel,
|
|
7306
7689
|
{
|
|
7307
7690
|
messages: optimistic.messages,
|
|
@@ -7310,7 +7693,6 @@ function StudioOverlay({
|
|
|
7310
7693
|
sendDisabled: chatSendDisabled,
|
|
7311
7694
|
forking: chatForking,
|
|
7312
7695
|
sending: chatSending,
|
|
7313
|
-
autoFocusComposer: sheetOpen && activePage === "chat",
|
|
7314
7696
|
shouldForkOnEdit,
|
|
7315
7697
|
attachments: chatAttachments,
|
|
7316
7698
|
onRemoveAttachment: (idx) => setChatAttachments((prev) => prev.filter((_, i) => i !== idx)),
|
|
@@ -7320,24 +7702,27 @@ function StudioOverlay({
|
|
|
7320
7702
|
onNavigateHome,
|
|
7321
7703
|
onStartDraw: startDraw,
|
|
7322
7704
|
onSend: optimistic.onSend,
|
|
7705
|
+
onRetryMessage: optimistic.onRetry,
|
|
7706
|
+
isRetryingMessage: optimistic.isRetrying,
|
|
7323
7707
|
queueItems: queueItemsForChat,
|
|
7324
7708
|
onRemoveQueueItem
|
|
7325
7709
|
}
|
|
7326
7710
|
)
|
|
7327
7711
|
}
|
|
7328
7712
|
) }),
|
|
7329
|
-
showBubble && /* @__PURE__ */
|
|
7713
|
+
showBubble && /* @__PURE__ */ jsx59(
|
|
7330
7714
|
Bubble,
|
|
7331
7715
|
{
|
|
7332
7716
|
visible: !sheetOpen && !drawing,
|
|
7333
7717
|
ariaLabel: sheetOpen ? "Hide studio" : "Show studio",
|
|
7334
7718
|
badgeCount: incomingMergeRequests.length,
|
|
7335
7719
|
onPress: toggleSheet,
|
|
7336
|
-
isLoading: (app == null ? void 0 : app.status) === "editing",
|
|
7337
|
-
|
|
7720
|
+
isLoading: (app == null ? void 0 : app.status) === "editing" || isBaseBundleDownloading,
|
|
7721
|
+
loadingBorderTone: isBaseBundleDownloading ? "warning" : "default",
|
|
7722
|
+
children: /* @__PURE__ */ jsx59(View45, { style: { width: 28, height: 28, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsx59(MergeIcon, { width: 24, height: 24, color: theme.colors.floatingContent }) })
|
|
7338
7723
|
}
|
|
7339
7724
|
),
|
|
7340
|
-
/* @__PURE__ */
|
|
7725
|
+
/* @__PURE__ */ jsx59(
|
|
7341
7726
|
DrawModeOverlay,
|
|
7342
7727
|
{
|
|
7343
7728
|
visible: drawing,
|
|
@@ -7346,7 +7731,7 @@ function StudioOverlay({
|
|
|
7346
7731
|
onCapture: handleDrawCapture
|
|
7347
7732
|
}
|
|
7348
7733
|
),
|
|
7349
|
-
/* @__PURE__ */
|
|
7734
|
+
/* @__PURE__ */ jsx59(
|
|
7350
7735
|
ConfirmMergeFlow,
|
|
7351
7736
|
{
|
|
7352
7737
|
visible: Boolean(confirmMr),
|
|
@@ -7355,11 +7740,12 @@ function StudioOverlay({
|
|
|
7355
7740
|
},
|
|
7356
7741
|
mergeRequest: confirmMr,
|
|
7357
7742
|
toSummary: toMergeRequestSummary,
|
|
7743
|
+
isBuilding: isBuildingMrTest,
|
|
7358
7744
|
onConfirm: (mr) => onApprove == null ? void 0 : onApprove(mr),
|
|
7359
7745
|
onTestFirst: handleTestMr
|
|
7360
7746
|
}
|
|
7361
7747
|
),
|
|
7362
|
-
/* @__PURE__ */
|
|
7748
|
+
/* @__PURE__ */ jsx59(
|
|
7363
7749
|
AppCommentsSheet,
|
|
7364
7750
|
{
|
|
7365
7751
|
appId: commentsAppId,
|
|
@@ -7552,7 +7938,7 @@ function useEditQueueActions(appId) {
|
|
|
7552
7938
|
}
|
|
7553
7939
|
|
|
7554
7940
|
// src/studio/ComergeStudio.tsx
|
|
7555
|
-
import { jsx as
|
|
7941
|
+
import { jsx as jsx60, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
7556
7942
|
function ComergeStudio({
|
|
7557
7943
|
appId,
|
|
7558
7944
|
clientKey: clientKey2,
|
|
@@ -7573,7 +7959,7 @@ function ComergeStudio({
|
|
|
7573
7959
|
setPendingRuntimeTargetAppId(null);
|
|
7574
7960
|
}, [appId]);
|
|
7575
7961
|
const captureTargetRef = React47.useRef(null);
|
|
7576
|
-
return /* @__PURE__ */
|
|
7962
|
+
return /* @__PURE__ */ jsx60(StudioBootstrap, { clientKey: clientKey2, fallback: /* @__PURE__ */ jsx60(View46, { style: { flex: 1 } }), children: ({ userId }) => /* @__PURE__ */ jsx60(BottomSheetModalProvider, { children: /* @__PURE__ */ jsx60(LiquidGlassResetProvider, { resetTriggers: [appId, activeAppId, runtimeAppId], children: /* @__PURE__ */ jsx60(
|
|
7577
7963
|
ComergeStudioInner,
|
|
7578
7964
|
{
|
|
7579
7965
|
userId,
|
|
@@ -7722,6 +8108,8 @@ function ComergeStudioInner({
|
|
|
7722
8108
|
const [testingMrId, setTestingMrId] = React47.useState(null);
|
|
7723
8109
|
const [syncingUpstream, setSyncingUpstream] = React47.useState(false);
|
|
7724
8110
|
const [upstreamSyncStatus, setUpstreamSyncStatus] = React47.useState(null);
|
|
8111
|
+
const isMrTestBuildInProgress = bundle.loading && bundle.loadingMode === "test";
|
|
8112
|
+
const isBaseBundleDownloading = bundle.loading && bundle.loadingMode === "base" && !bundle.isTesting;
|
|
7725
8113
|
const chatShowTypingIndicator = React47.useMemo(() => {
|
|
7726
8114
|
var _a;
|
|
7727
8115
|
if (!thread.raw || thread.raw.length === 0) return false;
|
|
@@ -7768,8 +8156,8 @@ function ComergeStudioInner({
|
|
|
7768
8156
|
}
|
|
7769
8157
|
return editQueue.items;
|
|
7770
8158
|
}, [editQueue.items, lastEditQueueInfo, suppressQueueUntilResponse]);
|
|
7771
|
-
return /* @__PURE__ */
|
|
7772
|
-
/* @__PURE__ */
|
|
8159
|
+
return /* @__PURE__ */ jsx60(View46, { style: [{ flex: 1 }, style], children: /* @__PURE__ */ jsxs37(View46, { ref: captureTargetRef, style: { flex: 1 }, collapsable: false, children: [
|
|
8160
|
+
/* @__PURE__ */ jsx60(
|
|
7773
8161
|
RuntimeRenderer,
|
|
7774
8162
|
{
|
|
7775
8163
|
appKey,
|
|
@@ -7779,7 +8167,7 @@ function ComergeStudioInner({
|
|
|
7779
8167
|
allowInitialPreparing: !embeddedBaseBundles
|
|
7780
8168
|
}
|
|
7781
8169
|
),
|
|
7782
|
-
/* @__PURE__ */
|
|
8170
|
+
/* @__PURE__ */ jsx60(
|
|
7783
8171
|
StudioOverlay,
|
|
7784
8172
|
{
|
|
7785
8173
|
captureTargetRef,
|
|
@@ -7788,6 +8176,7 @@ function ComergeStudioInner({
|
|
|
7788
8176
|
isOwner: actions.isOwner,
|
|
7789
8177
|
shouldForkOnEdit: actions.shouldForkOnEdit,
|
|
7790
8178
|
isTesting: bundle.isTesting,
|
|
8179
|
+
isBaseBundleDownloading,
|
|
7791
8180
|
onRestoreBase: async () => {
|
|
7792
8181
|
setTestingMrId(null);
|
|
7793
8182
|
await bundle.restoreBase();
|
|
@@ -7796,10 +8185,10 @@ function ComergeStudioInner({
|
|
|
7796
8185
|
outgoingMergeRequests: mergeRequests.lists.outgoing,
|
|
7797
8186
|
creatorStatsById: mergeRequests.creatorStatsById,
|
|
7798
8187
|
processingMrId,
|
|
7799
|
-
isBuildingMrTest:
|
|
8188
|
+
isBuildingMrTest: isMrTestBuildInProgress,
|
|
7800
8189
|
testingMrId,
|
|
7801
8190
|
toMergeRequestSummary: mergeRequests.toSummary,
|
|
7802
|
-
onSubmitMergeRequest: (app == null ? void 0 : app.forkedFromAppId) && actions.isOwner && !hasOpenOutgoingMr ? async () => {
|
|
8191
|
+
onSubmitMergeRequest: (app == null ? void 0 : app.forkedFromAppId) && actions.isOwner && !mergeRequests.loading && !hasOpenOutgoingMr ? async () => {
|
|
7803
8192
|
await mergeRequests.actions.openMergeRequest(activeAppId);
|
|
7804
8193
|
} : void 0,
|
|
7805
8194
|
onSyncUpstream: actions.isOwner && (app == null ? void 0 : app.forkedFromAppId) ? handleSyncUpstream : void 0,
|
|
@@ -7824,6 +8213,7 @@ function ComergeStudioInner({
|
|
|
7824
8213
|
}
|
|
7825
8214
|
},
|
|
7826
8215
|
onTestMr: async (mr) => {
|
|
8216
|
+
if (testingMrId === mr.id || bundle.loadingMode === "test") return;
|
|
7827
8217
|
setTestingMrId(mr.id);
|
|
7828
8218
|
await bundle.loadTest({ appId: mr.sourceAppId, commitId: mr.sourceTipCommitId ?? mr.sourceCommitId });
|
|
7829
8219
|
},
|
|
@@ -7845,6 +8235,7 @@ function ComergeStudioInner({
|
|
|
7845
8235
|
}
|
|
7846
8236
|
export {
|
|
7847
8237
|
ComergeStudio,
|
|
8238
|
+
resetRealtimeState,
|
|
7848
8239
|
setSupabaseClient
|
|
7849
8240
|
};
|
|
7850
8241
|
//# sourceMappingURL=index.mjs.map
|