@comergehq/studio 0.1.22 → 0.1.24
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 +697 -312
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +724 -336
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/bubble/Bubble.tsx +11 -5
- 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;
|
|
@@ -2471,18 +2650,15 @@ function Bubble({
|
|
|
2471
2650
|
[height, rotation, scale, size, translateX, translateY]
|
|
2472
2651
|
);
|
|
2473
2652
|
const animateOut = useCallback8(() => {
|
|
2653
|
+
var _a;
|
|
2474
2654
|
if (isAnimatingOut.current) return;
|
|
2475
2655
|
isAnimatingOut.current = true;
|
|
2476
2656
|
try {
|
|
2477
2657
|
void Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
|
|
2478
2658
|
} catch {
|
|
2479
2659
|
}
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
var _a;
|
|
2483
|
-
(_a = onPressRef.current) == null ? void 0 : _a.call(onPressRef);
|
|
2484
|
-
}
|
|
2485
|
-
});
|
|
2660
|
+
(_a = onPressRef.current) == null ? void 0 : _a.call(onPressRef);
|
|
2661
|
+
animateToHidden();
|
|
2486
2662
|
}, [animateToHidden]);
|
|
2487
2663
|
useEffect11(() => {
|
|
2488
2664
|
if (isLoading) {
|
|
@@ -2531,7 +2707,7 @@ function Bubble({
|
|
|
2531
2707
|
animateIn();
|
|
2532
2708
|
}
|
|
2533
2709
|
}, [forceShowTrigger, visible, animateIn]);
|
|
2534
|
-
const panResponder =
|
|
2710
|
+
const panResponder = useRef8(
|
|
2535
2711
|
PanResponder.create({
|
|
2536
2712
|
onStartShouldSetPanResponder: () => true,
|
|
2537
2713
|
onMoveShouldSetPanResponder: () => true,
|
|
@@ -2567,10 +2743,11 @@ function Bubble({
|
|
|
2567
2743
|
]
|
|
2568
2744
|
}));
|
|
2569
2745
|
const borderAnimatedStyle = useAnimatedStyle(() => {
|
|
2746
|
+
const isWarning = loadingBorderTone === "warning";
|
|
2570
2747
|
const borderColor = interpolateColor(
|
|
2571
2748
|
borderPulse.value,
|
|
2572
2749
|
[0, 1],
|
|
2573
|
-
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)"]
|
|
2574
2751
|
);
|
|
2575
2752
|
return {
|
|
2576
2753
|
borderWidth: isLoading ? 2 : 0,
|
|
@@ -2650,23 +2827,6 @@ var styles = StyleSheet.create({
|
|
|
2650
2827
|
import * as React14 from "react";
|
|
2651
2828
|
import { Animated as Animated3, View as View6 } from "react-native";
|
|
2652
2829
|
import { LinearGradient } from "expo-linear-gradient";
|
|
2653
|
-
|
|
2654
|
-
// src/components/utils/color.ts
|
|
2655
|
-
function withAlpha(color, alpha) {
|
|
2656
|
-
const a = Math.max(0, Math.min(1, alpha));
|
|
2657
|
-
const hex = color.trim();
|
|
2658
|
-
if (!hex.startsWith("#")) return color;
|
|
2659
|
-
const raw = hex.slice(1);
|
|
2660
|
-
const expanded = raw.length === 3 ? raw.split("").map((c) => c + c).join("") : raw;
|
|
2661
|
-
if (expanded.length !== 6) return color;
|
|
2662
|
-
const r = Number.parseInt(expanded.slice(0, 2), 16);
|
|
2663
|
-
const g = Number.parseInt(expanded.slice(2, 4), 16);
|
|
2664
|
-
const b = Number.parseInt(expanded.slice(4, 6), 16);
|
|
2665
|
-
if ([r, g, b].some((n) => Number.isNaN(n))) return color;
|
|
2666
|
-
return `rgba(${r}, ${g}, ${b}, ${a})`;
|
|
2667
|
-
}
|
|
2668
|
-
|
|
2669
|
-
// src/components/overlays/EdgeGlowFrame.tsx
|
|
2670
2830
|
import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2671
2831
|
function baseColor(role, theme) {
|
|
2672
2832
|
switch (role) {
|
|
@@ -3261,10 +3421,10 @@ var styles3 = StyleSheet3.create({
|
|
|
3261
3421
|
|
|
3262
3422
|
// src/components/comments/AppCommentsSheet.tsx
|
|
3263
3423
|
import * as React24 from "react";
|
|
3264
|
-
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";
|
|
3265
3425
|
import {
|
|
3266
3426
|
BottomSheetBackdrop,
|
|
3267
|
-
BottomSheetModal,
|
|
3427
|
+
BottomSheetModal as BottomSheetModal2,
|
|
3268
3428
|
BottomSheetScrollView
|
|
3269
3429
|
} from "@gorhom/bottom-sheet";
|
|
3270
3430
|
import { useSafeAreaInsets as useSafeAreaInsets3 } from "react-native-safe-area-context";
|
|
@@ -3282,7 +3442,7 @@ import {
|
|
|
3282
3442
|
ScrollView,
|
|
3283
3443
|
View as View11
|
|
3284
3444
|
} from "react-native";
|
|
3285
|
-
import { isLiquidGlassSupported as isLiquidGlassSupported3 } from "@callstack/liquid-glass";
|
|
3445
|
+
import { isLiquidGlassSupported as isLiquidGlassSupported3, LiquidGlassView as LiquidGlassView2 } from "@callstack/liquid-glass";
|
|
3286
3446
|
import { Plus } from "lucide-react-native";
|
|
3287
3447
|
|
|
3288
3448
|
// src/components/chat/MultilineTextInput.tsx
|
|
@@ -3420,7 +3580,6 @@ function ChatComposer({
|
|
|
3420
3580
|
disabled = false,
|
|
3421
3581
|
sendDisabled = false,
|
|
3422
3582
|
sending = false,
|
|
3423
|
-
autoFocus = false,
|
|
3424
3583
|
onSend,
|
|
3425
3584
|
attachments = [],
|
|
3426
3585
|
onRemoveAttachment,
|
|
@@ -3443,18 +3602,6 @@ function ChatComposer({
|
|
|
3443
3602
|
const maxInputHeight = React19.useMemo(() => Dimensions.get("window").height * 0.5, []);
|
|
3444
3603
|
const shakeAnim = React19.useRef(new Animated5.Value(0)).current;
|
|
3445
3604
|
const [sendPressed, setSendPressed] = React19.useState(false);
|
|
3446
|
-
const inputRef = React19.useRef(null);
|
|
3447
|
-
const prevAutoFocusRef = React19.useRef(false);
|
|
3448
|
-
React19.useEffect(() => {
|
|
3449
|
-
const shouldFocus = autoFocus && !prevAutoFocusRef.current && !disabled && !sending;
|
|
3450
|
-
prevAutoFocusRef.current = autoFocus;
|
|
3451
|
-
if (!shouldFocus) return;
|
|
3452
|
-
const t = setTimeout(() => {
|
|
3453
|
-
var _a;
|
|
3454
|
-
(_a = inputRef.current) == null ? void 0 : _a.focus();
|
|
3455
|
-
}, 75);
|
|
3456
|
-
return () => clearTimeout(t);
|
|
3457
|
-
}, [autoFocus, disabled, sending]);
|
|
3458
3605
|
const triggerShake = React19.useCallback(() => {
|
|
3459
3606
|
shakeAnim.setValue(0);
|
|
3460
3607
|
Animated5.sequence([
|
|
@@ -3485,7 +3632,7 @@ function ChatComposer({
|
|
|
3485
3632
|
onLayout: (e) => onLayout == null ? void 0 : onLayout({ height: e.nativeEvent.layout.height }),
|
|
3486
3633
|
children: /* @__PURE__ */ jsxs8(View11, { style: { flexDirection: "row", alignItems: "flex-end", gap: 8 }, children: [
|
|
3487
3634
|
/* @__PURE__ */ jsx17(Animated5.View, { style: { flex: 1, transform: [{ translateX: shakeAnim }] }, children: /* @__PURE__ */ jsxs8(
|
|
3488
|
-
|
|
3635
|
+
LiquidGlassView2,
|
|
3489
3636
|
{
|
|
3490
3637
|
style: [
|
|
3491
3638
|
// LiquidGlassView doesn't reliably auto-size to children; ensure enough height for the
|
|
@@ -3537,13 +3684,12 @@ function ChatComposer({
|
|
|
3537
3684
|
/* @__PURE__ */ jsx17(
|
|
3538
3685
|
MultilineTextInput,
|
|
3539
3686
|
{
|
|
3540
|
-
ref: inputRef,
|
|
3541
3687
|
value: text,
|
|
3542
3688
|
onChangeText: setText,
|
|
3543
3689
|
placeholder,
|
|
3544
3690
|
editable: !disabled && !sending,
|
|
3545
3691
|
useBottomSheetTextInput,
|
|
3546
|
-
autoFocus,
|
|
3692
|
+
autoFocus: false,
|
|
3547
3693
|
placeholderTextColor,
|
|
3548
3694
|
scrollEnabled: true,
|
|
3549
3695
|
style: {
|
|
@@ -3868,11 +4014,11 @@ function useAppDetails(appId) {
|
|
|
3868
4014
|
|
|
3869
4015
|
// src/components/comments/useIosKeyboardSnapFix.ts
|
|
3870
4016
|
import * as React23 from "react";
|
|
3871
|
-
import { Keyboard as Keyboard2, Platform as
|
|
4017
|
+
import { Keyboard as Keyboard2, Platform as Platform4 } from "react-native";
|
|
3872
4018
|
function useIosKeyboardSnapFix(sheetRef, options) {
|
|
3873
4019
|
const [keyboardVisible, setKeyboardVisible] = React23.useState(false);
|
|
3874
4020
|
React23.useEffect(() => {
|
|
3875
|
-
if (
|
|
4021
|
+
if (Platform4.OS !== "ios") return;
|
|
3876
4022
|
const show = Keyboard2.addListener("keyboardWillShow", () => setKeyboardVisible(true));
|
|
3877
4023
|
const hide = Keyboard2.addListener("keyboardWillHide", () => {
|
|
3878
4024
|
var _a;
|
|
@@ -3940,7 +4086,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
3940
4086
|
onClose();
|
|
3941
4087
|
}, [appId, onClose, onPlayApp]);
|
|
3942
4088
|
return /* @__PURE__ */ jsx20(
|
|
3943
|
-
|
|
4089
|
+
BottomSheetModal2,
|
|
3944
4090
|
{
|
|
3945
4091
|
ref: sheetRef,
|
|
3946
4092
|
index: 1,
|
|
@@ -3950,8 +4096,8 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
3950
4096
|
onChange: handleChange,
|
|
3951
4097
|
backgroundStyle: {
|
|
3952
4098
|
backgroundColor: theme.scheme === "dark" ? "#0B080F" : "#FFFFFF",
|
|
3953
|
-
borderTopLeftRadius:
|
|
3954
|
-
borderTopRightRadius:
|
|
4099
|
+
borderTopLeftRadius: Platform5.OS === "ios" ? 39 : 16,
|
|
4100
|
+
borderTopRightRadius: Platform5.OS === "ios" ? 39 : 16
|
|
3955
4101
|
},
|
|
3956
4102
|
handleIndicatorStyle: { backgroundColor: theme.colors.handleIndicator },
|
|
3957
4103
|
keyboardBehavior: "interactive",
|
|
@@ -4057,7 +4203,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
4057
4203
|
bottom: 0,
|
|
4058
4204
|
paddingHorizontal: theme.spacing.lg,
|
|
4059
4205
|
paddingTop: theme.spacing.sm,
|
|
4060
|
-
paddingBottom:
|
|
4206
|
+
paddingBottom: Platform5.OS === "ios" ? keyboardVisible ? theme.spacing.lg : insets.bottom : insets.bottom + 10,
|
|
4061
4207
|
borderTopWidth: 1,
|
|
4062
4208
|
borderTopColor: withAlpha(theme.colors.border, 0.1),
|
|
4063
4209
|
backgroundColor: withAlpha(theme.colors.background, 0.8)
|
|
@@ -4084,7 +4230,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
4084
4230
|
|
|
4085
4231
|
// src/studio/ui/PreviewPanel.tsx
|
|
4086
4232
|
import * as React35 from "react";
|
|
4087
|
-
import { ActivityIndicator as ActivityIndicator7, Platform as
|
|
4233
|
+
import { ActivityIndicator as ActivityIndicator7, Platform as Platform7, Share, View as View33 } from "react-native";
|
|
4088
4234
|
|
|
4089
4235
|
// src/components/preview/PreviewPage.tsx
|
|
4090
4236
|
import { View as View15 } from "react-native";
|
|
@@ -4971,16 +5117,48 @@ import { RefreshCw, Send as Send2 } from "lucide-react-native";
|
|
|
4971
5117
|
|
|
4972
5118
|
// src/components/merge-requests/MergeRequestStatusCard.tsx
|
|
4973
5119
|
import * as React28 from "react";
|
|
4974
|
-
import { Animated as Animated7, Pressable as
|
|
5120
|
+
import { Animated as Animated7, Pressable as Pressable10, View as View28 } from "react-native";
|
|
4975
5121
|
import { Ban, Check as Check3, CheckCheck, ChevronDown as ChevronDown2 } from "lucide-react-native";
|
|
4976
5122
|
|
|
4977
5123
|
// src/components/primitives/MarkdownText.tsx
|
|
4978
|
-
import { Platform as
|
|
5124
|
+
import { Platform as Platform6, Pressable as Pressable9, Text as Text3, View as View27 } from "react-native";
|
|
4979
5125
|
import Markdown from "react-native-markdown-display";
|
|
4980
|
-
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
|
+
}
|
|
4981
5154
|
function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
|
|
4982
5155
|
const theme = useTheme();
|
|
4983
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);
|
|
4984
5162
|
const baseBodyColor = variant === "mergeRequest" ? theme.colors.textMuted : theme.colors.text;
|
|
4985
5163
|
const linkColor = variant === "mergeRequest" ? isDark ? theme.colors.primary : "#3700B3" : theme.colors.link;
|
|
4986
5164
|
const linkWeight = variant === "mergeRequest" ? theme.typography.fontWeight.semibold : void 0;
|
|
@@ -4988,40 +5166,96 @@ function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
|
|
|
4988
5166
|
const codeTextColor = isDark ? "#FFFFFF" : theme.colors.text;
|
|
4989
5167
|
const paragraphBottom = variant === "mergeRequest" ? 8 : 6;
|
|
4990
5168
|
const baseLineHeight = variant === "mergeRequest" ? 22 : 20;
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
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
|
+
}
|
|
5006
5226
|
},
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
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 }]
|
|
5013
5243
|
},
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
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
|
+
] }) });
|
|
5025
5259
|
}
|
|
5026
5260
|
|
|
5027
5261
|
// src/components/merge-requests/mergeRequestStatusDisplay.ts
|
|
@@ -5068,7 +5302,7 @@ function useControlledExpansion(props) {
|
|
|
5068
5302
|
}
|
|
5069
5303
|
|
|
5070
5304
|
// src/components/merge-requests/MergeRequestStatusCard.tsx
|
|
5071
|
-
import { jsx as jsx40, jsxs as
|
|
5305
|
+
import { jsx as jsx40, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
5072
5306
|
function MergeRequestStatusCard({
|
|
5073
5307
|
mergeRequest,
|
|
5074
5308
|
expanded: expandedProp,
|
|
@@ -5121,7 +5355,7 @@ function MergeRequestStatusCard({
|
|
|
5121
5355
|
useNativeDriver: true
|
|
5122
5356
|
}).start();
|
|
5123
5357
|
}, [expanded, rotate]);
|
|
5124
|
-
return /* @__PURE__ */ jsx40(
|
|
5358
|
+
return /* @__PURE__ */ jsx40(Pressable10, { onPress: () => setExpanded(!expanded), style: ({ pressed }) => [{ opacity: pressed ? 0.95 : 1 }], children: /* @__PURE__ */ jsxs23(
|
|
5125
5359
|
Card,
|
|
5126
5360
|
{
|
|
5127
5361
|
padded: false,
|
|
@@ -5134,10 +5368,10 @@ function MergeRequestStatusCard({
|
|
|
5134
5368
|
style
|
|
5135
5369
|
],
|
|
5136
5370
|
children: [
|
|
5137
|
-
/* @__PURE__ */
|
|
5371
|
+
/* @__PURE__ */ jsxs23(View28, { style: { flexDirection: "row", alignItems: "center", gap: theme.spacing.lg }, children: [
|
|
5138
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 }) }),
|
|
5139
|
-
/* @__PURE__ */
|
|
5140
|
-
/* @__PURE__ */
|
|
5373
|
+
/* @__PURE__ */ jsxs23(View28, { style: { flex: 1, minWidth: 0 }, children: [
|
|
5374
|
+
/* @__PURE__ */ jsxs23(View28, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
5141
5375
|
/* @__PURE__ */ jsx40(
|
|
5142
5376
|
Text,
|
|
5143
5377
|
{
|
|
@@ -5170,7 +5404,7 @@ function MergeRequestStatusCard({
|
|
|
5170
5404
|
}
|
|
5171
5405
|
)
|
|
5172
5406
|
] }),
|
|
5173
|
-
expanded ? /* @__PURE__ */
|
|
5407
|
+
expanded ? /* @__PURE__ */ jsxs23(View28, { style: { marginTop: 16, marginLeft: 56 }, children: [
|
|
5174
5408
|
/* @__PURE__ */ jsx40(
|
|
5175
5409
|
Text,
|
|
5176
5410
|
{
|
|
@@ -5210,12 +5444,12 @@ import { Animated as Animated9, FlatList, View as View31, useWindowDimensions as
|
|
|
5210
5444
|
|
|
5211
5445
|
// src/components/merge-requests/ReviewMergeRequestCard.tsx
|
|
5212
5446
|
import * as React30 from "react";
|
|
5213
|
-
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";
|
|
5214
5448
|
import { Check as Check4, ChevronDown as ChevronDown3, Play as Play3, X as X3 } from "lucide-react-native";
|
|
5215
5449
|
|
|
5216
5450
|
// src/components/merge-requests/ReviewMergeRequestActionButton.tsx
|
|
5217
5451
|
import * as React29 from "react";
|
|
5218
|
-
import { Pressable as
|
|
5452
|
+
import { Pressable as Pressable11, View as View29 } from "react-native";
|
|
5219
5453
|
import { jsx as jsx41 } from "react/jsx-runtime";
|
|
5220
5454
|
function ReviewMergeRequestActionButton({
|
|
5221
5455
|
accessibilityLabel,
|
|
@@ -5247,7 +5481,7 @@ function ReviewMergeRequestActionButton({
|
|
|
5247
5481
|
justifyContent: "center"
|
|
5248
5482
|
},
|
|
5249
5483
|
children: /* @__PURE__ */ jsx41(
|
|
5250
|
-
|
|
5484
|
+
Pressable11,
|
|
5251
5485
|
{
|
|
5252
5486
|
accessibilityRole: "button",
|
|
5253
5487
|
accessibilityLabel,
|
|
@@ -5270,7 +5504,7 @@ function ReviewMergeRequestActionButton({
|
|
|
5270
5504
|
}
|
|
5271
5505
|
|
|
5272
5506
|
// src/components/merge-requests/ReviewMergeRequestCard.tsx
|
|
5273
|
-
import { jsx as jsx42, jsxs as
|
|
5507
|
+
import { jsx as jsx42, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
5274
5508
|
function ReviewMergeRequestCard({
|
|
5275
5509
|
mr,
|
|
5276
5510
|
index,
|
|
@@ -5294,7 +5528,7 @@ function ReviewMergeRequestCard({
|
|
|
5294
5528
|
Animated8.timing(rotate, { toValue: isExpanded ? 1 : 0, duration: 200, useNativeDriver: true }).start();
|
|
5295
5529
|
}, [isExpanded, rotate]);
|
|
5296
5530
|
const position = total > 1 ? `${index + 1}/${total}` : "Merge request";
|
|
5297
|
-
return /* @__PURE__ */ jsx42(
|
|
5531
|
+
return /* @__PURE__ */ jsx42(Pressable12, { onPress: onToggle, style: ({ pressed }) => ({ opacity: pressed ? 0.95 : 1 }), children: /* @__PURE__ */ jsxs24(
|
|
5298
5532
|
Card,
|
|
5299
5533
|
{
|
|
5300
5534
|
padded: false,
|
|
@@ -5307,9 +5541,9 @@ function ReviewMergeRequestCard({
|
|
|
5307
5541
|
}
|
|
5308
5542
|
],
|
|
5309
5543
|
children: [
|
|
5310
|
-
/* @__PURE__ */
|
|
5544
|
+
/* @__PURE__ */ jsxs24(View30, { style: { flexDirection: "row", alignItems: "center", gap: 12 }, children: [
|
|
5311
5545
|
/* @__PURE__ */ jsx42(Avatar, { size: 40, uri: (creator == null ? void 0 : creator.avatar) ?? null, name: (creator == null ? void 0 : creator.name) ?? void 0 }),
|
|
5312
|
-
/* @__PURE__ */
|
|
5546
|
+
/* @__PURE__ */ jsxs24(View30, { style: { flex: 1, minWidth: 0 }, children: [
|
|
5313
5547
|
/* @__PURE__ */ jsx42(
|
|
5314
5548
|
Text,
|
|
5315
5549
|
{
|
|
@@ -5318,7 +5552,7 @@ function ReviewMergeRequestCard({
|
|
|
5318
5552
|
children: mr.title ?? "Untitled merge request"
|
|
5319
5553
|
}
|
|
5320
5554
|
),
|
|
5321
|
-
/* @__PURE__ */
|
|
5555
|
+
/* @__PURE__ */ jsxs24(Text, { style: { color: theme.colors.textMuted, fontSize: 12, lineHeight: 16 }, numberOfLines: 1, children: [
|
|
5322
5556
|
(creator == null ? void 0 : creator.name) ?? "Loading...",
|
|
5323
5557
|
" \xB7 ",
|
|
5324
5558
|
position
|
|
@@ -5334,7 +5568,7 @@ function ReviewMergeRequestCard({
|
|
|
5334
5568
|
}
|
|
5335
5569
|
)
|
|
5336
5570
|
] }),
|
|
5337
|
-
isExpanded ? /* @__PURE__ */
|
|
5571
|
+
isExpanded ? /* @__PURE__ */ jsxs24(View30, { style: { marginTop: 16 }, children: [
|
|
5338
5572
|
/* @__PURE__ */ jsx42(
|
|
5339
5573
|
Text,
|
|
5340
5574
|
{
|
|
@@ -5349,12 +5583,12 @@ function ReviewMergeRequestCard({
|
|
|
5349
5583
|
children: status.text
|
|
5350
5584
|
}
|
|
5351
5585
|
),
|
|
5352
|
-
/* @__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..." }),
|
|
5353
5587
|
mr.description ? /* @__PURE__ */ jsx42(MarkdownText, { markdown: mr.description, variant: "mergeRequest" }) : null
|
|
5354
5588
|
] }) : null,
|
|
5355
5589
|
/* @__PURE__ */ jsx42(View30, { style: { height: 1, backgroundColor: withAlpha(theme.colors.borderStrong, 0.5), marginTop: 12, marginBottom: 12 } }),
|
|
5356
|
-
/* @__PURE__ */
|
|
5357
|
-
/* @__PURE__ */
|
|
5590
|
+
/* @__PURE__ */ jsxs24(View30, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
5591
|
+
/* @__PURE__ */ jsxs24(View30, { style: { flexDirection: "row", gap: 8 }, children: [
|
|
5358
5592
|
/* @__PURE__ */ jsx42(
|
|
5359
5593
|
ReviewMergeRequestActionButton,
|
|
5360
5594
|
{
|
|
@@ -5363,7 +5597,7 @@ function ReviewMergeRequestCard({
|
|
|
5363
5597
|
disabled: !canAct || isAnyProcessing,
|
|
5364
5598
|
onPress: onReject,
|
|
5365
5599
|
iconOnly: !isExpanded,
|
|
5366
|
-
children: /* @__PURE__ */
|
|
5600
|
+
children: /* @__PURE__ */ jsxs24(View30, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
|
|
5367
5601
|
/* @__PURE__ */ jsx42(X3, { size: 18, color: "#FFFFFF" }),
|
|
5368
5602
|
isExpanded ? /* @__PURE__ */ jsx42(Text, { style: { fontSize: 13, color: "#FFFFFF", fontWeight: theme.typography.fontWeight.semibold }, children: "Reject" }) : null
|
|
5369
5603
|
] })
|
|
@@ -5377,10 +5611,10 @@ function ReviewMergeRequestCard({
|
|
|
5377
5611
|
disabled: !canAct || isAnyProcessing,
|
|
5378
5612
|
onPress: onApprove,
|
|
5379
5613
|
iconOnly: !isExpanded,
|
|
5380
|
-
children: isProcessing ? /* @__PURE__ */
|
|
5614
|
+
children: isProcessing ? /* @__PURE__ */ jsxs24(View30, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
|
|
5381
5615
|
/* @__PURE__ */ jsx42(ActivityIndicator5, { size: "small", color: "#FFFFFF" }),
|
|
5382
5616
|
isExpanded ? /* @__PURE__ */ jsx42(Text, { style: { fontSize: 13, color: "#FFFFFF", fontWeight: theme.typography.fontWeight.semibold }, children: "Processing" }) : null
|
|
5383
|
-
] }) : /* @__PURE__ */
|
|
5617
|
+
] }) : /* @__PURE__ */ jsxs24(View30, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
|
|
5384
5618
|
/* @__PURE__ */ jsx42(Check4, { size: 18, color: "#FFFFFF" }),
|
|
5385
5619
|
isExpanded ? /* @__PURE__ */ jsx42(Text, { style: { fontSize: 13, color: "#FFFFFF", fontWeight: theme.typography.fontWeight.semibold }, children: "Approve" }) : null
|
|
5386
5620
|
] })
|
|
@@ -5395,7 +5629,7 @@ function ReviewMergeRequestCard({
|
|
|
5395
5629
|
disabled: isBuilding || isTestingThis,
|
|
5396
5630
|
onPress: onTest,
|
|
5397
5631
|
iconOnly: !isExpanded,
|
|
5398
|
-
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: [
|
|
5399
5633
|
/* @__PURE__ */ jsx42(Play3, { size: 14, color: theme.colors.text }),
|
|
5400
5634
|
isExpanded ? /* @__PURE__ */ jsx42(Text, { style: { fontSize: 13, color: theme.colors.text, fontWeight: theme.typography.fontWeight.semibold }, children: "Test" }) : null
|
|
5401
5635
|
] })
|
|
@@ -5408,7 +5642,7 @@ function ReviewMergeRequestCard({
|
|
|
5408
5642
|
}
|
|
5409
5643
|
|
|
5410
5644
|
// src/components/merge-requests/ReviewMergeRequestCarousel.tsx
|
|
5411
|
-
import { jsx as jsx43, jsxs as
|
|
5645
|
+
import { jsx as jsx43, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
5412
5646
|
function ReviewMergeRequestCarousel({
|
|
5413
5647
|
mergeRequests,
|
|
5414
5648
|
creatorStatsById,
|
|
@@ -5430,7 +5664,7 @@ function ReviewMergeRequestCarousel({
|
|
|
5430
5664
|
const snapInterval = cardWidth + gap;
|
|
5431
5665
|
const dotColor = theme.scheme === "dark" ? "#FFFFFF" : "#000000";
|
|
5432
5666
|
if (mergeRequests.length === 0) return null;
|
|
5433
|
-
return /* @__PURE__ */
|
|
5667
|
+
return /* @__PURE__ */ jsxs25(View31, { style: [{ marginHorizontal: -theme.spacing.lg }, style], children: [
|
|
5434
5668
|
/* @__PURE__ */ jsx43(
|
|
5435
5669
|
FlatList,
|
|
5436
5670
|
{
|
|
@@ -5509,7 +5743,7 @@ function ReviewMergeRequestCarousel({
|
|
|
5509
5743
|
}
|
|
5510
5744
|
|
|
5511
5745
|
// src/studio/ui/preview-panel/PreviewCollaborateSection.tsx
|
|
5512
|
-
import { Fragment as Fragment5, jsx as jsx44, jsxs as
|
|
5746
|
+
import { Fragment as Fragment5, jsx as jsx44, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
5513
5747
|
function PreviewCollaborateSection({
|
|
5514
5748
|
canSubmitMergeRequest,
|
|
5515
5749
|
canSyncUpstream,
|
|
@@ -5535,7 +5769,7 @@ function PreviewCollaborateSection({
|
|
|
5535
5769
|
if (!hasSection) return null;
|
|
5536
5770
|
const isSyncing = Boolean(syncingUpstream || syncingLocal);
|
|
5537
5771
|
const showActionsSubtitle = canSubmitMergeRequest && onSubmitMergeRequest || canSyncUpstream && onSyncUpstream || onTestMr && incomingMergeRequests.length > 0;
|
|
5538
|
-
return /* @__PURE__ */
|
|
5772
|
+
return /* @__PURE__ */ jsxs26(Fragment5, { children: [
|
|
5539
5773
|
/* @__PURE__ */ jsx44(SectionTitle, { marginTop: theme.spacing.xl, children: "Collaborate" }),
|
|
5540
5774
|
showActionsSubtitle ? /* @__PURE__ */ jsx44(
|
|
5541
5775
|
Text,
|
|
@@ -5674,7 +5908,7 @@ function PreviewCollaborateSection({
|
|
|
5674
5908
|
onTest: (mr) => onTestMr ? onTestMr(mr) : void 0
|
|
5675
5909
|
}
|
|
5676
5910
|
) : null,
|
|
5677
|
-
outgoingMergeRequests.length > 0 ? /* @__PURE__ */
|
|
5911
|
+
outgoingMergeRequests.length > 0 ? /* @__PURE__ */ jsxs26(Fragment5, { children: [
|
|
5678
5912
|
/* @__PURE__ */ jsx44(
|
|
5679
5913
|
Text,
|
|
5680
5914
|
{
|
|
@@ -5989,7 +6223,7 @@ function usePreviewPanelData(params) {
|
|
|
5989
6223
|
}
|
|
5990
6224
|
|
|
5991
6225
|
// src/studio/ui/PreviewPanel.tsx
|
|
5992
|
-
import { jsx as jsx45, jsxs as
|
|
6226
|
+
import { jsx as jsx45, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
5993
6227
|
function PreviewPanel({
|
|
5994
6228
|
app,
|
|
5995
6229
|
loading,
|
|
@@ -6024,7 +6258,7 @@ ${shareUrl}` : `Check out this app on Remix
|
|
|
6024
6258
|
${shareUrl}`;
|
|
6025
6259
|
try {
|
|
6026
6260
|
const title = app.name ?? "Remix app";
|
|
6027
|
-
const payload =
|
|
6261
|
+
const payload = Platform7.OS === "ios" ? {
|
|
6028
6262
|
title,
|
|
6029
6263
|
message
|
|
6030
6264
|
} : {
|
|
@@ -6066,13 +6300,13 @@ ${shareUrl}`;
|
|
|
6066
6300
|
}
|
|
6067
6301
|
);
|
|
6068
6302
|
if (loading || !app) {
|
|
6069
|
-
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: [
|
|
6070
6304
|
/* @__PURE__ */ jsx45(ActivityIndicator7, {}),
|
|
6071
6305
|
/* @__PURE__ */ jsx45(View33, { style: { height: 12 } }),
|
|
6072
6306
|
/* @__PURE__ */ jsx45(Text, { variant: "bodyMuted", children: "Loading app\u2026" })
|
|
6073
6307
|
] }) });
|
|
6074
6308
|
}
|
|
6075
|
-
return /* @__PURE__ */
|
|
6309
|
+
return /* @__PURE__ */ jsxs27(PreviewPage, { header, children: [
|
|
6076
6310
|
/* @__PURE__ */ jsx45(
|
|
6077
6311
|
PreviewHeroSection,
|
|
6078
6312
|
{
|
|
@@ -6133,7 +6367,7 @@ import { ActivityIndicator as ActivityIndicator9, View as View42 } from "react-n
|
|
|
6133
6367
|
|
|
6134
6368
|
// src/components/chat/ChatPage.tsx
|
|
6135
6369
|
import * as React38 from "react";
|
|
6136
|
-
import {
|
|
6370
|
+
import { Platform as Platform9, View as View37 } from "react-native";
|
|
6137
6371
|
import { useSafeAreaInsets as useSafeAreaInsets4 } from "react-native-safe-area-context";
|
|
6138
6372
|
|
|
6139
6373
|
// src/components/chat/ChatMessageList.tsx
|
|
@@ -6143,9 +6377,76 @@ import { BottomSheetFlatList } from "@gorhom/bottom-sheet";
|
|
|
6143
6377
|
|
|
6144
6378
|
// src/components/chat/ChatMessageBubble.tsx
|
|
6145
6379
|
import { View as View34 } from "react-native";
|
|
6146
|
-
import { CheckCheck as CheckCheck2, GitMerge as GitMerge2 } from "lucide-react-native";
|
|
6147
|
-
|
|
6148
|
-
|
|
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 }) {
|
|
6149
6450
|
var _a, _b;
|
|
6150
6451
|
const theme = useTheme();
|
|
6151
6452
|
const metaEvent = ((_a = message.meta) == null ? void 0 : _a.event) ?? null;
|
|
@@ -6160,34 +6461,62 @@ function ChatMessageBubble({ message, renderContent, style }) {
|
|
|
6160
6461
|
const bubbleVariant = isHuman ? "surface" : "surfaceRaised";
|
|
6161
6462
|
const cornerStyle = isHuman ? { borderTopRightRadius: 0 } : { borderTopLeftRadius: 0 };
|
|
6162
6463
|
const bodyColor = metaStatus === "success" ? theme.colors.success : metaStatus === "error" ? theme.colors.danger : void 0;
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
/* @__PURE__ */
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6464
|
+
const showRetry = Boolean(onRetry) && isLast && metaStatus === "error";
|
|
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
|
+
] });
|
|
6185
6514
|
}
|
|
6186
6515
|
|
|
6187
6516
|
// src/components/chat/TypingIndicator.tsx
|
|
6188
6517
|
import * as React36 from "react";
|
|
6189
6518
|
import { Animated as Animated10, View as View35 } from "react-native";
|
|
6190
|
-
import { jsx as
|
|
6519
|
+
import { jsx as jsx48 } from "react/jsx-runtime";
|
|
6191
6520
|
function TypingIndicator({ style }) {
|
|
6192
6521
|
const theme = useTheme();
|
|
6193
6522
|
const dotColor = theme.colors.textSubtle;
|
|
@@ -6210,7 +6539,7 @@ function TypingIndicator({ style }) {
|
|
|
6210
6539
|
loops.forEach((l) => l.stop());
|
|
6211
6540
|
};
|
|
6212
6541
|
}, [anims]);
|
|
6213
|
-
return /* @__PURE__ */
|
|
6542
|
+
return /* @__PURE__ */ jsx48(View35, { style: [{ flexDirection: "row", alignItems: "center" }, style], children: anims.map((a, i) => /* @__PURE__ */ jsx48(
|
|
6214
6543
|
Animated10.View,
|
|
6215
6544
|
{
|
|
6216
6545
|
style: {
|
|
@@ -6228,12 +6557,14 @@ function TypingIndicator({ style }) {
|
|
|
6228
6557
|
}
|
|
6229
6558
|
|
|
6230
6559
|
// src/components/chat/ChatMessageList.tsx
|
|
6231
|
-
import { jsx as
|
|
6560
|
+
import { jsx as jsx49, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
6232
6561
|
var ChatMessageList = React37.forwardRef(
|
|
6233
6562
|
({
|
|
6234
6563
|
messages,
|
|
6235
6564
|
showTypingIndicator = false,
|
|
6236
6565
|
renderMessageContent,
|
|
6566
|
+
onRetryMessage,
|
|
6567
|
+
isRetryingMessage,
|
|
6237
6568
|
contentStyle,
|
|
6238
6569
|
bottomInset = 0,
|
|
6239
6570
|
onNearBottomChange,
|
|
@@ -6247,6 +6578,7 @@ var ChatMessageList = React37.forwardRef(
|
|
|
6247
6578
|
const data = React37.useMemo(() => {
|
|
6248
6579
|
return [...messages].reverse();
|
|
6249
6580
|
}, [messages]);
|
|
6581
|
+
const lastMessageId = messages.length > 0 ? messages[messages.length - 1].id : null;
|
|
6250
6582
|
const scrollToBottom = React37.useCallback((options) => {
|
|
6251
6583
|
var _a;
|
|
6252
6584
|
const animated = (options == null ? void 0 : options.animated) ?? true;
|
|
@@ -6282,7 +6614,7 @@ var ChatMessageList = React37.forwardRef(
|
|
|
6282
6614
|
}
|
|
6283
6615
|
return void 0;
|
|
6284
6616
|
}, [showTypingIndicator, scrollToBottom]);
|
|
6285
|
-
return /* @__PURE__ */
|
|
6617
|
+
return /* @__PURE__ */ jsx49(
|
|
6286
6618
|
BottomSheetFlatList,
|
|
6287
6619
|
{
|
|
6288
6620
|
ref: listRef,
|
|
@@ -6308,11 +6640,20 @@ var ChatMessageList = React37.forwardRef(
|
|
|
6308
6640
|
},
|
|
6309
6641
|
contentStyle
|
|
6310
6642
|
],
|
|
6311
|
-
ItemSeparatorComponent: () => /* @__PURE__ */
|
|
6312
|
-
renderItem: ({ item }) => /* @__PURE__ */
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
|
|
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
|
|
6316
6657
|
] })
|
|
6317
6658
|
}
|
|
6318
6659
|
);
|
|
@@ -6321,12 +6662,14 @@ var ChatMessageList = React37.forwardRef(
|
|
|
6321
6662
|
ChatMessageList.displayName = "ChatMessageList";
|
|
6322
6663
|
|
|
6323
6664
|
// src/components/chat/ChatPage.tsx
|
|
6324
|
-
import { jsx as
|
|
6665
|
+
import { jsx as jsx50, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
6325
6666
|
function ChatPage({
|
|
6326
6667
|
header,
|
|
6327
6668
|
messages,
|
|
6328
6669
|
showTypingIndicator,
|
|
6329
6670
|
renderMessageContent,
|
|
6671
|
+
onRetryMessage,
|
|
6672
|
+
isRetryingMessage,
|
|
6330
6673
|
topBanner,
|
|
6331
6674
|
composerTop,
|
|
6332
6675
|
composer,
|
|
@@ -6340,17 +6683,7 @@ function ChatPage({
|
|
|
6340
6683
|
const insets = useSafeAreaInsets4();
|
|
6341
6684
|
const [composerHeight, setComposerHeight] = React38.useState(0);
|
|
6342
6685
|
const [composerTopHeight, setComposerTopHeight] = React38.useState(0);
|
|
6343
|
-
const
|
|
6344
|
-
React38.useEffect(() => {
|
|
6345
|
-
if (Platform10.OS !== "ios") return;
|
|
6346
|
-
const show = Keyboard4.addListener("keyboardWillShow", () => setKeyboardVisible(true));
|
|
6347
|
-
const hide = Keyboard4.addListener("keyboardWillHide", () => setKeyboardVisible(false));
|
|
6348
|
-
return () => {
|
|
6349
|
-
show.remove();
|
|
6350
|
-
hide.remove();
|
|
6351
|
-
};
|
|
6352
|
-
}, []);
|
|
6353
|
-
const footerBottomPadding = Platform10.OS === "ios" ? keyboardVisible ? 0 : insets.bottom : insets.bottom + 10;
|
|
6686
|
+
const footerBottomPadding = Platform9.OS === "ios" ? insets.bottom : insets.bottom + 10;
|
|
6354
6687
|
const totalComposerHeight = composerHeight + composerTopHeight;
|
|
6355
6688
|
const overlayBottom = totalComposerHeight + footerBottomPadding + theme.spacing.lg;
|
|
6356
6689
|
const bottomInset = totalComposerHeight + footerBottomPadding + theme.spacing.xl;
|
|
@@ -6367,22 +6700,24 @@ function ChatPage({
|
|
|
6367
6700
|
if (composerTop) return;
|
|
6368
6701
|
setComposerTopHeight(0);
|
|
6369
6702
|
}, [composerTop]);
|
|
6370
|
-
return /* @__PURE__ */
|
|
6371
|
-
header ? /* @__PURE__ */
|
|
6372
|
-
topBanner ? /* @__PURE__ */
|
|
6373
|
-
/* @__PURE__ */
|
|
6374
|
-
/* @__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(
|
|
6375
6708
|
View37,
|
|
6376
6709
|
{
|
|
6377
6710
|
style: { flex: 1 },
|
|
6378
6711
|
children: [
|
|
6379
|
-
/* @__PURE__ */
|
|
6712
|
+
/* @__PURE__ */ jsx50(
|
|
6380
6713
|
ChatMessageList,
|
|
6381
6714
|
{
|
|
6382
6715
|
ref: listRef,
|
|
6383
6716
|
messages,
|
|
6384
6717
|
showTypingIndicator,
|
|
6385
6718
|
renderMessageContent,
|
|
6719
|
+
onRetryMessage,
|
|
6720
|
+
isRetryingMessage,
|
|
6386
6721
|
onNearBottomChange,
|
|
6387
6722
|
bottomInset
|
|
6388
6723
|
}
|
|
@@ -6391,7 +6726,7 @@ function ChatPage({
|
|
|
6391
6726
|
]
|
|
6392
6727
|
}
|
|
6393
6728
|
),
|
|
6394
|
-
/* @__PURE__ */
|
|
6729
|
+
/* @__PURE__ */ jsxs30(
|
|
6395
6730
|
View37,
|
|
6396
6731
|
{
|
|
6397
6732
|
style: {
|
|
@@ -6404,7 +6739,7 @@ function ChatPage({
|
|
|
6404
6739
|
paddingBottom: footerBottomPadding
|
|
6405
6740
|
},
|
|
6406
6741
|
children: [
|
|
6407
|
-
composerTop ? /* @__PURE__ */
|
|
6742
|
+
composerTop ? /* @__PURE__ */ jsx50(
|
|
6408
6743
|
View37,
|
|
6409
6744
|
{
|
|
6410
6745
|
style: { marginBottom: theme.spacing.sm },
|
|
@@ -6412,7 +6747,7 @@ function ChatPage({
|
|
|
6412
6747
|
children: composerTop
|
|
6413
6748
|
}
|
|
6414
6749
|
) : null,
|
|
6415
|
-
/* @__PURE__ */
|
|
6750
|
+
/* @__PURE__ */ jsx50(
|
|
6416
6751
|
ChatComposer,
|
|
6417
6752
|
{
|
|
6418
6753
|
...composer,
|
|
@@ -6429,9 +6764,9 @@ function ChatPage({
|
|
|
6429
6764
|
|
|
6430
6765
|
// src/components/chat/ScrollToBottomButton.tsx
|
|
6431
6766
|
import * as React39 from "react";
|
|
6432
|
-
import { Pressable as
|
|
6767
|
+
import { Pressable as Pressable14, View as View38 } from "react-native";
|
|
6433
6768
|
import Animated11, { Easing as Easing2, useAnimatedStyle as useAnimatedStyle2, useSharedValue as useSharedValue2, withTiming as withTiming2 } from "react-native-reanimated";
|
|
6434
|
-
import { jsx as
|
|
6769
|
+
import { jsx as jsx51 } from "react/jsx-runtime";
|
|
6435
6770
|
function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
6436
6771
|
const theme = useTheme();
|
|
6437
6772
|
const progress = useSharedValue2(visible ? 1 : 0);
|
|
@@ -6445,7 +6780,7 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
|
6445
6780
|
}));
|
|
6446
6781
|
const bg = theme.scheme === "dark" ? "rgba(39,39,42,0.9)" : "rgba(244,244,245,0.95)";
|
|
6447
6782
|
const border = theme.scheme === "dark" ? withAlpha("#FFFFFF", 0.12) : withAlpha("#000000", 0.08);
|
|
6448
|
-
return /* @__PURE__ */
|
|
6783
|
+
return /* @__PURE__ */ jsx51(
|
|
6449
6784
|
Animated11.View,
|
|
6450
6785
|
{
|
|
6451
6786
|
pointerEvents: visible ? "auto" : "none",
|
|
@@ -6459,7 +6794,7 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
|
6459
6794
|
style,
|
|
6460
6795
|
animStyle
|
|
6461
6796
|
],
|
|
6462
|
-
children: /* @__PURE__ */
|
|
6797
|
+
children: /* @__PURE__ */ jsx51(
|
|
6463
6798
|
View38,
|
|
6464
6799
|
{
|
|
6465
6800
|
style: {
|
|
@@ -6478,8 +6813,8 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
|
6478
6813
|
elevation: 5,
|
|
6479
6814
|
opacity: pressed ? 0.85 : 1
|
|
6480
6815
|
},
|
|
6481
|
-
children: /* @__PURE__ */
|
|
6482
|
-
|
|
6816
|
+
children: /* @__PURE__ */ jsx51(
|
|
6817
|
+
Pressable14,
|
|
6483
6818
|
{
|
|
6484
6819
|
onPress,
|
|
6485
6820
|
onPressIn: () => setPressed(true),
|
|
@@ -6497,7 +6832,7 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
|
6497
6832
|
|
|
6498
6833
|
// src/components/chat/ChatHeader.tsx
|
|
6499
6834
|
import { StyleSheet as StyleSheet4 } from "react-native";
|
|
6500
|
-
import { jsx as
|
|
6835
|
+
import { jsx as jsx52 } from "react/jsx-runtime";
|
|
6501
6836
|
function ChatHeader({ left, right, center, style }) {
|
|
6502
6837
|
const flattenedStyle = StyleSheet4.flatten([
|
|
6503
6838
|
{
|
|
@@ -6505,7 +6840,7 @@ function ChatHeader({ left, right, center, style }) {
|
|
|
6505
6840
|
},
|
|
6506
6841
|
style
|
|
6507
6842
|
]);
|
|
6508
|
-
return /* @__PURE__ */
|
|
6843
|
+
return /* @__PURE__ */ jsx52(
|
|
6509
6844
|
StudioSheetHeader,
|
|
6510
6845
|
{
|
|
6511
6846
|
left,
|
|
@@ -6518,12 +6853,12 @@ function ChatHeader({ left, right, center, style }) {
|
|
|
6518
6853
|
|
|
6519
6854
|
// src/components/chat/ForkNoticeBanner.tsx
|
|
6520
6855
|
import { View as View40 } from "react-native";
|
|
6521
|
-
import { jsx as
|
|
6856
|
+
import { jsx as jsx53, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
6522
6857
|
function ForkNoticeBanner({ isOwner = true, title, description, style }) {
|
|
6523
6858
|
const theme = useTheme();
|
|
6524
6859
|
const resolvedTitle = title ?? (isOwner ? "Remixed app" : "Remix app");
|
|
6525
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.");
|
|
6526
|
-
return /* @__PURE__ */
|
|
6861
|
+
return /* @__PURE__ */ jsx53(
|
|
6527
6862
|
Card,
|
|
6528
6863
|
{
|
|
6529
6864
|
variant: "surfaceRaised",
|
|
@@ -6538,8 +6873,8 @@ function ForkNoticeBanner({ isOwner = true, title, description, style }) {
|
|
|
6538
6873
|
},
|
|
6539
6874
|
style
|
|
6540
6875
|
],
|
|
6541
|
-
children: /* @__PURE__ */
|
|
6542
|
-
/* @__PURE__ */
|
|
6876
|
+
children: /* @__PURE__ */ jsxs31(View40, { style: { minWidth: 0 }, children: [
|
|
6877
|
+
/* @__PURE__ */ jsx53(
|
|
6543
6878
|
Text,
|
|
6544
6879
|
{
|
|
6545
6880
|
style: {
|
|
@@ -6553,7 +6888,7 @@ function ForkNoticeBanner({ isOwner = true, title, description, style }) {
|
|
|
6553
6888
|
children: resolvedTitle
|
|
6554
6889
|
}
|
|
6555
6890
|
),
|
|
6556
|
-
/* @__PURE__ */
|
|
6891
|
+
/* @__PURE__ */ jsx53(
|
|
6557
6892
|
Text,
|
|
6558
6893
|
{
|
|
6559
6894
|
style: {
|
|
@@ -6572,8 +6907,8 @@ function ForkNoticeBanner({ isOwner = true, title, description, style }) {
|
|
|
6572
6907
|
|
|
6573
6908
|
// src/components/chat/ChatQueue.tsx
|
|
6574
6909
|
import * as React40 from "react";
|
|
6575
|
-
import { ActivityIndicator as ActivityIndicator8, Pressable as
|
|
6576
|
-
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";
|
|
6577
6912
|
function ChatQueue({ items, onRemove }) {
|
|
6578
6913
|
const theme = useTheme();
|
|
6579
6914
|
const [expanded, setExpanded] = React40.useState({});
|
|
@@ -6605,7 +6940,7 @@ ${trimmedLine2}\u2026 `;
|
|
|
6605
6940
|
setRemoving((prev) => Object.fromEntries(Object.entries(prev).filter(([id]) => ids.has(id))));
|
|
6606
6941
|
}, [items]);
|
|
6607
6942
|
if (items.length === 0) return null;
|
|
6608
|
-
return /* @__PURE__ */
|
|
6943
|
+
return /* @__PURE__ */ jsxs32(
|
|
6609
6944
|
View41,
|
|
6610
6945
|
{
|
|
6611
6946
|
style: {
|
|
@@ -6617,15 +6952,15 @@ ${trimmedLine2}\u2026 `;
|
|
|
6617
6952
|
backgroundColor: "transparent"
|
|
6618
6953
|
},
|
|
6619
6954
|
children: [
|
|
6620
|
-
/* @__PURE__ */
|
|
6621
|
-
/* @__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) => {
|
|
6622
6957
|
const isExpanded = Boolean(expanded[item.id]);
|
|
6623
6958
|
const showToggle = Boolean(canExpand[item.id]);
|
|
6624
6959
|
const prompt = item.prompt ?? "";
|
|
6625
6960
|
const moreLabel = "more";
|
|
6626
6961
|
const displayPrompt = !isExpanded && showToggle && collapsedText[item.id] ? collapsedText[item.id] : prompt;
|
|
6627
6962
|
const isRemoving = Boolean(removing[item.id]);
|
|
6628
|
-
return /* @__PURE__ */
|
|
6963
|
+
return /* @__PURE__ */ jsxs32(
|
|
6629
6964
|
View41,
|
|
6630
6965
|
{
|
|
6631
6966
|
style: {
|
|
@@ -6638,8 +6973,8 @@ ${trimmedLine2}\u2026 `;
|
|
|
6638
6973
|
backgroundColor: withAlpha(theme.colors.surface, theme.scheme === "dark" ? 0.8 : 0.9)
|
|
6639
6974
|
},
|
|
6640
6975
|
children: [
|
|
6641
|
-
/* @__PURE__ */
|
|
6642
|
-
!canExpand[item.id] ? /* @__PURE__ */
|
|
6976
|
+
/* @__PURE__ */ jsxs32(View41, { style: { flex: 1 }, children: [
|
|
6977
|
+
!canExpand[item.id] ? /* @__PURE__ */ jsx54(
|
|
6643
6978
|
Text,
|
|
6644
6979
|
{
|
|
6645
6980
|
style: { position: "absolute", opacity: 0, zIndex: -1, width: "100%" },
|
|
@@ -6658,14 +6993,14 @@ ${trimmedLine2}\u2026 `;
|
|
|
6658
6993
|
children: prompt
|
|
6659
6994
|
}
|
|
6660
6995
|
) : null,
|
|
6661
|
-
/* @__PURE__ */
|
|
6996
|
+
/* @__PURE__ */ jsxs32(
|
|
6662
6997
|
Text,
|
|
6663
6998
|
{
|
|
6664
6999
|
variant: "bodyMuted",
|
|
6665
7000
|
numberOfLines: isExpanded ? void 0 : 2,
|
|
6666
7001
|
children: [
|
|
6667
7002
|
displayPrompt,
|
|
6668
|
-
!isExpanded && showToggle ? /* @__PURE__ */
|
|
7003
|
+
!isExpanded && showToggle ? /* @__PURE__ */ jsx54(
|
|
6669
7004
|
Text,
|
|
6670
7005
|
{
|
|
6671
7006
|
color: theme.colors.text,
|
|
@@ -6677,18 +7012,18 @@ ${trimmedLine2}\u2026 `;
|
|
|
6677
7012
|
]
|
|
6678
7013
|
}
|
|
6679
7014
|
),
|
|
6680
|
-
showToggle && isExpanded ? /* @__PURE__ */
|
|
6681
|
-
|
|
7015
|
+
showToggle && isExpanded ? /* @__PURE__ */ jsx54(
|
|
7016
|
+
Pressable15,
|
|
6682
7017
|
{
|
|
6683
7018
|
onPress: () => setExpanded((prev) => ({ ...prev, [item.id]: false })),
|
|
6684
7019
|
hitSlop: 6,
|
|
6685
7020
|
style: { alignSelf: "flex-start", marginTop: 4 },
|
|
6686
|
-
children: /* @__PURE__ */
|
|
7021
|
+
children: /* @__PURE__ */ jsx54(Text, { variant: "captionMuted", color: theme.colors.text, children: "less" })
|
|
6687
7022
|
}
|
|
6688
7023
|
) : null
|
|
6689
7024
|
] }),
|
|
6690
|
-
/* @__PURE__ */
|
|
6691
|
-
|
|
7025
|
+
/* @__PURE__ */ jsx54(
|
|
7026
|
+
Pressable15,
|
|
6692
7027
|
{
|
|
6693
7028
|
onPress: () => {
|
|
6694
7029
|
if (!onRemove || isRemoving) return;
|
|
@@ -6703,7 +7038,7 @@ ${trimmedLine2}\u2026 `;
|
|
|
6703
7038
|
},
|
|
6704
7039
|
hitSlop: 8,
|
|
6705
7040
|
style: { alignSelf: "center" },
|
|
6706
|
-
children: isRemoving ? /* @__PURE__ */
|
|
7041
|
+
children: isRemoving ? /* @__PURE__ */ jsx54(ActivityIndicator8, { size: "small", color: theme.colors.text }) : /* @__PURE__ */ jsx54(IconClose, { size: 14, colorToken: "text" })
|
|
6707
7042
|
}
|
|
6708
7043
|
)
|
|
6709
7044
|
]
|
|
@@ -6717,10 +7052,9 @@ ${trimmedLine2}\u2026 `;
|
|
|
6717
7052
|
}
|
|
6718
7053
|
|
|
6719
7054
|
// src/studio/ui/ChatPanel.tsx
|
|
6720
|
-
import { jsx as
|
|
7055
|
+
import { jsx as jsx55, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
6721
7056
|
function ChatPanel({
|
|
6722
7057
|
title = "Chat",
|
|
6723
|
-
autoFocusComposer = false,
|
|
6724
7058
|
messages,
|
|
6725
7059
|
showTypingIndicator,
|
|
6726
7060
|
loading,
|
|
@@ -6736,6 +7070,8 @@ function ChatPanel({
|
|
|
6736
7070
|
onNavigateHome,
|
|
6737
7071
|
onStartDraw,
|
|
6738
7072
|
onSend,
|
|
7073
|
+
onRetryMessage,
|
|
7074
|
+
isRetryingMessage,
|
|
6739
7075
|
queueItems = [],
|
|
6740
7076
|
onRemoveQueueItem
|
|
6741
7077
|
}) {
|
|
@@ -6759,21 +7095,21 @@ function ChatPanel({
|
|
|
6759
7095
|
var _a;
|
|
6760
7096
|
(_a = listRef.current) == null ? void 0 : _a.scrollToBottom({ animated: true });
|
|
6761
7097
|
}, []);
|
|
6762
|
-
const header = /* @__PURE__ */
|
|
7098
|
+
const header = /* @__PURE__ */ jsx55(
|
|
6763
7099
|
ChatHeader,
|
|
6764
7100
|
{
|
|
6765
|
-
left: /* @__PURE__ */
|
|
6766
|
-
/* @__PURE__ */
|
|
6767
|
-
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
|
|
6768
7104
|
] }),
|
|
6769
|
-
right: /* @__PURE__ */
|
|
6770
|
-
onStartDraw ? /* @__PURE__ */
|
|
6771
|
-
/* @__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" }) })
|
|
6772
7108
|
] }),
|
|
6773
7109
|
center: null
|
|
6774
7110
|
}
|
|
6775
7111
|
);
|
|
6776
|
-
const topBanner = shouldForkOnEdit ? /* @__PURE__ */
|
|
7112
|
+
const topBanner = shouldForkOnEdit ? /* @__PURE__ */ jsx55(
|
|
6777
7113
|
ForkNoticeBanner,
|
|
6778
7114
|
{
|
|
6779
7115
|
isOwner: !shouldForkOnEdit,
|
|
@@ -6782,35 +7118,37 @@ function ChatPanel({
|
|
|
6782
7118
|
) : null;
|
|
6783
7119
|
const showMessagesLoading = Boolean(loading) && messages.length === 0 || forking;
|
|
6784
7120
|
if (showMessagesLoading) {
|
|
6785
|
-
return /* @__PURE__ */
|
|
6786
|
-
/* @__PURE__ */
|
|
6787
|
-
topBanner ? /* @__PURE__ */
|
|
6788
|
-
/* @__PURE__ */
|
|
6789
|
-
/* @__PURE__ */
|
|
6790
|
-
/* @__PURE__ */
|
|
6791
|
-
/* @__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" })
|
|
6792
7128
|
] })
|
|
6793
7129
|
] });
|
|
6794
7130
|
}
|
|
6795
|
-
const queueTop = queueItems.length > 0 ? /* @__PURE__ */
|
|
6796
|
-
return /* @__PURE__ */
|
|
7131
|
+
const queueTop = queueItems.length > 0 ? /* @__PURE__ */ jsx55(ChatQueue, { items: queueItems, onRemove: onRemoveQueueItem }) : null;
|
|
7132
|
+
return /* @__PURE__ */ jsx55(
|
|
6797
7133
|
ChatPage,
|
|
6798
7134
|
{
|
|
6799
7135
|
header,
|
|
6800
7136
|
messages,
|
|
6801
7137
|
showTypingIndicator,
|
|
7138
|
+
onRetryMessage,
|
|
7139
|
+
isRetryingMessage,
|
|
6802
7140
|
topBanner,
|
|
6803
7141
|
composerTop: queueTop,
|
|
6804
7142
|
composerHorizontalPadding: 0,
|
|
6805
7143
|
listRef,
|
|
6806
7144
|
onNearBottomChange: setNearBottom,
|
|
6807
|
-
overlay: /* @__PURE__ */
|
|
7145
|
+
overlay: /* @__PURE__ */ jsx55(
|
|
6808
7146
|
ScrollToBottomButton,
|
|
6809
7147
|
{
|
|
6810
7148
|
visible: !nearBottom,
|
|
6811
7149
|
onPress: handleScrollToBottom,
|
|
6812
7150
|
style: { bottom: 80 },
|
|
6813
|
-
children: /* @__PURE__ */
|
|
7151
|
+
children: /* @__PURE__ */ jsx55(IconArrowDown, { size: 20, colorToken: "floatingContent" })
|
|
6814
7152
|
}
|
|
6815
7153
|
),
|
|
6816
7154
|
composer: {
|
|
@@ -6819,7 +7157,6 @@ function ChatPanel({
|
|
|
6819
7157
|
disabled: Boolean(loading) || Boolean(forking),
|
|
6820
7158
|
sendDisabled: Boolean(sendDisabled) || Boolean(loading) || Boolean(forking),
|
|
6821
7159
|
sending: Boolean(sending),
|
|
6822
|
-
autoFocus: autoFocusComposer,
|
|
6823
7160
|
onSend: handleSend,
|
|
6824
7161
|
attachments,
|
|
6825
7162
|
onRemoveAttachment,
|
|
@@ -6832,15 +7169,15 @@ function ChatPanel({
|
|
|
6832
7169
|
|
|
6833
7170
|
// src/components/dialogs/ConfirmMergeRequestDialog.tsx
|
|
6834
7171
|
import * as React42 from "react";
|
|
6835
|
-
import { Pressable as
|
|
7172
|
+
import { Pressable as Pressable17, View as View44 } from "react-native";
|
|
6836
7173
|
|
|
6837
7174
|
// src/components/primitives/Modal.tsx
|
|
6838
7175
|
import {
|
|
6839
7176
|
Modal as RNModal,
|
|
6840
|
-
Pressable as
|
|
7177
|
+
Pressable as Pressable16,
|
|
6841
7178
|
View as View43
|
|
6842
7179
|
} from "react-native";
|
|
6843
|
-
import { jsx as
|
|
7180
|
+
import { jsx as jsx56, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
6844
7181
|
function Modal({
|
|
6845
7182
|
visible,
|
|
6846
7183
|
onRequestClose,
|
|
@@ -6849,30 +7186,30 @@ function Modal({
|
|
|
6849
7186
|
contentStyle
|
|
6850
7187
|
}) {
|
|
6851
7188
|
const theme = useTheme();
|
|
6852
|
-
return /* @__PURE__ */
|
|
7189
|
+
return /* @__PURE__ */ jsx56(
|
|
6853
7190
|
RNModal,
|
|
6854
7191
|
{
|
|
6855
7192
|
visible,
|
|
6856
7193
|
transparent: true,
|
|
6857
7194
|
animationType: "fade",
|
|
6858
7195
|
onRequestClose,
|
|
6859
|
-
children: /* @__PURE__ */
|
|
6860
|
-
/* @__PURE__ */
|
|
6861
|
-
|
|
7196
|
+
children: /* @__PURE__ */ jsxs34(View43, { style: { flex: 1, backgroundColor: theme.colors.backdrop, justifyContent: "center", padding: theme.spacing.lg }, children: [
|
|
7197
|
+
/* @__PURE__ */ jsx56(
|
|
7198
|
+
Pressable16,
|
|
6862
7199
|
{
|
|
6863
7200
|
accessibilityRole: "button",
|
|
6864
7201
|
onPress: dismissOnBackdropPress ? onRequestClose : void 0,
|
|
6865
7202
|
style: { position: "absolute", inset: 0 }
|
|
6866
7203
|
}
|
|
6867
7204
|
),
|
|
6868
|
-
/* @__PURE__ */
|
|
7205
|
+
/* @__PURE__ */ jsx56(Card, { variant: "surfaceRaised", padded: true, style: [{ borderRadius: theme.radii.xl }, contentStyle], children })
|
|
6869
7206
|
] })
|
|
6870
7207
|
}
|
|
6871
7208
|
);
|
|
6872
7209
|
}
|
|
6873
7210
|
|
|
6874
7211
|
// src/components/dialogs/ConfirmMergeRequestDialog.tsx
|
|
6875
|
-
import { jsx as
|
|
7212
|
+
import { jsx as jsx57, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
6876
7213
|
function ConfirmMergeRequestDialog({
|
|
6877
7214
|
visible,
|
|
6878
7215
|
onOpenChange,
|
|
@@ -6902,7 +7239,7 @@ function ConfirmMergeRequestDialog({
|
|
|
6902
7239
|
justifyContent: "center",
|
|
6903
7240
|
alignSelf: "stretch"
|
|
6904
7241
|
};
|
|
6905
|
-
return /* @__PURE__ */
|
|
7242
|
+
return /* @__PURE__ */ jsxs35(
|
|
6906
7243
|
Modal,
|
|
6907
7244
|
{
|
|
6908
7245
|
visible,
|
|
@@ -6913,7 +7250,7 @@ function ConfirmMergeRequestDialog({
|
|
|
6913
7250
|
backgroundColor: theme.colors.background
|
|
6914
7251
|
},
|
|
6915
7252
|
children: [
|
|
6916
|
-
/* @__PURE__ */
|
|
7253
|
+
/* @__PURE__ */ jsx57(View44, { children: /* @__PURE__ */ jsx57(
|
|
6917
7254
|
Text,
|
|
6918
7255
|
{
|
|
6919
7256
|
style: {
|
|
@@ -6925,8 +7262,8 @@ function ConfirmMergeRequestDialog({
|
|
|
6925
7262
|
children: "Are you sure you want to approve this merge request?"
|
|
6926
7263
|
}
|
|
6927
7264
|
) }),
|
|
6928
|
-
/* @__PURE__ */
|
|
6929
|
-
/* @__PURE__ */
|
|
7265
|
+
/* @__PURE__ */ jsxs35(View44, { style: { marginTop: 16 }, children: [
|
|
7266
|
+
/* @__PURE__ */ jsx57(
|
|
6930
7267
|
View44,
|
|
6931
7268
|
{
|
|
6932
7269
|
style: [
|
|
@@ -6936,21 +7273,21 @@ function ConfirmMergeRequestDialog({
|
|
|
6936
7273
|
opacity: canConfirm ? 1 : 0.5
|
|
6937
7274
|
}
|
|
6938
7275
|
],
|
|
6939
|
-
children: /* @__PURE__ */
|
|
6940
|
-
|
|
7276
|
+
children: /* @__PURE__ */ jsx57(
|
|
7277
|
+
Pressable17,
|
|
6941
7278
|
{
|
|
6942
7279
|
accessibilityRole: "button",
|
|
6943
7280
|
accessibilityLabel: "Approve Merge",
|
|
6944
7281
|
disabled: !canConfirm,
|
|
6945
7282
|
onPress: handleConfirm,
|
|
6946
7283
|
style: [fullWidthButtonBase, { flex: 1 }],
|
|
6947
|
-
children: /* @__PURE__ */
|
|
7284
|
+
children: /* @__PURE__ */ jsx57(Text, { style: { textAlign: "center", color: theme.colors.onPrimary }, children: "Approve Merge" })
|
|
6948
7285
|
}
|
|
6949
7286
|
)
|
|
6950
7287
|
}
|
|
6951
7288
|
),
|
|
6952
|
-
/* @__PURE__ */
|
|
6953
|
-
/* @__PURE__ */
|
|
7289
|
+
/* @__PURE__ */ jsx57(View44, { style: { height: 8 } }),
|
|
7290
|
+
/* @__PURE__ */ jsx57(
|
|
6954
7291
|
View44,
|
|
6955
7292
|
{
|
|
6956
7293
|
style: [
|
|
@@ -6962,21 +7299,21 @@ function ConfirmMergeRequestDialog({
|
|
|
6962
7299
|
opacity: isBuilding || !mergeRequest ? 0.5 : 1
|
|
6963
7300
|
}
|
|
6964
7301
|
],
|
|
6965
|
-
children: /* @__PURE__ */
|
|
6966
|
-
|
|
7302
|
+
children: /* @__PURE__ */ jsx57(
|
|
7303
|
+
Pressable17,
|
|
6967
7304
|
{
|
|
6968
7305
|
accessibilityRole: "button",
|
|
6969
7306
|
accessibilityLabel: isBuilding ? "Preparing\u2026" : "Test edits first",
|
|
6970
7307
|
disabled: isBuilding || !mergeRequest,
|
|
6971
7308
|
onPress: handleTestFirst,
|
|
6972
7309
|
style: [fullWidthButtonBase, { flex: 1 }],
|
|
6973
|
-
children: /* @__PURE__ */
|
|
7310
|
+
children: /* @__PURE__ */ jsx57(Text, { style: { textAlign: "center", color: theme.colors.text }, children: isBuilding ? "Preparing\u2026" : "Test edits first" })
|
|
6974
7311
|
}
|
|
6975
7312
|
)
|
|
6976
7313
|
}
|
|
6977
7314
|
),
|
|
6978
|
-
/* @__PURE__ */
|
|
6979
|
-
/* @__PURE__ */
|
|
7315
|
+
/* @__PURE__ */ jsx57(View44, { style: { height: 8 } }),
|
|
7316
|
+
/* @__PURE__ */ jsx57(
|
|
6980
7317
|
View44,
|
|
6981
7318
|
{
|
|
6982
7319
|
style: [
|
|
@@ -6987,14 +7324,14 @@ function ConfirmMergeRequestDialog({
|
|
|
6987
7324
|
borderColor: theme.colors.border
|
|
6988
7325
|
}
|
|
6989
7326
|
],
|
|
6990
|
-
children: /* @__PURE__ */
|
|
6991
|
-
|
|
7327
|
+
children: /* @__PURE__ */ jsx57(
|
|
7328
|
+
Pressable17,
|
|
6992
7329
|
{
|
|
6993
7330
|
accessibilityRole: "button",
|
|
6994
7331
|
accessibilityLabel: "Cancel",
|
|
6995
7332
|
onPress: close,
|
|
6996
7333
|
style: [fullWidthButtonBase, { flex: 1 }],
|
|
6997
|
-
children: /* @__PURE__ */
|
|
7334
|
+
children: /* @__PURE__ */ jsx57(Text, { style: { textAlign: "center", color: theme.colors.text }, children: "Cancel" })
|
|
6998
7335
|
}
|
|
6999
7336
|
)
|
|
7000
7337
|
}
|
|
@@ -7006,7 +7343,7 @@ function ConfirmMergeRequestDialog({
|
|
|
7006
7343
|
}
|
|
7007
7344
|
|
|
7008
7345
|
// src/studio/ui/ConfirmMergeFlow.tsx
|
|
7009
|
-
import { jsx as
|
|
7346
|
+
import { jsx as jsx58 } from "react/jsx-runtime";
|
|
7010
7347
|
function ConfirmMergeFlow({
|
|
7011
7348
|
visible,
|
|
7012
7349
|
onOpenChange,
|
|
@@ -7017,7 +7354,7 @@ function ConfirmMergeFlow({
|
|
|
7017
7354
|
onConfirm,
|
|
7018
7355
|
onTestFirst
|
|
7019
7356
|
}) {
|
|
7020
|
-
return /* @__PURE__ */
|
|
7357
|
+
return /* @__PURE__ */ jsx58(
|
|
7021
7358
|
ConfirmMergeRequestDialog,
|
|
7022
7359
|
{
|
|
7023
7360
|
visible,
|
|
@@ -7115,14 +7452,56 @@ function useOptimisticChatMessages({
|
|
|
7115
7452
|
const createdAtIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
7116
7453
|
const baseServerLastId = chatMessages.length > 0 ? chatMessages[chatMessages.length - 1].id : null;
|
|
7117
7454
|
const id = makeOptimisticId();
|
|
7118
|
-
|
|
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
|
+
]);
|
|
7119
7468
|
void Promise.resolve(onSendChat(text, attachments)).catch(() => {
|
|
7120
7469
|
setOptimisticChat((prev) => prev.map((m) => m.id === id ? { ...m, failed: true } : m));
|
|
7121
7470
|
});
|
|
7122
7471
|
},
|
|
7123
7472
|
[chatMessages, disableOptimistic, onSendChat, shouldForkOnEdit]
|
|
7124
7473
|
);
|
|
7125
|
-
|
|
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 };
|
|
7126
7505
|
}
|
|
7127
7506
|
|
|
7128
7507
|
// src/studio/ui/StudioOverlay.tsx
|
|
@@ -7130,7 +7509,7 @@ import {
|
|
|
7130
7509
|
publishComergeStudioUIState,
|
|
7131
7510
|
startStudioControlPolling
|
|
7132
7511
|
} from "@comergehq/studio-control";
|
|
7133
|
-
import { Fragment as Fragment6, jsx as
|
|
7512
|
+
import { Fragment as Fragment6, jsx as jsx59, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
7134
7513
|
function StudioOverlay({
|
|
7135
7514
|
captureTargetRef,
|
|
7136
7515
|
app,
|
|
@@ -7138,6 +7517,7 @@ function StudioOverlay({
|
|
|
7138
7517
|
isOwner,
|
|
7139
7518
|
shouldForkOnEdit,
|
|
7140
7519
|
isTesting,
|
|
7520
|
+
isBaseBundleDownloading = false,
|
|
7141
7521
|
onRestoreBase,
|
|
7142
7522
|
incomingMergeRequests,
|
|
7143
7523
|
outgoingMergeRequests,
|
|
@@ -7193,7 +7573,7 @@ function StudioOverlay({
|
|
|
7193
7573
|
);
|
|
7194
7574
|
const handleSheetOpenChange = React44.useCallback((open) => {
|
|
7195
7575
|
setSheetOpen(open);
|
|
7196
|
-
if (!open)
|
|
7576
|
+
if (!open) Keyboard4.dismiss();
|
|
7197
7577
|
}, []);
|
|
7198
7578
|
const closeSheet = React44.useCallback(() => {
|
|
7199
7579
|
handleSheetOpenChange(false);
|
|
@@ -7204,8 +7584,8 @@ function StudioOverlay({
|
|
|
7204
7584
|
openSheet();
|
|
7205
7585
|
}, [openSheet]);
|
|
7206
7586
|
const backToPreview = React44.useCallback(() => {
|
|
7207
|
-
if (
|
|
7208
|
-
|
|
7587
|
+
if (Platform10.OS !== "ios") {
|
|
7588
|
+
Keyboard4.dismiss();
|
|
7209
7589
|
setActivePage("preview");
|
|
7210
7590
|
return;
|
|
7211
7591
|
}
|
|
@@ -7217,9 +7597,9 @@ function StudioOverlay({
|
|
|
7217
7597
|
clearTimeout(t);
|
|
7218
7598
|
setActivePage("preview");
|
|
7219
7599
|
};
|
|
7220
|
-
const sub =
|
|
7600
|
+
const sub = Keyboard4.addListener("keyboardDidHide", finalize);
|
|
7221
7601
|
const t = setTimeout(finalize, 350);
|
|
7222
|
-
|
|
7602
|
+
Keyboard4.dismiss();
|
|
7223
7603
|
}, []);
|
|
7224
7604
|
const startDraw = React44.useCallback(() => {
|
|
7225
7605
|
setDrawing(true);
|
|
@@ -7268,14 +7648,14 @@ function StudioOverlay({
|
|
|
7268
7648
|
React44.useEffect(() => {
|
|
7269
7649
|
void publishComergeStudioUIState(sheetOpen, studioControlOptions);
|
|
7270
7650
|
}, [sheetOpen, studioControlOptions]);
|
|
7271
|
-
return /* @__PURE__ */
|
|
7272
|
-
/* @__PURE__ */
|
|
7273
|
-
/* @__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(
|
|
7274
7654
|
StudioSheetPager,
|
|
7275
7655
|
{
|
|
7276
7656
|
activePage,
|
|
7277
7657
|
width,
|
|
7278
|
-
preview: /* @__PURE__ */
|
|
7658
|
+
preview: /* @__PURE__ */ jsx59(
|
|
7279
7659
|
PreviewPanel,
|
|
7280
7660
|
{
|
|
7281
7661
|
app,
|
|
@@ -7304,7 +7684,7 @@ function StudioOverlay({
|
|
|
7304
7684
|
commentCountOverride: commentsCount ?? void 0
|
|
7305
7685
|
}
|
|
7306
7686
|
),
|
|
7307
|
-
chat: /* @__PURE__ */
|
|
7687
|
+
chat: /* @__PURE__ */ jsx59(
|
|
7308
7688
|
ChatPanel,
|
|
7309
7689
|
{
|
|
7310
7690
|
messages: optimistic.messages,
|
|
@@ -7313,7 +7693,6 @@ function StudioOverlay({
|
|
|
7313
7693
|
sendDisabled: chatSendDisabled,
|
|
7314
7694
|
forking: chatForking,
|
|
7315
7695
|
sending: chatSending,
|
|
7316
|
-
autoFocusComposer: sheetOpen && activePage === "chat",
|
|
7317
7696
|
shouldForkOnEdit,
|
|
7318
7697
|
attachments: chatAttachments,
|
|
7319
7698
|
onRemoveAttachment: (idx) => setChatAttachments((prev) => prev.filter((_, i) => i !== idx)),
|
|
@@ -7323,24 +7702,27 @@ function StudioOverlay({
|
|
|
7323
7702
|
onNavigateHome,
|
|
7324
7703
|
onStartDraw: startDraw,
|
|
7325
7704
|
onSend: optimistic.onSend,
|
|
7705
|
+
onRetryMessage: optimistic.onRetry,
|
|
7706
|
+
isRetryingMessage: optimistic.isRetrying,
|
|
7326
7707
|
queueItems: queueItemsForChat,
|
|
7327
7708
|
onRemoveQueueItem
|
|
7328
7709
|
}
|
|
7329
7710
|
)
|
|
7330
7711
|
}
|
|
7331
7712
|
) }),
|
|
7332
|
-
showBubble && /* @__PURE__ */
|
|
7713
|
+
showBubble && /* @__PURE__ */ jsx59(
|
|
7333
7714
|
Bubble,
|
|
7334
7715
|
{
|
|
7335
7716
|
visible: !sheetOpen && !drawing,
|
|
7336
7717
|
ariaLabel: sheetOpen ? "Hide studio" : "Show studio",
|
|
7337
7718
|
badgeCount: incomingMergeRequests.length,
|
|
7338
7719
|
onPress: toggleSheet,
|
|
7339
|
-
isLoading: (app == null ? void 0 : app.status) === "editing",
|
|
7340
|
-
|
|
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 }) })
|
|
7341
7723
|
}
|
|
7342
7724
|
),
|
|
7343
|
-
/* @__PURE__ */
|
|
7725
|
+
/* @__PURE__ */ jsx59(
|
|
7344
7726
|
DrawModeOverlay,
|
|
7345
7727
|
{
|
|
7346
7728
|
visible: drawing,
|
|
@@ -7349,7 +7731,7 @@ function StudioOverlay({
|
|
|
7349
7731
|
onCapture: handleDrawCapture
|
|
7350
7732
|
}
|
|
7351
7733
|
),
|
|
7352
|
-
/* @__PURE__ */
|
|
7734
|
+
/* @__PURE__ */ jsx59(
|
|
7353
7735
|
ConfirmMergeFlow,
|
|
7354
7736
|
{
|
|
7355
7737
|
visible: Boolean(confirmMr),
|
|
@@ -7358,11 +7740,12 @@ function StudioOverlay({
|
|
|
7358
7740
|
},
|
|
7359
7741
|
mergeRequest: confirmMr,
|
|
7360
7742
|
toSummary: toMergeRequestSummary,
|
|
7743
|
+
isBuilding: isBuildingMrTest,
|
|
7361
7744
|
onConfirm: (mr) => onApprove == null ? void 0 : onApprove(mr),
|
|
7362
7745
|
onTestFirst: handleTestMr
|
|
7363
7746
|
}
|
|
7364
7747
|
),
|
|
7365
|
-
/* @__PURE__ */
|
|
7748
|
+
/* @__PURE__ */ jsx59(
|
|
7366
7749
|
AppCommentsSheet,
|
|
7367
7750
|
{
|
|
7368
7751
|
appId: commentsAppId,
|
|
@@ -7555,7 +7938,7 @@ function useEditQueueActions(appId) {
|
|
|
7555
7938
|
}
|
|
7556
7939
|
|
|
7557
7940
|
// src/studio/ComergeStudio.tsx
|
|
7558
|
-
import { jsx as
|
|
7941
|
+
import { jsx as jsx60, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
7559
7942
|
function ComergeStudio({
|
|
7560
7943
|
appId,
|
|
7561
7944
|
clientKey: clientKey2,
|
|
@@ -7576,7 +7959,7 @@ function ComergeStudio({
|
|
|
7576
7959
|
setPendingRuntimeTargetAppId(null);
|
|
7577
7960
|
}, [appId]);
|
|
7578
7961
|
const captureTargetRef = React47.useRef(null);
|
|
7579
|
-
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(
|
|
7580
7963
|
ComergeStudioInner,
|
|
7581
7964
|
{
|
|
7582
7965
|
userId,
|
|
@@ -7725,6 +8108,8 @@ function ComergeStudioInner({
|
|
|
7725
8108
|
const [testingMrId, setTestingMrId] = React47.useState(null);
|
|
7726
8109
|
const [syncingUpstream, setSyncingUpstream] = React47.useState(false);
|
|
7727
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;
|
|
7728
8113
|
const chatShowTypingIndicator = React47.useMemo(() => {
|
|
7729
8114
|
var _a;
|
|
7730
8115
|
if (!thread.raw || thread.raw.length === 0) return false;
|
|
@@ -7771,8 +8156,8 @@ function ComergeStudioInner({
|
|
|
7771
8156
|
}
|
|
7772
8157
|
return editQueue.items;
|
|
7773
8158
|
}, [editQueue.items, lastEditQueueInfo, suppressQueueUntilResponse]);
|
|
7774
|
-
return /* @__PURE__ */
|
|
7775
|
-
/* @__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(
|
|
7776
8161
|
RuntimeRenderer,
|
|
7777
8162
|
{
|
|
7778
8163
|
appKey,
|
|
@@ -7782,7 +8167,7 @@ function ComergeStudioInner({
|
|
|
7782
8167
|
allowInitialPreparing: !embeddedBaseBundles
|
|
7783
8168
|
}
|
|
7784
8169
|
),
|
|
7785
|
-
/* @__PURE__ */
|
|
8170
|
+
/* @__PURE__ */ jsx60(
|
|
7786
8171
|
StudioOverlay,
|
|
7787
8172
|
{
|
|
7788
8173
|
captureTargetRef,
|
|
@@ -7791,6 +8176,7 @@ function ComergeStudioInner({
|
|
|
7791
8176
|
isOwner: actions.isOwner,
|
|
7792
8177
|
shouldForkOnEdit: actions.shouldForkOnEdit,
|
|
7793
8178
|
isTesting: bundle.isTesting,
|
|
8179
|
+
isBaseBundleDownloading,
|
|
7794
8180
|
onRestoreBase: async () => {
|
|
7795
8181
|
setTestingMrId(null);
|
|
7796
8182
|
await bundle.restoreBase();
|
|
@@ -7799,10 +8185,10 @@ function ComergeStudioInner({
|
|
|
7799
8185
|
outgoingMergeRequests: mergeRequests.lists.outgoing,
|
|
7800
8186
|
creatorStatsById: mergeRequests.creatorStatsById,
|
|
7801
8187
|
processingMrId,
|
|
7802
|
-
isBuildingMrTest:
|
|
8188
|
+
isBuildingMrTest: isMrTestBuildInProgress,
|
|
7803
8189
|
testingMrId,
|
|
7804
8190
|
toMergeRequestSummary: mergeRequests.toSummary,
|
|
7805
|
-
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 () => {
|
|
7806
8192
|
await mergeRequests.actions.openMergeRequest(activeAppId);
|
|
7807
8193
|
} : void 0,
|
|
7808
8194
|
onSyncUpstream: actions.isOwner && (app == null ? void 0 : app.forkedFromAppId) ? handleSyncUpstream : void 0,
|
|
@@ -7827,6 +8213,7 @@ function ComergeStudioInner({
|
|
|
7827
8213
|
}
|
|
7828
8214
|
},
|
|
7829
8215
|
onTestMr: async (mr) => {
|
|
8216
|
+
if (testingMrId === mr.id || bundle.loadingMode === "test") return;
|
|
7830
8217
|
setTestingMrId(mr.id);
|
|
7831
8218
|
await bundle.loadTest({ appId: mr.sourceAppId, commitId: mr.sourceTipCommitId ?? mr.sourceCommitId });
|
|
7832
8219
|
},
|
|
@@ -7848,6 +8235,7 @@ function ComergeStudioInner({
|
|
|
7848
8235
|
}
|
|
7849
8236
|
export {
|
|
7850
8237
|
ComergeStudio,
|
|
8238
|
+
resetRealtimeState,
|
|
7851
8239
|
setSupabaseClient
|
|
7852
8240
|
};
|
|
7853
8241
|
//# sourceMappingURL=index.mjs.map
|