@comergehq/studio 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +642 -427
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +363 -148
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/chat/ChatMessageList.tsx +23 -35
- package/src/components/chat/ChatPage.tsx +26 -30
- package/src/components/studio-sheet/StudioBottomSheet.tsx +4 -19
- package/src/studio/ComergeStudio.tsx +34 -1
- package/src/studio/hooks/useAttachmentUpload.ts +51 -5
- package/src/studio/hooks/useBundleManager.ts +91 -17
- package/src/studio/hooks/useOptimisticChatMessages.ts +128 -0
- package/src/studio/ui/ChatPanel.tsx +1 -0
- package/src/studio/ui/RuntimeRenderer.tsx +7 -2
- package/src/studio/ui/StudioOverlay.tsx +19 -6
package/dist/index.js
CHANGED
|
@@ -36,8 +36,8 @@ __export(index_exports, {
|
|
|
36
36
|
module.exports = __toCommonJS(index_exports);
|
|
37
37
|
|
|
38
38
|
// src/studio/ComergeStudio.tsx
|
|
39
|
-
var
|
|
40
|
-
var
|
|
39
|
+
var React40 = __toESM(require("react"));
|
|
40
|
+
var import_react_native54 = require("react-native");
|
|
41
41
|
var import_bottom_sheet6 = require("@gorhom/bottom-sheet");
|
|
42
42
|
|
|
43
43
|
// src/studio/bootstrap/StudioBootstrap.tsx
|
|
@@ -982,6 +982,39 @@ var BundlesRepositoryImpl = class extends BaseRepository {
|
|
|
982
982
|
var bundlesRepository = new BundlesRepositoryImpl(bundlesRemoteDataSource);
|
|
983
983
|
|
|
984
984
|
// src/studio/hooks/useBundleManager.ts
|
|
985
|
+
function sleep(ms) {
|
|
986
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
987
|
+
}
|
|
988
|
+
function isRetryableNetworkError(e) {
|
|
989
|
+
var _a;
|
|
990
|
+
const err = e;
|
|
991
|
+
const code = typeof (err == null ? void 0 : err.code) === "string" ? err.code : "";
|
|
992
|
+
const message = typeof (err == null ? void 0 : err.message) === "string" ? err.message : "";
|
|
993
|
+
if (code === "ERR_NETWORK" || code === "ECONNABORTED") return true;
|
|
994
|
+
if (message.toLowerCase().includes("network error")) return true;
|
|
995
|
+
if (message.toLowerCase().includes("timeout")) return true;
|
|
996
|
+
const status = typeof ((_a = err == null ? void 0 : err.response) == null ? void 0 : _a.status) === "number" ? err.response.status : void 0;
|
|
997
|
+
if (status && (status === 429 || status >= 500)) return true;
|
|
998
|
+
return false;
|
|
999
|
+
}
|
|
1000
|
+
async function withRetry(fn, opts) {
|
|
1001
|
+
let lastErr = null;
|
|
1002
|
+
for (let attempt = 1; attempt <= opts.attempts; attempt += 1) {
|
|
1003
|
+
try {
|
|
1004
|
+
return await fn();
|
|
1005
|
+
} catch (e) {
|
|
1006
|
+
lastErr = e;
|
|
1007
|
+
const retryable = isRetryableNetworkError(e);
|
|
1008
|
+
if (!retryable || attempt >= opts.attempts) {
|
|
1009
|
+
throw e;
|
|
1010
|
+
}
|
|
1011
|
+
const exp = Math.min(opts.maxDelayMs, opts.baseDelayMs * Math.pow(2, attempt - 1));
|
|
1012
|
+
const jitter = Math.floor(Math.random() * 250);
|
|
1013
|
+
await sleep(exp + jitter);
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
throw lastErr;
|
|
1017
|
+
}
|
|
985
1018
|
function safeName(s) {
|
|
986
1019
|
return s.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
987
1020
|
}
|
|
@@ -1039,8 +1072,16 @@ async function getExistingNonEmptyFileUri(fileUri) {
|
|
|
1039
1072
|
async function downloadIfMissing(url, fileUri) {
|
|
1040
1073
|
const existing = await getExistingNonEmptyFileUri(fileUri);
|
|
1041
1074
|
if (existing) return existing;
|
|
1042
|
-
|
|
1043
|
-
|
|
1075
|
+
return await withRetry(
|
|
1076
|
+
async () => {
|
|
1077
|
+
await deleteFileIfExists(fileUri);
|
|
1078
|
+
const res = await FileSystem.downloadAsync(url, fileUri);
|
|
1079
|
+
const ok = await getExistingNonEmptyFileUri(res.uri);
|
|
1080
|
+
if (!ok) throw new Error("Downloaded bundle is empty.");
|
|
1081
|
+
return res.uri;
|
|
1082
|
+
},
|
|
1083
|
+
{ attempts: 3, baseDelayMs: 500, maxDelayMs: 4e3 }
|
|
1084
|
+
);
|
|
1044
1085
|
}
|
|
1045
1086
|
async function deleteFileIfExists(fileUri) {
|
|
1046
1087
|
try {
|
|
@@ -1054,11 +1095,15 @@ async function deleteFileIfExists(fileUri) {
|
|
|
1054
1095
|
async function safeReplaceFileFromUrl(url, targetUri, tmpKey) {
|
|
1055
1096
|
const tmpUri = toBundleFileUri(`tmp:${tmpKey}:${Date.now()}`);
|
|
1056
1097
|
try {
|
|
1057
|
-
await
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1098
|
+
await withRetry(
|
|
1099
|
+
async () => {
|
|
1100
|
+
await deleteFileIfExists(tmpUri);
|
|
1101
|
+
await FileSystem.downloadAsync(url, tmpUri);
|
|
1102
|
+
const tmpOk = await getExistingNonEmptyFileUri(tmpUri);
|
|
1103
|
+
if (!tmpOk) throw new Error("Downloaded bundle is empty.");
|
|
1104
|
+
},
|
|
1105
|
+
{ attempts: 3, baseDelayMs: 500, maxDelayMs: 4e3 }
|
|
1106
|
+
);
|
|
1062
1107
|
await deleteFileIfExists(targetUri);
|
|
1063
1108
|
await FileSystem.moveAsync({ from: tmpUri, to: targetUri });
|
|
1064
1109
|
const finalOk = await getExistingNonEmptyFileUri(targetUri);
|
|
@@ -1071,28 +1116,44 @@ async function safeReplaceFileFromUrl(url, targetUri, tmpKey) {
|
|
|
1071
1116
|
async function pollBundle(appId, bundleId, opts) {
|
|
1072
1117
|
const start = Date.now();
|
|
1073
1118
|
while (true) {
|
|
1074
|
-
|
|
1075
|
-
|
|
1119
|
+
try {
|
|
1120
|
+
const bundle = await bundlesRepository.getById(appId, bundleId);
|
|
1121
|
+
if (bundle.status === "succeeded" || bundle.status === "failed") return bundle;
|
|
1122
|
+
} catch (e) {
|
|
1123
|
+
if (!isRetryableNetworkError(e)) {
|
|
1124
|
+
throw e;
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1076
1127
|
if (Date.now() - start > opts.timeoutMs) {
|
|
1077
1128
|
throw new Error("Bundle build timed out.");
|
|
1078
1129
|
}
|
|
1079
|
-
await
|
|
1130
|
+
await sleep(opts.intervalMs);
|
|
1080
1131
|
}
|
|
1081
1132
|
}
|
|
1082
1133
|
async function resolveBundlePath(src, platform, mode) {
|
|
1083
1134
|
const { appId, commitId } = src;
|
|
1084
1135
|
const dir = bundlesCacheDir();
|
|
1085
1136
|
await ensureDir(dir);
|
|
1086
|
-
const initiate = await
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1137
|
+
const initiate = await withRetry(
|
|
1138
|
+
async () => {
|
|
1139
|
+
return await bundlesRepository.initiate(appId, {
|
|
1140
|
+
platform,
|
|
1141
|
+
commitId: commitId ?? void 0,
|
|
1142
|
+
idempotencyKey: `${appId}:${commitId ?? "head"}:${platform}`
|
|
1143
|
+
});
|
|
1144
|
+
},
|
|
1145
|
+
{ attempts: 3, baseDelayMs: 500, maxDelayMs: 4e3 }
|
|
1146
|
+
);
|
|
1091
1147
|
const finalBundle = initiate.status === "succeeded" || initiate.status === "failed" ? initiate : await pollBundle(appId, initiate.id, { timeoutMs: 3 * 60 * 1e3, intervalMs: 1200 });
|
|
1092
1148
|
if (finalBundle.status === "failed") {
|
|
1093
1149
|
throw new Error("Bundle build failed.");
|
|
1094
1150
|
}
|
|
1095
|
-
const signed = await
|
|
1151
|
+
const signed = await withRetry(
|
|
1152
|
+
async () => {
|
|
1153
|
+
return await bundlesRepository.getSignedDownloadUrl(appId, finalBundle.id, { redirect: false });
|
|
1154
|
+
},
|
|
1155
|
+
{ attempts: 3, baseDelayMs: 500, maxDelayMs: 4e3 }
|
|
1156
|
+
);
|
|
1096
1157
|
const bundlePath = mode === "base" ? await safeReplaceFileFromUrl(
|
|
1097
1158
|
signed.url,
|
|
1098
1159
|
toBundleFileUri(baseBundleKey(appId, platform)),
|
|
@@ -1108,6 +1169,7 @@ function useBundleManager({
|
|
|
1108
1169
|
const [bundlePath, setBundlePath] = React5.useState(null);
|
|
1109
1170
|
const [renderToken, setRenderToken] = React5.useState(0);
|
|
1110
1171
|
const [loading, setLoading] = React5.useState(false);
|
|
1172
|
+
const [loadingMode, setLoadingMode] = React5.useState(null);
|
|
1111
1173
|
const [statusLabel, setStatusLabel] = React5.useState(null);
|
|
1112
1174
|
const [error, setError] = React5.useState(null);
|
|
1113
1175
|
const [isTesting, setIsTesting] = React5.useState(false);
|
|
@@ -1123,6 +1185,7 @@ function useBundleManager({
|
|
|
1123
1185
|
baseOpIdRef.current += 1;
|
|
1124
1186
|
if (activeLoadModeRef.current === "base") {
|
|
1125
1187
|
setLoading(false);
|
|
1188
|
+
setLoadingMode(null);
|
|
1126
1189
|
setStatusLabel(null);
|
|
1127
1190
|
activeLoadModeRef.current = null;
|
|
1128
1191
|
}
|
|
@@ -1187,6 +1250,7 @@ function useBundleManager({
|
|
|
1187
1250
|
const opId = mode === "base" ? ++baseOpIdRef.current : ++testOpIdRef.current;
|
|
1188
1251
|
activeLoadModeRef.current = mode;
|
|
1189
1252
|
setLoading(true);
|
|
1253
|
+
setLoadingMode(mode);
|
|
1190
1254
|
setError(null);
|
|
1191
1255
|
setStatusLabel(mode === "test" ? "Loading test bundle\u2026" : "Loading latest build\u2026");
|
|
1192
1256
|
if (mode === "base") {
|
|
@@ -1229,6 +1293,7 @@ function useBundleManager({
|
|
|
1229
1293
|
if (mode === "base" && opId !== baseOpIdRef.current) return;
|
|
1230
1294
|
if (mode === "test" && opId !== testOpIdRef.current) return;
|
|
1231
1295
|
setLoading(false);
|
|
1296
|
+
setLoadingMode(null);
|
|
1232
1297
|
if (activeLoadModeRef.current === mode) activeLoadModeRef.current = null;
|
|
1233
1298
|
}
|
|
1234
1299
|
}, [activateCachedBase, platform]);
|
|
@@ -1250,7 +1315,7 @@ function useBundleManager({
|
|
|
1250
1315
|
if (!canRequestLatest) return;
|
|
1251
1316
|
void loadBase();
|
|
1252
1317
|
}, [base.appId, base.commitId, platform, canRequestLatest, loadBase]);
|
|
1253
|
-
return { bundlePath, renderToken, loading, statusLabel, error, isTesting, loadBase, loadTest, restoreBase };
|
|
1318
|
+
return { bundlePath, renderToken, loading, loadingMode, statusLabel, error, isTesting, loadBase, loadTest, restoreBase };
|
|
1254
1319
|
}
|
|
1255
1320
|
|
|
1256
1321
|
// src/studio/hooks/useMergeRequests.ts
|
|
@@ -1509,6 +1574,8 @@ function useMergeRequests(params) {
|
|
|
1509
1574
|
|
|
1510
1575
|
// src/studio/hooks/useAttachmentUpload.ts
|
|
1511
1576
|
var React7 = __toESM(require("react"));
|
|
1577
|
+
var import_react_native5 = require("react-native");
|
|
1578
|
+
var FileSystem2 = __toESM(require("expo-file-system/legacy"));
|
|
1512
1579
|
|
|
1513
1580
|
// src/data/attachment/remote.ts
|
|
1514
1581
|
var AttachmentRemoteDataSourceImpl = class extends BaseRemote {
|
|
@@ -1548,6 +1615,40 @@ var attachmentRepository = new AttachmentRepositoryImpl(
|
|
|
1548
1615
|
);
|
|
1549
1616
|
|
|
1550
1617
|
// src/studio/hooks/useAttachmentUpload.ts
|
|
1618
|
+
async function dataUrlToBlobAndroid(dataUrl) {
|
|
1619
|
+
const normalized = dataUrl.startsWith("data:") ? dataUrl : `data:image/png;base64,${dataUrl}`;
|
|
1620
|
+
const comma = normalized.indexOf(",");
|
|
1621
|
+
if (comma === -1) {
|
|
1622
|
+
throw new Error("Invalid data URL (missing comma separator)");
|
|
1623
|
+
}
|
|
1624
|
+
const header = normalized.slice(0, comma);
|
|
1625
|
+
const base64 = normalized.slice(comma + 1);
|
|
1626
|
+
const mimeMatch = header.match(/data:(.*?);base64/i);
|
|
1627
|
+
const mimeType = (mimeMatch == null ? void 0 : mimeMatch[1]) ?? "application/octet-stream";
|
|
1628
|
+
const cacheDir = FileSystem2.cacheDirectory;
|
|
1629
|
+
if (!cacheDir) {
|
|
1630
|
+
throw new Error("expo-file-system cacheDirectory is unavailable");
|
|
1631
|
+
}
|
|
1632
|
+
const fileUri = `${cacheDir}attachment-${Date.now()}-${Math.random().toString(16).slice(2)}.bin`;
|
|
1633
|
+
await FileSystem2.writeAsStringAsync(fileUri, base64, {
|
|
1634
|
+
encoding: FileSystem2.EncodingType.Base64
|
|
1635
|
+
});
|
|
1636
|
+
try {
|
|
1637
|
+
const resp = await fetch(fileUri);
|
|
1638
|
+
const blob = await resp.blob();
|
|
1639
|
+
return blob.type ? blob : new Blob([blob], { type: mimeType });
|
|
1640
|
+
} finally {
|
|
1641
|
+
void FileSystem2.deleteAsync(fileUri, { idempotent: true }).catch(() => {
|
|
1642
|
+
});
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
function getMimeTypeFromDataUrl(dataUrl) {
|
|
1646
|
+
const normalized = dataUrl.startsWith("data:") ? dataUrl : `data:image/png;base64,${dataUrl}`;
|
|
1647
|
+
const comma = normalized.indexOf(",");
|
|
1648
|
+
const header = comma === -1 ? normalized : normalized.slice(0, comma);
|
|
1649
|
+
const mimeMatch = header.match(/data:(.*?);base64/i);
|
|
1650
|
+
return (mimeMatch == null ? void 0 : mimeMatch[1]) ?? "image/png";
|
|
1651
|
+
}
|
|
1551
1652
|
function useAttachmentUpload() {
|
|
1552
1653
|
const [uploading, setUploading] = React7.useState(false);
|
|
1553
1654
|
const [error, setError] = React7.useState(null);
|
|
@@ -1560,15 +1661,15 @@ function useAttachmentUpload() {
|
|
|
1560
1661
|
const blobs = await Promise.all(
|
|
1561
1662
|
dataUrls.map(async (dataUrl, idx) => {
|
|
1562
1663
|
const normalized = dataUrl.startsWith("data:") ? dataUrl : `data:image/png;base64,${dataUrl}`;
|
|
1563
|
-
const
|
|
1564
|
-
const
|
|
1565
|
-
return { blob, idx };
|
|
1664
|
+
const blob = import_react_native5.Platform.OS === "android" ? await dataUrlToBlobAndroid(normalized) : await (await fetch(normalized)).blob();
|
|
1665
|
+
const mimeType = getMimeTypeFromDataUrl(normalized);
|
|
1666
|
+
return { blob, idx, mimeType };
|
|
1566
1667
|
})
|
|
1567
1668
|
);
|
|
1568
|
-
const files = blobs.map(({ blob }, idx) => ({
|
|
1669
|
+
const files = blobs.map(({ blob, mimeType }, idx) => ({
|
|
1569
1670
|
name: `attachment-${Date.now()}-${idx}.png`,
|
|
1570
1671
|
size: blob.size,
|
|
1571
|
-
mimeType
|
|
1672
|
+
mimeType
|
|
1572
1673
|
}));
|
|
1573
1674
|
const presign = await attachmentRepository.presign({ threadId, appId, files });
|
|
1574
1675
|
await Promise.all(presign.uploads.map((u, index) => attachmentRepository.upload(u, blobs[index].blob)));
|
|
@@ -1692,14 +1793,14 @@ function hasNoOutcomeAfterLastHuman(messages) {
|
|
|
1692
1793
|
}
|
|
1693
1794
|
|
|
1694
1795
|
// src/studio/ui/RuntimeRenderer.tsx
|
|
1695
|
-
var
|
|
1796
|
+
var import_react_native6 = require("react-native");
|
|
1696
1797
|
var import_runtime = require("@comergehq/runtime");
|
|
1697
1798
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1698
|
-
function RuntimeRenderer({ appKey, bundlePath, renderToken, style }) {
|
|
1699
|
-
if (!bundlePath) {
|
|
1700
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1799
|
+
function RuntimeRenderer({ appKey, bundlePath, forcePreparing, renderToken, style }) {
|
|
1800
|
+
if (!bundlePath || forcePreparing) {
|
|
1801
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native6.View, { style: [{ flex: 1, justifyContent: "center", alignItems: "center", padding: 24 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { variant: "bodyMuted", children: "Preparing app\u2026" }) });
|
|
1701
1802
|
}
|
|
1702
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1803
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native6.View, { style: [{ flex: 1 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1703
1804
|
import_runtime.ComergeRuntimeRenderer,
|
|
1704
1805
|
{
|
|
1705
1806
|
appKey,
|
|
@@ -1711,17 +1812,17 @@ function RuntimeRenderer({ appKey, bundlePath, renderToken, style }) {
|
|
|
1711
1812
|
}
|
|
1712
1813
|
|
|
1713
1814
|
// src/studio/ui/StudioOverlay.tsx
|
|
1714
|
-
var
|
|
1715
|
-
var
|
|
1815
|
+
var React39 = __toESM(require("react"));
|
|
1816
|
+
var import_react_native53 = require("react-native");
|
|
1716
1817
|
|
|
1717
1818
|
// src/components/studio-sheet/StudioBottomSheet.tsx
|
|
1718
1819
|
var React9 = __toESM(require("react"));
|
|
1719
|
-
var
|
|
1820
|
+
var import_react_native8 = require("react-native");
|
|
1720
1821
|
var import_bottom_sheet = __toESM(require("@gorhom/bottom-sheet"));
|
|
1721
1822
|
var import_react_native_safe_area_context = require("react-native-safe-area-context");
|
|
1722
1823
|
|
|
1723
1824
|
// src/components/studio-sheet/StudioSheetBackground.tsx
|
|
1724
|
-
var
|
|
1825
|
+
var import_react_native7 = require("react-native");
|
|
1725
1826
|
var import_liquid_glass = require("@callstack/liquid-glass");
|
|
1726
1827
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1727
1828
|
function StudioSheetBackground({
|
|
@@ -1729,7 +1830,7 @@ function StudioSheetBackground({
|
|
|
1729
1830
|
renderBackground
|
|
1730
1831
|
}) {
|
|
1731
1832
|
const theme = useTheme();
|
|
1732
|
-
const radius =
|
|
1833
|
+
const radius = import_react_native7.Platform.OS === "ios" ? 39 : 16;
|
|
1733
1834
|
const fallbackBgColor = theme.scheme === "dark" ? "rgba(11, 8, 15, 0.85)" : "rgba(255, 255, 255, 0.85)";
|
|
1734
1835
|
const secondaryBgBaseColor = theme.scheme === "dark" ? "rgb(24, 24, 27)" : "rgb(173, 173, 173)";
|
|
1735
1836
|
const containerStyle = {
|
|
@@ -1750,7 +1851,7 @@ function StudioSheetBackground({
|
|
|
1750
1851
|
}
|
|
1751
1852
|
),
|
|
1752
1853
|
import_liquid_glass.isLiquidGlassSupported && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1753
|
-
|
|
1854
|
+
import_react_native7.View,
|
|
1754
1855
|
{
|
|
1755
1856
|
style: [
|
|
1756
1857
|
containerStyle,
|
|
@@ -1775,7 +1876,7 @@ var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
|
1775
1876
|
function StudioBottomSheet({
|
|
1776
1877
|
open,
|
|
1777
1878
|
onOpenChange,
|
|
1778
|
-
snapPoints = ["
|
|
1879
|
+
snapPoints = ["100%"],
|
|
1779
1880
|
sheetRef,
|
|
1780
1881
|
background,
|
|
1781
1882
|
children,
|
|
@@ -1786,13 +1887,13 @@ function StudioBottomSheet({
|
|
|
1786
1887
|
const internalSheetRef = React9.useRef(null);
|
|
1787
1888
|
const resolvedSheetRef = sheetRef ?? internalSheetRef;
|
|
1788
1889
|
const currentIndexRef = React9.useRef(open ? snapPoints.length - 1 : -1);
|
|
1789
|
-
const lastAppStateRef = React9.useRef(
|
|
1890
|
+
const lastAppStateRef = React9.useRef(import_react_native8.AppState.currentState);
|
|
1790
1891
|
React9.useEffect(() => {
|
|
1791
|
-
const sub =
|
|
1892
|
+
const sub = import_react_native8.AppState.addEventListener("change", (state) => {
|
|
1792
1893
|
const prev = lastAppStateRef.current;
|
|
1793
1894
|
lastAppStateRef.current = state;
|
|
1794
1895
|
if (state === "background" || state === "inactive") {
|
|
1795
|
-
|
|
1896
|
+
import_react_native8.Keyboard.dismiss();
|
|
1796
1897
|
return;
|
|
1797
1898
|
}
|
|
1798
1899
|
if (state !== "active") return;
|
|
@@ -1800,25 +1901,13 @@ function StudioBottomSheet({
|
|
|
1800
1901
|
if (!sheet) return;
|
|
1801
1902
|
const idx = currentIndexRef.current;
|
|
1802
1903
|
if (open && idx >= 0) {
|
|
1803
|
-
|
|
1904
|
+
import_react_native8.Keyboard.dismiss();
|
|
1804
1905
|
requestAnimationFrame(() => sheet.snapToIndex(idx));
|
|
1805
1906
|
setTimeout(() => sheet.snapToIndex(idx), 120);
|
|
1806
1907
|
}
|
|
1807
1908
|
});
|
|
1808
1909
|
return () => sub.remove();
|
|
1809
1910
|
}, [open, resolvedSheetRef]);
|
|
1810
|
-
React9.useEffect(() => {
|
|
1811
|
-
if (import_react_native7.Platform.OS !== "ios") return;
|
|
1812
|
-
const sub = import_react_native7.Keyboard.addListener("keyboardDidHide", () => {
|
|
1813
|
-
const sheet = resolvedSheetRef.current;
|
|
1814
|
-
if (!sheet || !open) return;
|
|
1815
|
-
const targetIndex = snapPoints.length - 1;
|
|
1816
|
-
if (currentIndexRef.current === targetIndex) {
|
|
1817
|
-
setTimeout(() => sheet.snapToIndex(targetIndex), 10);
|
|
1818
|
-
}
|
|
1819
|
-
});
|
|
1820
|
-
return () => sub.remove();
|
|
1821
|
-
}, [open, resolvedSheetRef, snapPoints.length]);
|
|
1822
1911
|
React9.useEffect(() => {
|
|
1823
1912
|
const sheet = resolvedSheetRef.current;
|
|
1824
1913
|
if (!sheet) return;
|
|
@@ -1841,9 +1930,9 @@ function StudioBottomSheet({
|
|
|
1841
1930
|
ref: resolvedSheetRef,
|
|
1842
1931
|
index: open ? snapPoints.length - 1 : -1,
|
|
1843
1932
|
snapPoints,
|
|
1933
|
+
enableDynamicSizing: false,
|
|
1844
1934
|
enablePanDownToClose: true,
|
|
1845
|
-
|
|
1846
|
-
keyboardBlurBehavior: "restore",
|
|
1935
|
+
enableContentPanningGesture: false,
|
|
1847
1936
|
android_keyboardInputMode: "adjustResize",
|
|
1848
1937
|
backgroundComponent: (props) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(StudioSheetBackground, { ...props, renderBackground: background == null ? void 0 : background.renderBackground }),
|
|
1849
1938
|
topInset: insets.top,
|
|
@@ -1851,19 +1940,19 @@ function StudioBottomSheet({
|
|
|
1851
1940
|
handleIndicatorStyle: { backgroundColor: theme.colors.handleIndicator },
|
|
1852
1941
|
onChange: handleChange,
|
|
1853
1942
|
...bottomSheetProps,
|
|
1854
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1943
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native8.View, { style: { flex: 1, overflow: "hidden" }, children })
|
|
1855
1944
|
}
|
|
1856
1945
|
);
|
|
1857
1946
|
}
|
|
1858
1947
|
|
|
1859
1948
|
// src/components/studio-sheet/StudioSheetPager.tsx
|
|
1860
1949
|
var React10 = __toESM(require("react"));
|
|
1861
|
-
var
|
|
1950
|
+
var import_react_native9 = require("react-native");
|
|
1862
1951
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1863
1952
|
function StudioSheetPager({ activePage, width, preview, chat, style }) {
|
|
1864
|
-
const anim = React10.useRef(new
|
|
1953
|
+
const anim = React10.useRef(new import_react_native9.Animated.Value(activePage === "chat" ? 1 : 0)).current;
|
|
1865
1954
|
React10.useEffect(() => {
|
|
1866
|
-
|
|
1955
|
+
import_react_native9.Animated.spring(anim, {
|
|
1867
1956
|
toValue: activePage === "chat" ? 1 : 0,
|
|
1868
1957
|
useNativeDriver: true,
|
|
1869
1958
|
tension: 65,
|
|
@@ -1872,9 +1961,9 @@ function StudioSheetPager({ activePage, width, preview, chat, style }) {
|
|
|
1872
1961
|
}, [activePage, anim]);
|
|
1873
1962
|
const previewTranslateX = anim.interpolate({ inputRange: [0, 1], outputRange: [0, -width] });
|
|
1874
1963
|
const chatTranslateX = anim.interpolate({ inputRange: [0, 1], outputRange: [width, 0] });
|
|
1875
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1964
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react_native9.Animated.View, { style: [{ flex: 1 }, style], children: [
|
|
1876
1965
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1877
|
-
|
|
1966
|
+
import_react_native9.Animated.View,
|
|
1878
1967
|
{
|
|
1879
1968
|
style: [
|
|
1880
1969
|
{
|
|
@@ -1891,7 +1980,7 @@ function StudioSheetPager({ activePage, width, preview, chat, style }) {
|
|
|
1891
1980
|
}
|
|
1892
1981
|
),
|
|
1893
1982
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1894
|
-
|
|
1983
|
+
import_react_native9.Animated.View,
|
|
1895
1984
|
{
|
|
1896
1985
|
style: [
|
|
1897
1986
|
{
|
|
@@ -1912,7 +2001,7 @@ function StudioSheetPager({ activePage, width, preview, chat, style }) {
|
|
|
1912
2001
|
|
|
1913
2002
|
// src/components/floating-draggable-button/FloatingDraggableButton.tsx
|
|
1914
2003
|
var import_react = require("react");
|
|
1915
|
-
var
|
|
2004
|
+
var import_react_native10 = require("react-native");
|
|
1916
2005
|
var Haptics = __toESM(require("expo-haptics"));
|
|
1917
2006
|
var import_react_native_reanimated = __toESM(require("react-native-reanimated"));
|
|
1918
2007
|
var import_liquid_glass2 = require("@callstack/liquid-glass");
|
|
@@ -1971,7 +2060,7 @@ function FloatingDraggableButton({
|
|
|
1971
2060
|
backgroundColor
|
|
1972
2061
|
}) {
|
|
1973
2062
|
const theme = useTheme();
|
|
1974
|
-
const { width, height } = (0,
|
|
2063
|
+
const { width, height } = (0, import_react_native10.useWindowDimensions)();
|
|
1975
2064
|
const isDanger = variant === "danger";
|
|
1976
2065
|
const onPressRef = (0, import_react.useRef)(onPress);
|
|
1977
2066
|
(0, import_react.useEffect)(() => {
|
|
@@ -2074,7 +2163,7 @@ function FloatingDraggableButton({
|
|
|
2074
2163
|
}
|
|
2075
2164
|
}, [forceShowTrigger, visible, animateIn]);
|
|
2076
2165
|
const panResponder = (0, import_react.useRef)(
|
|
2077
|
-
|
|
2166
|
+
import_react_native10.PanResponder.create({
|
|
2078
2167
|
onStartShouldSetPanResponder: () => true,
|
|
2079
2168
|
onMoveShouldSetPanResponder: () => true,
|
|
2080
2169
|
onPanResponderGrant: () => {
|
|
@@ -2137,24 +2226,24 @@ function FloatingDraggableButton({
|
|
|
2137
2226
|
interactive: true,
|
|
2138
2227
|
effect: "clear",
|
|
2139
2228
|
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2140
|
-
|
|
2229
|
+
import_react_native10.Pressable,
|
|
2141
2230
|
{
|
|
2142
2231
|
onPress: () => {
|
|
2143
2232
|
if (!disabled) animateOut();
|
|
2144
2233
|
},
|
|
2145
2234
|
style: styles.buttonInner,
|
|
2146
2235
|
android_ripple: { color: "rgba(255, 255, 255, 0.3)", borderless: true },
|
|
2147
|
-
children: children ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2236
|
+
children: children ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native10.View, {})
|
|
2148
2237
|
}
|
|
2149
2238
|
)
|
|
2150
2239
|
}
|
|
2151
2240
|
) }),
|
|
2152
|
-
badgeCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2241
|
+
badgeCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native10.View, { style: [styles.badge, { backgroundColor: theme.colors.danger }], children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native10.Text, { style: [styles.badgeText, { color: theme.colors.onDanger }], children: badgeCount > 99 ? "99+" : badgeCount }) })
|
|
2153
2242
|
]
|
|
2154
2243
|
}
|
|
2155
2244
|
);
|
|
2156
2245
|
}
|
|
2157
|
-
var styles =
|
|
2246
|
+
var styles = import_react_native10.StyleSheet.create({
|
|
2158
2247
|
floatingButton: {
|
|
2159
2248
|
position: "absolute",
|
|
2160
2249
|
justifyContent: "center",
|
|
@@ -2191,7 +2280,7 @@ var styles = import_react_native9.StyleSheet.create({
|
|
|
2191
2280
|
|
|
2192
2281
|
// src/components/overlays/EdgeGlowFrame.tsx
|
|
2193
2282
|
var React11 = __toESM(require("react"));
|
|
2194
|
-
var
|
|
2283
|
+
var import_react_native11 = require("react-native");
|
|
2195
2284
|
var import_expo_linear_gradient = require("expo-linear-gradient");
|
|
2196
2285
|
|
|
2197
2286
|
// src/components/utils/color.ts
|
|
@@ -2233,9 +2322,9 @@ function EdgeGlowFrame({
|
|
|
2233
2322
|
}) {
|
|
2234
2323
|
const theme = useTheme();
|
|
2235
2324
|
const alpha = Math.max(0, Math.min(1, intensity));
|
|
2236
|
-
const anim = React11.useRef(new
|
|
2325
|
+
const anim = React11.useRef(new import_react_native11.Animated.Value(visible ? 1 : 0)).current;
|
|
2237
2326
|
React11.useEffect(() => {
|
|
2238
|
-
|
|
2327
|
+
import_react_native11.Animated.timing(anim, {
|
|
2239
2328
|
toValue: visible ? 1 : 0,
|
|
2240
2329
|
duration: 300,
|
|
2241
2330
|
useNativeDriver: true
|
|
@@ -2244,8 +2333,8 @@ function EdgeGlowFrame({
|
|
|
2244
2333
|
const c = baseColor(role, theme);
|
|
2245
2334
|
const strong = withAlpha(c, 0.6 * alpha);
|
|
2246
2335
|
const soft = withAlpha(c, 0.22 * alpha);
|
|
2247
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2248
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2336
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native11.Animated.View, { pointerEvents: "none", style: [{ position: "absolute", inset: 0, opacity: anim }, style], children: [
|
|
2337
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native11.View, { style: { position: "absolute", top: 0, left: 0, right: 0, height: thickness }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2249
2338
|
import_expo_linear_gradient.LinearGradient,
|
|
2250
2339
|
{
|
|
2251
2340
|
colors: [strong, soft, "transparent"],
|
|
@@ -2254,7 +2343,7 @@ function EdgeGlowFrame({
|
|
|
2254
2343
|
style: { width: "100%", height: "100%" }
|
|
2255
2344
|
}
|
|
2256
2345
|
) }),
|
|
2257
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2346
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native11.View, { style: { position: "absolute", bottom: 0, left: 0, right: 0, height: thickness }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2258
2347
|
import_expo_linear_gradient.LinearGradient,
|
|
2259
2348
|
{
|
|
2260
2349
|
colors: ["transparent", soft, strong],
|
|
@@ -2263,7 +2352,7 @@ function EdgeGlowFrame({
|
|
|
2263
2352
|
style: { width: "100%", height: "100%" }
|
|
2264
2353
|
}
|
|
2265
2354
|
) }),
|
|
2266
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2355
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native11.View, { style: { position: "absolute", top: 0, bottom: 0, left: 0, width: thickness }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2267
2356
|
import_expo_linear_gradient.LinearGradient,
|
|
2268
2357
|
{
|
|
2269
2358
|
colors: [strong, soft, "transparent"],
|
|
@@ -2272,7 +2361,7 @@ function EdgeGlowFrame({
|
|
|
2272
2361
|
style: { width: "100%", height: "100%" }
|
|
2273
2362
|
}
|
|
2274
2363
|
) }),
|
|
2275
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2364
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native11.View, { style: { position: "absolute", top: 0, bottom: 0, right: 0, width: thickness }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2276
2365
|
import_expo_linear_gradient.LinearGradient,
|
|
2277
2366
|
{
|
|
2278
2367
|
colors: ["transparent", soft, strong],
|
|
@@ -2286,12 +2375,12 @@ function EdgeGlowFrame({
|
|
|
2286
2375
|
|
|
2287
2376
|
// src/components/draw/DrawModeOverlay.tsx
|
|
2288
2377
|
var React14 = __toESM(require("react"));
|
|
2289
|
-
var
|
|
2378
|
+
var import_react_native15 = require("react-native");
|
|
2290
2379
|
var import_react_native_view_shot = require("react-native-view-shot");
|
|
2291
2380
|
|
|
2292
2381
|
// src/components/draw/DrawSurface.tsx
|
|
2293
2382
|
var React12 = __toESM(require("react"));
|
|
2294
|
-
var
|
|
2383
|
+
var import_react_native12 = require("react-native");
|
|
2295
2384
|
var import_react_native_svg = __toESM(require("react-native-svg"));
|
|
2296
2385
|
|
|
2297
2386
|
// src/components/draw/strokes.ts
|
|
@@ -2362,7 +2451,7 @@ function DrawSurface({
|
|
|
2362
2451
|
triggerRender();
|
|
2363
2452
|
}, [color, onAddStroke, strokeWidth, triggerRender]);
|
|
2364
2453
|
const panResponder = React12.useMemo(
|
|
2365
|
-
() =>
|
|
2454
|
+
() => import_react_native12.PanResponder.create({
|
|
2366
2455
|
onStartShouldSetPanResponder: () => true,
|
|
2367
2456
|
onMoveShouldSetPanResponder: () => true,
|
|
2368
2457
|
onPanResponderGrant: onStart,
|
|
@@ -2374,7 +2463,7 @@ function DrawSurface({
|
|
|
2374
2463
|
);
|
|
2375
2464
|
const currentPath = pointsToSmoothPath(currentPointsRef.current);
|
|
2376
2465
|
void renderTick;
|
|
2377
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2466
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native12.View, { style: [import_react_native12.StyleSheet.absoluteFill, styles2.container, style], ...panResponder.panHandlers, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native_svg.default, { style: import_react_native12.StyleSheet.absoluteFill, width: "100%", height: "100%", children: [
|
|
2378
2467
|
strokes.map((s, idx) => {
|
|
2379
2468
|
const d = pointsToSmoothPath(s.points);
|
|
2380
2469
|
if (!d) return null;
|
|
@@ -2404,7 +2493,7 @@ function DrawSurface({
|
|
|
2404
2493
|
) : null
|
|
2405
2494
|
] }) });
|
|
2406
2495
|
}
|
|
2407
|
-
var styles2 =
|
|
2496
|
+
var styles2 = import_react_native12.StyleSheet.create({
|
|
2408
2497
|
container: {
|
|
2409
2498
|
zIndex: 5
|
|
2410
2499
|
}
|
|
@@ -2412,7 +2501,7 @@ var styles2 = import_react_native11.StyleSheet.create({
|
|
|
2412
2501
|
|
|
2413
2502
|
// src/components/draw/DrawToolbar.tsx
|
|
2414
2503
|
var React13 = __toESM(require("react"));
|
|
2415
|
-
var
|
|
2504
|
+
var import_react_native14 = require("react-native");
|
|
2416
2505
|
var import_react_native_safe_area_context2 = require("react-native-safe-area-context");
|
|
2417
2506
|
var import_lucide_react_native = require("lucide-react-native");
|
|
2418
2507
|
|
|
@@ -2431,7 +2520,7 @@ async function impact(style) {
|
|
|
2431
2520
|
}
|
|
2432
2521
|
|
|
2433
2522
|
// src/components/draw/DrawColorPicker.tsx
|
|
2434
|
-
var
|
|
2523
|
+
var import_react_native13 = require("react-native");
|
|
2435
2524
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
2436
2525
|
function DrawColorPicker({
|
|
2437
2526
|
colors,
|
|
@@ -2466,10 +2555,10 @@ function DrawColorPicker({
|
|
|
2466
2555
|
return { ...base, ...selectedStyle, ...whiteStyle };
|
|
2467
2556
|
};
|
|
2468
2557
|
if (!expanded) {
|
|
2469
|
-
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2558
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native13.Pressable, { onPress: onToggle, style: [swatchStyle(selected, true), style] });
|
|
2470
2559
|
}
|
|
2471
|
-
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2472
|
-
|
|
2560
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native13.View, { style: [{ flexDirection: "row", alignItems: "center", gap: 8 }, style], children: colors.map((c, idx) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2561
|
+
import_react_native13.Pressable,
|
|
2473
2562
|
{
|
|
2474
2563
|
onPress: () => {
|
|
2475
2564
|
onSelect(c);
|
|
@@ -2500,14 +2589,14 @@ function DrawToolbar({
|
|
|
2500
2589
|
style
|
|
2501
2590
|
}) {
|
|
2502
2591
|
const insets = (0, import_react_native_safe_area_context2.useSafeAreaInsets)();
|
|
2503
|
-
const { width: screenWidth, height: screenHeight } = (0,
|
|
2592
|
+
const { width: screenWidth, height: screenHeight } = (0, import_react_native14.useWindowDimensions)();
|
|
2504
2593
|
const [expanded, setExpanded] = React13.useState(false);
|
|
2505
|
-
const pos = React13.useRef(new
|
|
2594
|
+
const pos = React13.useRef(new import_react_native14.Animated.ValueXY({ x: screenWidth / 2 - 110, y: -140 })).current;
|
|
2506
2595
|
const start = React13.useRef({ x: 0, y: 0 });
|
|
2507
2596
|
const currentPos = React13.useRef({ x: 0, y: 0 });
|
|
2508
2597
|
React13.useEffect(() => {
|
|
2509
2598
|
if (hidden) return;
|
|
2510
|
-
|
|
2599
|
+
import_react_native14.Animated.spring(pos.y, {
|
|
2511
2600
|
toValue: insets.top + 60,
|
|
2512
2601
|
useNativeDriver: true,
|
|
2513
2602
|
damping: 12,
|
|
@@ -2534,7 +2623,7 @@ function DrawToolbar({
|
|
|
2534
2623
|
[insets.top, screenHeight, screenWidth]
|
|
2535
2624
|
);
|
|
2536
2625
|
const panResponder = React13.useMemo(
|
|
2537
|
-
() =>
|
|
2626
|
+
() => import_react_native14.PanResponder.create({
|
|
2538
2627
|
onStartShouldSetPanResponder: () => false,
|
|
2539
2628
|
onMoveShouldSetPanResponder: (_e, g) => Math.abs(g.dx) > 5 || Math.abs(g.dy) > 5,
|
|
2540
2629
|
onPanResponderGrant: () => {
|
|
@@ -2546,7 +2635,7 @@ function DrawToolbar({
|
|
|
2546
2635
|
},
|
|
2547
2636
|
onPanResponderRelease: () => {
|
|
2548
2637
|
const next = clamp2(currentPos.current.x, currentPos.current.y);
|
|
2549
|
-
|
|
2638
|
+
import_react_native14.Animated.spring(pos, { toValue: next, useNativeDriver: true }).start();
|
|
2550
2639
|
}
|
|
2551
2640
|
}),
|
|
2552
2641
|
[clamp2, pos]
|
|
@@ -2563,7 +2652,7 @@ function DrawToolbar({
|
|
|
2563
2652
|
const isDisabled = Boolean(disabled) || Boolean(capturingDisabled);
|
|
2564
2653
|
const [pressed, setPressed] = React13.useState(false);
|
|
2565
2654
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2566
|
-
|
|
2655
|
+
import_react_native14.View,
|
|
2567
2656
|
{
|
|
2568
2657
|
style: {
|
|
2569
2658
|
width: 28,
|
|
@@ -2575,7 +2664,7 @@ function DrawToolbar({
|
|
|
2575
2664
|
opacity: isDisabled ? 0.5 : pressed ? 0.85 : 1
|
|
2576
2665
|
},
|
|
2577
2666
|
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2578
|
-
|
|
2667
|
+
import_react_native14.Pressable,
|
|
2579
2668
|
{
|
|
2580
2669
|
accessibilityRole: "button",
|
|
2581
2670
|
accessibilityLabel,
|
|
@@ -2592,7 +2681,7 @@ function DrawToolbar({
|
|
|
2592
2681
|
);
|
|
2593
2682
|
}
|
|
2594
2683
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2595
|
-
|
|
2684
|
+
import_react_native14.Animated.View,
|
|
2596
2685
|
{
|
|
2597
2686
|
style: [
|
|
2598
2687
|
{
|
|
@@ -2609,7 +2698,7 @@ function DrawToolbar({
|
|
|
2609
2698
|
],
|
|
2610
2699
|
...panResponder.panHandlers,
|
|
2611
2700
|
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2612
|
-
|
|
2701
|
+
import_react_native14.View,
|
|
2613
2702
|
{
|
|
2614
2703
|
style: {
|
|
2615
2704
|
backgroundColor: "#F43F5E",
|
|
@@ -2617,7 +2706,7 @@ function DrawToolbar({
|
|
|
2617
2706
|
padding: 12,
|
|
2618
2707
|
minWidth: 220
|
|
2619
2708
|
},
|
|
2620
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
2709
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native14.View, { style: { flexDirection: "row", alignItems: "center", gap: 8 }, children: [
|
|
2621
2710
|
renderDragHandle ? renderDragHandle() : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react_native.GripVertical, { size: 20, color: "rgba(255, 255, 255, 0.6)" }),
|
|
2622
2711
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2623
2712
|
DrawColorPicker,
|
|
@@ -2635,7 +2724,7 @@ function DrawToolbar({
|
|
|
2635
2724
|
}
|
|
2636
2725
|
}
|
|
2637
2726
|
),
|
|
2638
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2727
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native14.View, { style: { width: 1, height: 20, backgroundColor: "rgba(255, 255, 255, 0.3)", marginHorizontal: 4 } }),
|
|
2639
2728
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2640
2729
|
CircleActionButton,
|
|
2641
2730
|
{
|
|
@@ -2673,7 +2762,7 @@ function DrawToolbar({
|
|
|
2673
2762
|
void impact("medium");
|
|
2674
2763
|
onDone();
|
|
2675
2764
|
},
|
|
2676
|
-
children: capturing ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2765
|
+
children: capturing ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native14.ActivityIndicator, { color: "#FFFFFF", size: "small" }) : renderDoneIcon ? renderDoneIcon() : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react_native.Check, { size: 16, color: "#FFFFFF" })
|
|
2677
2766
|
}
|
|
2678
2767
|
)
|
|
2679
2768
|
] })
|
|
@@ -2758,7 +2847,7 @@ function DrawModeOverlay({
|
|
|
2758
2847
|
}
|
|
2759
2848
|
}, [captureTargetRef, capturing, onCapture]);
|
|
2760
2849
|
if (!visible) return null;
|
|
2761
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2850
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native15.View, { style: [import_react_native15.StyleSheet.absoluteFill, styles3.root, style], pointerEvents: "box-none", children: [
|
|
2762
2851
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(EdgeGlowFrame, { visible: !hideUi, role: "danger", thickness: 50, intensity: 1 }),
|
|
2763
2852
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2764
2853
|
DrawSurface,
|
|
@@ -2789,7 +2878,7 @@ function DrawModeOverlay({
|
|
|
2789
2878
|
)
|
|
2790
2879
|
] });
|
|
2791
2880
|
}
|
|
2792
|
-
var styles3 =
|
|
2881
|
+
var styles3 = import_react_native15.StyleSheet.create({
|
|
2793
2882
|
root: {
|
|
2794
2883
|
zIndex: 9999
|
|
2795
2884
|
}
|
|
@@ -2797,7 +2886,7 @@ var styles3 = import_react_native14.StyleSheet.create({
|
|
|
2797
2886
|
|
|
2798
2887
|
// src/components/comments/AppCommentsSheet.tsx
|
|
2799
2888
|
var React21 = __toESM(require("react"));
|
|
2800
|
-
var
|
|
2889
|
+
var import_react_native21 = require("react-native");
|
|
2801
2890
|
var import_bottom_sheet3 = require("@gorhom/bottom-sheet");
|
|
2802
2891
|
var import_react_native_safe_area_context3 = require("react-native-safe-area-context");
|
|
2803
2892
|
var import_liquid_glass4 = require("@callstack/liquid-glass");
|
|
@@ -2805,13 +2894,13 @@ var import_lucide_react_native4 = require("lucide-react-native");
|
|
|
2805
2894
|
|
|
2806
2895
|
// src/components/chat/ChatComposer.tsx
|
|
2807
2896
|
var React16 = __toESM(require("react"));
|
|
2808
|
-
var
|
|
2897
|
+
var import_react_native17 = require("react-native");
|
|
2809
2898
|
var import_liquid_glass3 = require("@callstack/liquid-glass");
|
|
2810
2899
|
var import_lucide_react_native3 = require("lucide-react-native");
|
|
2811
2900
|
|
|
2812
2901
|
// src/components/chat/MultilineTextInput.tsx
|
|
2813
2902
|
var React15 = __toESM(require("react"));
|
|
2814
|
-
var
|
|
2903
|
+
var import_react_native16 = require("react-native");
|
|
2815
2904
|
var import_bottom_sheet2 = require("@gorhom/bottom-sheet");
|
|
2816
2905
|
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
2817
2906
|
var MultilineTextInput = React15.forwardRef(function MultilineTextInput2({ useBottomSheetTextInput = false, placeholder, placeholderTextColor, style, ...props }, ref) {
|
|
@@ -2834,7 +2923,7 @@ var MultilineTextInput = React15.forwardRef(function MultilineTextInput2({ useBo
|
|
|
2834
2923
|
style: [baseStyle, style],
|
|
2835
2924
|
textAlignVertical: "top"
|
|
2836
2925
|
};
|
|
2837
|
-
return useBottomSheetTextInput ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_bottom_sheet2.BottomSheetTextInput, { ref, ...commonProps }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2926
|
+
return useBottomSheetTextInput ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_bottom_sheet2.BottomSheetTextInput, { ref, ...commonProps }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native16.TextInput, { ref, ...commonProps });
|
|
2838
2927
|
});
|
|
2839
2928
|
|
|
2840
2929
|
// src/components/icons/StudioIcons.tsx
|
|
@@ -2887,9 +2976,9 @@ function AspectRatioThumbnail({
|
|
|
2887
2976
|
renderRemoveIcon
|
|
2888
2977
|
}) {
|
|
2889
2978
|
const [aspectRatio, setAspectRatio] = React16.useState(1);
|
|
2890
|
-
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
2891
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2892
|
-
|
|
2979
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react_native17.View, { style: { height: THUMBNAIL_HEIGHT, aspectRatio, position: "relative" }, children: [
|
|
2980
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native17.View, { style: { flex: 1, borderRadius: 8, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2981
|
+
import_react_native17.Image,
|
|
2893
2982
|
{
|
|
2894
2983
|
source: { uri },
|
|
2895
2984
|
style: { width: "100%", height: "100%" },
|
|
@@ -2902,7 +2991,7 @@ function AspectRatioThumbnail({
|
|
|
2902
2991
|
}
|
|
2903
2992
|
) }),
|
|
2904
2993
|
onRemove ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2905
|
-
|
|
2994
|
+
import_react_native17.Pressable,
|
|
2906
2995
|
{
|
|
2907
2996
|
style: {
|
|
2908
2997
|
position: "absolute",
|
|
@@ -2950,8 +3039,8 @@ function ChatComposer({
|
|
|
2950
3039
|
const hasText = text.trim().length > 0;
|
|
2951
3040
|
const composerMinHeight = hasAttachments ? THUMBNAIL_HEIGHT + 44 + 24 : 44;
|
|
2952
3041
|
const isButtonDisabled = sending || disabled || sendDisabled;
|
|
2953
|
-
const maxInputHeight = React16.useMemo(() =>
|
|
2954
|
-
const shakeAnim = React16.useRef(new
|
|
3042
|
+
const maxInputHeight = React16.useMemo(() => import_react_native17.Dimensions.get("window").height * 0.5, []);
|
|
3043
|
+
const shakeAnim = React16.useRef(new import_react_native17.Animated.Value(0)).current;
|
|
2955
3044
|
const [sendPressed, setSendPressed] = React16.useState(false);
|
|
2956
3045
|
const inputRef = React16.useRef(null);
|
|
2957
3046
|
const prevAutoFocusRef = React16.useRef(false);
|
|
@@ -2967,12 +3056,12 @@ function ChatComposer({
|
|
|
2967
3056
|
}, [autoFocus, disabled, sending]);
|
|
2968
3057
|
const triggerShake = React16.useCallback(() => {
|
|
2969
3058
|
shakeAnim.setValue(0);
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
3059
|
+
import_react_native17.Animated.sequence([
|
|
3060
|
+
import_react_native17.Animated.timing(shakeAnim, { toValue: 10, duration: 50, useNativeDriver: true }),
|
|
3061
|
+
import_react_native17.Animated.timing(shakeAnim, { toValue: -10, duration: 50, useNativeDriver: true }),
|
|
3062
|
+
import_react_native17.Animated.timing(shakeAnim, { toValue: 10, duration: 50, useNativeDriver: true }),
|
|
3063
|
+
import_react_native17.Animated.timing(shakeAnim, { toValue: -10, duration: 50, useNativeDriver: true }),
|
|
3064
|
+
import_react_native17.Animated.timing(shakeAnim, { toValue: 0, duration: 50, useNativeDriver: true })
|
|
2976
3065
|
]).start();
|
|
2977
3066
|
}, [shakeAnim]);
|
|
2978
3067
|
const handleSend = React16.useCallback(async () => {
|
|
@@ -2988,12 +3077,12 @@ function ChatComposer({
|
|
|
2988
3077
|
const textareaBgColor = theme.scheme === "dark" ? "#18181B" : "#F6F6F6";
|
|
2989
3078
|
const placeholderTextColor = theme.scheme === "dark" ? "#A1A1AA" : "#71717A";
|
|
2990
3079
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2991
|
-
|
|
3080
|
+
import_react_native17.View,
|
|
2992
3081
|
{
|
|
2993
3082
|
style: [{ paddingHorizontal: 16, paddingBottom: 12, paddingTop: 8 }, style],
|
|
2994
3083
|
onLayout: (e) => onLayout == null ? void 0 : onLayout({ height: e.nativeEvent.layout.height }),
|
|
2995
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
2996
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3084
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react_native17.View, { style: { flexDirection: "row", alignItems: "flex-end", gap: 8 }, children: [
|
|
3085
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native17.Animated.View, { style: { flex: 1, transform: [{ translateX: shakeAnim }] }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
2997
3086
|
import_liquid_glass3.LiquidGlassView,
|
|
2998
3087
|
{
|
|
2999
3088
|
style: [
|
|
@@ -3006,7 +3095,7 @@ function ChatComposer({
|
|
|
3006
3095
|
effect: "clear",
|
|
3007
3096
|
children: [
|
|
3008
3097
|
hasAttachments ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
3009
|
-
|
|
3098
|
+
import_react_native17.ScrollView,
|
|
3010
3099
|
{
|
|
3011
3100
|
horizontal: true,
|
|
3012
3101
|
showsHorizontalScrollIndicator: false,
|
|
@@ -3023,7 +3112,7 @@ function ChatComposer({
|
|
|
3023
3112
|
`attachment-${index}`
|
|
3024
3113
|
)),
|
|
3025
3114
|
onAddAttachment ? renderAddAttachment ? renderAddAttachment() : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3026
|
-
|
|
3115
|
+
import_react_native17.Pressable,
|
|
3027
3116
|
{
|
|
3028
3117
|
style: {
|
|
3029
3118
|
height: THUMBNAIL_HEIGHT,
|
|
@@ -3075,7 +3164,7 @@ function ChatComposer({
|
|
|
3075
3164
|
interactive: true,
|
|
3076
3165
|
effect: "clear",
|
|
3077
3166
|
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3078
|
-
|
|
3167
|
+
import_react_native17.View,
|
|
3079
3168
|
{
|
|
3080
3169
|
style: {
|
|
3081
3170
|
width: 44,
|
|
@@ -3086,7 +3175,7 @@ function ChatComposer({
|
|
|
3086
3175
|
opacity: isButtonDisabled ? 0.6 : sendPressed ? 0.9 : 1
|
|
3087
3176
|
},
|
|
3088
3177
|
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3089
|
-
|
|
3178
|
+
import_react_native17.Pressable,
|
|
3090
3179
|
{
|
|
3091
3180
|
accessibilityRole: "button",
|
|
3092
3181
|
accessibilityLabel: "Send",
|
|
@@ -3095,7 +3184,7 @@ function ChatComposer({
|
|
|
3095
3184
|
onPressIn: () => setSendPressed(true),
|
|
3096
3185
|
onPressOut: () => setSendPressed(false),
|
|
3097
3186
|
style: { flex: 1, alignItems: "center", justifyContent: "center" },
|
|
3098
|
-
children: sending ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3187
|
+
children: sending ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native17.ActivityIndicator, {}) : renderSendIcon ? renderSendIcon() : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(IconChevronRight, { size: 20, colorToken: "onPrimary" })
|
|
3099
3188
|
}
|
|
3100
3189
|
)
|
|
3101
3190
|
}
|
|
@@ -3109,10 +3198,10 @@ function ChatComposer({
|
|
|
3109
3198
|
|
|
3110
3199
|
// src/components/comments/CommentRow.tsx
|
|
3111
3200
|
var React17 = __toESM(require("react"));
|
|
3112
|
-
var
|
|
3201
|
+
var import_react_native19 = require("react-native");
|
|
3113
3202
|
|
|
3114
3203
|
// src/components/primitives/Avatar.tsx
|
|
3115
|
-
var
|
|
3204
|
+
var import_react_native18 = require("react-native");
|
|
3116
3205
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
3117
3206
|
function initialsFrom(name) {
|
|
3118
3207
|
var _a, _b;
|
|
@@ -3132,7 +3221,7 @@ function Avatar({
|
|
|
3132
3221
|
const radius = size / 2;
|
|
3133
3222
|
const fallbackBg = fallbackBackgroundColor ?? theme.colors.neutral;
|
|
3134
3223
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3135
|
-
|
|
3224
|
+
import_react_native18.View,
|
|
3136
3225
|
{
|
|
3137
3226
|
style: [
|
|
3138
3227
|
{
|
|
@@ -3147,7 +3236,7 @@ function Avatar({
|
|
|
3147
3236
|
style
|
|
3148
3237
|
],
|
|
3149
3238
|
children: uri ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3150
|
-
|
|
3239
|
+
import_react_native18.Image,
|
|
3151
3240
|
{
|
|
3152
3241
|
source: { uri },
|
|
3153
3242
|
style: [{ width: size, height: size }, imageStyle],
|
|
@@ -3198,7 +3287,7 @@ function CommentRow({ comment, showDivider }) {
|
|
|
3198
3287
|
};
|
|
3199
3288
|
}, [comment.authorId]);
|
|
3200
3289
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
3201
|
-
|
|
3290
|
+
import_react_native19.View,
|
|
3202
3291
|
{
|
|
3203
3292
|
style: {
|
|
3204
3293
|
flexDirection: "row",
|
|
@@ -3209,8 +3298,8 @@ function CommentRow({ comment, showDivider }) {
|
|
|
3209
3298
|
},
|
|
3210
3299
|
children: [
|
|
3211
3300
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Avatar, { size: 32, uri: authorAvatar, name: authorName ?? comment.authorId, style: { marginTop: 6 } }),
|
|
3212
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
3213
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
3301
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_react_native19.View, { style: { flex: 1, minWidth: 0, gap: 4 }, children: [
|
|
3302
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_react_native19.View, { style: { flexDirection: "row", alignItems: "center", gap: theme.spacing.sm }, children: [
|
|
3214
3303
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { style: { fontSize: 14, lineHeight: 18, fontWeight: theme.typography.fontWeight.bold, color: theme.colors.text }, children: authorName ?? "Unknown User" }),
|
|
3215
3304
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { style: { fontSize: 12, lineHeight: 16, color: theme.colors.textMuted }, children: formatTimeAgo(comment.createdAt) })
|
|
3216
3305
|
] }),
|
|
@@ -3378,13 +3467,13 @@ function useAppDetails(appId) {
|
|
|
3378
3467
|
|
|
3379
3468
|
// src/components/comments/useIosKeyboardSnapFix.ts
|
|
3380
3469
|
var React20 = __toESM(require("react"));
|
|
3381
|
-
var
|
|
3470
|
+
var import_react_native20 = require("react-native");
|
|
3382
3471
|
function useIosKeyboardSnapFix(sheetRef, options) {
|
|
3383
3472
|
const [keyboardVisible, setKeyboardVisible] = React20.useState(false);
|
|
3384
3473
|
React20.useEffect(() => {
|
|
3385
|
-
if (
|
|
3386
|
-
const show =
|
|
3387
|
-
const hide =
|
|
3474
|
+
if (import_react_native20.Platform.OS !== "ios") return;
|
|
3475
|
+
const show = import_react_native20.Keyboard.addListener("keyboardWillShow", () => setKeyboardVisible(true));
|
|
3476
|
+
const hide = import_react_native20.Keyboard.addListener("keyboardWillHide", () => {
|
|
3388
3477
|
var _a;
|
|
3389
3478
|
setKeyboardVisible(false);
|
|
3390
3479
|
const target = (options == null ? void 0 : options.targetIndex) ?? 1;
|
|
@@ -3460,17 +3549,17 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
3460
3549
|
onChange: handleChange,
|
|
3461
3550
|
backgroundStyle: {
|
|
3462
3551
|
backgroundColor: theme.scheme === "dark" ? "#0B080F" : "#FFFFFF",
|
|
3463
|
-
borderTopLeftRadius:
|
|
3464
|
-
borderTopRightRadius:
|
|
3552
|
+
borderTopLeftRadius: import_react_native21.Platform.OS === "ios" ? 39 : 16,
|
|
3553
|
+
borderTopRightRadius: import_react_native21.Platform.OS === "ios" ? 39 : 16
|
|
3465
3554
|
},
|
|
3466
3555
|
handleIndicatorStyle: { backgroundColor: theme.colors.handleIndicator },
|
|
3467
3556
|
keyboardBehavior: "interactive",
|
|
3468
3557
|
keyboardBlurBehavior: "restore",
|
|
3469
3558
|
android_keyboardInputMode: "adjustResize",
|
|
3470
3559
|
topInset: insets.top,
|
|
3471
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
3560
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native21.View, { style: { flex: 1 }, children: [
|
|
3472
3561
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
3473
|
-
|
|
3562
|
+
import_react_native21.View,
|
|
3474
3563
|
{
|
|
3475
3564
|
style: {
|
|
3476
3565
|
flexDirection: "row",
|
|
@@ -3506,7 +3595,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
3506
3595
|
interactive: true,
|
|
3507
3596
|
effect: "clear",
|
|
3508
3597
|
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3509
|
-
|
|
3598
|
+
import_react_native21.View,
|
|
3510
3599
|
{
|
|
3511
3600
|
style: {
|
|
3512
3601
|
width: 32,
|
|
@@ -3518,7 +3607,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
3518
3607
|
opacity: appId ? 1 : 0.5
|
|
3519
3608
|
},
|
|
3520
3609
|
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3521
|
-
|
|
3610
|
+
import_react_native21.Pressable,
|
|
3522
3611
|
{
|
|
3523
3612
|
disabled: !appId,
|
|
3524
3613
|
onPress: () => void handlePlay(),
|
|
@@ -3553,13 +3642,13 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
3553
3642
|
},
|
|
3554
3643
|
keyboardShouldPersistTaps: "handled",
|
|
3555
3644
|
children: [
|
|
3556
|
-
loading && comments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3645
|
+
loading && comments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.View, { style: { flex: 1, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.ActivityIndicator, {}) }) : comments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native21.View, { style: { flex: 1, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Text, { variant: "bodyMuted", style: { textAlign: "center" }, children: "No comments yet" }) }) : comments.map((c, idx) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(CommentRow, { comment: c, showDivider: idx < comments.length - 1 }, c.id)),
|
|
3557
3646
|
error ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Text, { variant: "captionMuted", style: { marginTop: theme.spacing.lg }, children: "Failed to load comments." }) : null
|
|
3558
3647
|
]
|
|
3559
3648
|
}
|
|
3560
3649
|
),
|
|
3561
3650
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3562
|
-
|
|
3651
|
+
import_react_native21.View,
|
|
3563
3652
|
{
|
|
3564
3653
|
style: {
|
|
3565
3654
|
position: "absolute",
|
|
@@ -3568,7 +3657,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
3568
3657
|
bottom: 0,
|
|
3569
3658
|
paddingHorizontal: theme.spacing.lg,
|
|
3570
3659
|
paddingTop: theme.spacing.sm,
|
|
3571
|
-
paddingBottom:
|
|
3660
|
+
paddingBottom: import_react_native21.Platform.OS === "ios" ? keyboardVisible ? theme.spacing.lg : insets.bottom : insets.bottom + 10,
|
|
3572
3661
|
borderTopWidth: 1,
|
|
3573
3662
|
borderTopColor: withAlpha(theme.colors.border, 0.1),
|
|
3574
3663
|
backgroundColor: withAlpha(theme.colors.background, 0.8)
|
|
@@ -3582,7 +3671,7 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
3582
3671
|
useBottomSheetTextInput: true,
|
|
3583
3672
|
onSend: async (text) => {
|
|
3584
3673
|
await create(text);
|
|
3585
|
-
|
|
3674
|
+
import_react_native21.Keyboard.dismiss();
|
|
3586
3675
|
}
|
|
3587
3676
|
}
|
|
3588
3677
|
)
|
|
@@ -3594,16 +3683,16 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
3594
3683
|
}
|
|
3595
3684
|
|
|
3596
3685
|
// src/studio/ui/PreviewPanel.tsx
|
|
3597
|
-
var
|
|
3686
|
+
var import_react_native42 = require("react-native");
|
|
3598
3687
|
|
|
3599
3688
|
// src/components/preview/PreviewPage.tsx
|
|
3600
|
-
var
|
|
3689
|
+
var import_react_native22 = require("react-native");
|
|
3601
3690
|
var import_bottom_sheet4 = require("@gorhom/bottom-sheet");
|
|
3602
3691
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
3603
3692
|
function PreviewPage({ header, children, contentStyle }) {
|
|
3604
3693
|
const theme = useTheme();
|
|
3605
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
3606
|
-
header ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
3694
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_react_native22.View, { style: { flex: 1 }, children: [
|
|
3695
|
+
header ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native22.View, { children: header }) : null,
|
|
3607
3696
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
3608
3697
|
import_bottom_sheet4.BottomSheetScrollView,
|
|
3609
3698
|
{
|
|
@@ -3623,15 +3712,15 @@ function PreviewPage({ header, children, contentStyle }) {
|
|
|
3623
3712
|
}
|
|
3624
3713
|
|
|
3625
3714
|
// src/studio/ui/preview-panel/PreviewPanelHeader.tsx
|
|
3626
|
-
var
|
|
3715
|
+
var import_react_native25 = require("react-native");
|
|
3627
3716
|
|
|
3628
3717
|
// src/components/studio-sheet/StudioSheetHeader.tsx
|
|
3629
|
-
var
|
|
3718
|
+
var import_react_native23 = require("react-native");
|
|
3630
3719
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
3631
3720
|
function StudioSheetHeader({ left, center, right, style }) {
|
|
3632
3721
|
const theme = useTheme();
|
|
3633
3722
|
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
3634
|
-
|
|
3723
|
+
import_react_native23.View,
|
|
3635
3724
|
{
|
|
3636
3725
|
style: [
|
|
3637
3726
|
{
|
|
@@ -3644,9 +3733,9 @@ function StudioSheetHeader({ left, center, right, style }) {
|
|
|
3644
3733
|
style
|
|
3645
3734
|
],
|
|
3646
3735
|
children: [
|
|
3647
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3648
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3649
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3736
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native23.View, { style: { flexDirection: "row", alignItems: "center" }, children: left }),
|
|
3737
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native23.View, { style: { flex: 1, alignItems: "center" }, children: center }),
|
|
3738
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native23.View, { style: { flexDirection: "row", alignItems: "center" }, children: right })
|
|
3650
3739
|
]
|
|
3651
3740
|
}
|
|
3652
3741
|
);
|
|
@@ -3654,7 +3743,7 @@ function StudioSheetHeader({ left, center, right, style }) {
|
|
|
3654
3743
|
|
|
3655
3744
|
// src/components/studio-sheet/StudioSheetHeaderIconButton.tsx
|
|
3656
3745
|
var React22 = __toESM(require("react"));
|
|
3657
|
-
var
|
|
3746
|
+
var import_react_native24 = require("react-native");
|
|
3658
3747
|
var import_liquid_glass5 = require("@callstack/liquid-glass");
|
|
3659
3748
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
3660
3749
|
function StudioSheetHeaderIconButton({
|
|
@@ -3673,14 +3762,14 @@ function StudioSheetHeaderIconButton({
|
|
|
3673
3762
|
const glassFallbackBg = theme.scheme === "dark" ? "#18181B" : "#F6F6F6";
|
|
3674
3763
|
const glassInnerBg = intent === "danger" ? theme.colors.danger : theme.colors.primary;
|
|
3675
3764
|
const resolvedOpacity = disabled ? 0.6 : pressed ? 0.9 : 1;
|
|
3676
|
-
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3765
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native24.View, { style, children: appearance === "glass" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3677
3766
|
import_liquid_glass5.LiquidGlassView,
|
|
3678
3767
|
{
|
|
3679
3768
|
style: [{ borderRadius: 100 }, !import_liquid_glass5.isLiquidGlassSupported && { backgroundColor: glassFallbackBg }],
|
|
3680
3769
|
interactive: true,
|
|
3681
3770
|
effect: "clear",
|
|
3682
3771
|
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3683
|
-
|
|
3772
|
+
import_react_native24.View,
|
|
3684
3773
|
{
|
|
3685
3774
|
style: {
|
|
3686
3775
|
width: size,
|
|
@@ -3692,7 +3781,7 @@ function StudioSheetHeaderIconButton({
|
|
|
3692
3781
|
opacity: resolvedOpacity
|
|
3693
3782
|
},
|
|
3694
3783
|
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3695
|
-
|
|
3784
|
+
import_react_native24.Pressable,
|
|
3696
3785
|
{
|
|
3697
3786
|
accessibilityRole: "button",
|
|
3698
3787
|
accessibilityLabel,
|
|
@@ -3711,7 +3800,7 @@ function StudioSheetHeaderIconButton({
|
|
|
3711
3800
|
)
|
|
3712
3801
|
}
|
|
3713
3802
|
) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3714
|
-
|
|
3803
|
+
import_react_native24.View,
|
|
3715
3804
|
{
|
|
3716
3805
|
style: {
|
|
3717
3806
|
width: size,
|
|
@@ -3723,7 +3812,7 @@ function StudioSheetHeaderIconButton({
|
|
|
3723
3812
|
opacity: resolvedOpacity
|
|
3724
3813
|
},
|
|
3725
3814
|
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3726
|
-
|
|
3815
|
+
import_react_native24.Pressable,
|
|
3727
3816
|
{
|
|
3728
3817
|
accessibilityRole: "button",
|
|
3729
3818
|
accessibilityLabel,
|
|
@@ -3750,7 +3839,7 @@ function PreviewPanelHeader({ isOwner, onClose, onNavigateHome, onGoToChat }) {
|
|
|
3750
3839
|
{
|
|
3751
3840
|
left: onNavigateHome ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StudioSheetHeaderIconButton, { onPress: onNavigateHome, accessibilityLabel: "Home", appearance: "glass", intent: "primary", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(IconHome, { size: 20, colorToken: "onPrimary" }) }) : null,
|
|
3752
3841
|
center: null,
|
|
3753
|
-
right: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
3842
|
+
right: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native25.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
3754
3843
|
isOwner ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3755
3844
|
StudioSheetHeaderIconButton,
|
|
3756
3845
|
{
|
|
@@ -3769,10 +3858,10 @@ function PreviewPanelHeader({ isOwner, onClose, onNavigateHome, onGoToChat }) {
|
|
|
3769
3858
|
}
|
|
3770
3859
|
|
|
3771
3860
|
// src/components/preview/PreviewHeroCard.tsx
|
|
3772
|
-
var
|
|
3861
|
+
var import_react_native27 = require("react-native");
|
|
3773
3862
|
|
|
3774
3863
|
// src/components/primitives/Surface.tsx
|
|
3775
|
-
var
|
|
3864
|
+
var import_react_native26 = require("react-native");
|
|
3776
3865
|
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
3777
3866
|
function backgroundFor(variant, theme) {
|
|
3778
3867
|
const { colors } = theme;
|
|
@@ -3791,7 +3880,7 @@ function backgroundFor(variant, theme) {
|
|
|
3791
3880
|
function Surface({ variant = "surface", border = false, style, ...props }) {
|
|
3792
3881
|
const theme = useTheme();
|
|
3793
3882
|
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3794
|
-
|
|
3883
|
+
import_react_native26.View,
|
|
3795
3884
|
{
|
|
3796
3885
|
...props,
|
|
3797
3886
|
style: [
|
|
@@ -3847,11 +3936,11 @@ function PreviewHeroCard({
|
|
|
3847
3936
|
},
|
|
3848
3937
|
style
|
|
3849
3938
|
],
|
|
3850
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
3851
|
-
background ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3852
|
-
image ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3853
|
-
overlayTopLeft ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3854
|
-
overlayBottom ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3939
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react_native27.View, { style: { flex: 1 }, children: [
|
|
3940
|
+
background ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native27.View, { style: { position: "absolute", inset: 0 }, children: background }) : null,
|
|
3941
|
+
image ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native27.View, { style: { position: "absolute", inset: 0 }, children: image }) : null,
|
|
3942
|
+
overlayTopLeft ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native27.View, { style: { position: "absolute", top: theme.spacing.sm, left: theme.spacing.sm, zIndex: 2 }, children: overlayTopLeft }) : null,
|
|
3943
|
+
overlayBottom ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_native27.View, { style: { flex: 1, justifyContent: "flex-end" }, children: overlayBottom }) : null
|
|
3855
3944
|
] })
|
|
3856
3945
|
}
|
|
3857
3946
|
);
|
|
@@ -3859,20 +3948,20 @@ function PreviewHeroCard({
|
|
|
3859
3948
|
|
|
3860
3949
|
// src/components/preview/PreviewPlaceholder.tsx
|
|
3861
3950
|
var React23 = __toESM(require("react"));
|
|
3862
|
-
var
|
|
3951
|
+
var import_react_native28 = require("react-native");
|
|
3863
3952
|
var import_expo_linear_gradient2 = require("expo-linear-gradient");
|
|
3864
3953
|
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
3865
3954
|
function PreviewPlaceholder({ visible, style }) {
|
|
3866
3955
|
if (!visible) return null;
|
|
3867
|
-
const opacityAnim = React23.useRef(new
|
|
3956
|
+
const opacityAnim = React23.useRef(new import_react_native28.Animated.Value(0)).current;
|
|
3868
3957
|
React23.useEffect(() => {
|
|
3869
3958
|
if (!visible) return;
|
|
3870
|
-
const animation =
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3959
|
+
const animation = import_react_native28.Animated.loop(
|
|
3960
|
+
import_react_native28.Animated.sequence([
|
|
3961
|
+
import_react_native28.Animated.timing(opacityAnim, { toValue: 1, duration: 1500, useNativeDriver: true }),
|
|
3962
|
+
import_react_native28.Animated.timing(opacityAnim, { toValue: 2, duration: 1500, useNativeDriver: true }),
|
|
3963
|
+
import_react_native28.Animated.timing(opacityAnim, { toValue: 3, duration: 1500, useNativeDriver: true }),
|
|
3964
|
+
import_react_native28.Animated.timing(opacityAnim, { toValue: 0, duration: 1500, useNativeDriver: true })
|
|
3876
3965
|
])
|
|
3877
3966
|
);
|
|
3878
3967
|
animation.start();
|
|
@@ -3883,7 +3972,7 @@ function PreviewPlaceholder({ visible, style }) {
|
|
|
3883
3972
|
const opacity3 = opacityAnim.interpolate({ inputRange: [0, 1, 2, 3], outputRange: [0, 0, 1, 0] });
|
|
3884
3973
|
const opacity4 = opacityAnim.interpolate({ inputRange: [0, 1, 2, 3], outputRange: [0, 0, 0, 1] });
|
|
3885
3974
|
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
|
|
3886
|
-
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3975
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native28.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity1 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3887
3976
|
import_expo_linear_gradient2.LinearGradient,
|
|
3888
3977
|
{
|
|
3889
3978
|
colors: ["rgba(98, 0, 238, 0.45)", "rgba(168, 85, 247, 0.35)"],
|
|
@@ -3892,7 +3981,7 @@ function PreviewPlaceholder({ visible, style }) {
|
|
|
3892
3981
|
style: { width: "100%", height: "100%" }
|
|
3893
3982
|
}
|
|
3894
3983
|
) }),
|
|
3895
|
-
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3984
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native28.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity2 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3896
3985
|
import_expo_linear_gradient2.LinearGradient,
|
|
3897
3986
|
{
|
|
3898
3987
|
colors: ["rgba(168, 85, 247, 0.45)", "rgba(139, 92, 246, 0.35)"],
|
|
@@ -3901,7 +3990,7 @@ function PreviewPlaceholder({ visible, style }) {
|
|
|
3901
3990
|
style: { width: "100%", height: "100%" }
|
|
3902
3991
|
}
|
|
3903
3992
|
) }),
|
|
3904
|
-
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3993
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native28.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity3 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3905
3994
|
import_expo_linear_gradient2.LinearGradient,
|
|
3906
3995
|
{
|
|
3907
3996
|
colors: ["rgba(139, 92, 246, 0.45)", "rgba(126, 34, 206, 0.35)"],
|
|
@@ -3910,7 +3999,7 @@ function PreviewPlaceholder({ visible, style }) {
|
|
|
3910
3999
|
style: { width: "100%", height: "100%" }
|
|
3911
4000
|
}
|
|
3912
4001
|
) }),
|
|
3913
|
-
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
4002
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native28.Animated.View, { style: [{ position: "absolute", inset: 0, opacity: opacity4 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3914
4003
|
import_expo_linear_gradient2.LinearGradient,
|
|
3915
4004
|
{
|
|
3916
4005
|
colors: ["rgba(126, 34, 206, 0.45)", "rgba(98, 0, 238, 0.35)"],
|
|
@@ -3923,12 +4012,12 @@ function PreviewPlaceholder({ visible, style }) {
|
|
|
3923
4012
|
}
|
|
3924
4013
|
|
|
3925
4014
|
// src/components/preview/PreviewImage.tsx
|
|
3926
|
-
var
|
|
4015
|
+
var import_react_native29 = require("react-native");
|
|
3927
4016
|
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
3928
4017
|
function PreviewImage({ uri, onLoad, style }) {
|
|
3929
4018
|
if (!uri) return null;
|
|
3930
4019
|
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3931
|
-
|
|
4020
|
+
import_react_native29.Image,
|
|
3932
4021
|
{
|
|
3933
4022
|
source: { uri },
|
|
3934
4023
|
resizeMode: "cover",
|
|
@@ -3939,7 +4028,7 @@ function PreviewImage({ uri, onLoad, style }) {
|
|
|
3939
4028
|
}
|
|
3940
4029
|
|
|
3941
4030
|
// src/components/preview/StatsBar.tsx
|
|
3942
|
-
var
|
|
4031
|
+
var import_react_native30 = require("react-native");
|
|
3943
4032
|
var import_liquid_glass6 = require("@callstack/liquid-glass");
|
|
3944
4033
|
var import_lucide_react_native5 = require("lucide-react-native");
|
|
3945
4034
|
|
|
@@ -3972,7 +4061,7 @@ function StatsBar({
|
|
|
3972
4061
|
const theme = useTheme();
|
|
3973
4062
|
const statsBgColor = theme.scheme === "dark" ? "rgba(24, 24, 27, 0.5)" : "rgba(255, 255, 255, 0.5)";
|
|
3974
4063
|
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
3975
|
-
|
|
4064
|
+
import_react_native30.View,
|
|
3976
4065
|
{
|
|
3977
4066
|
style: [
|
|
3978
4067
|
{ position: "absolute", bottom: 12, width: "100%", paddingHorizontal: 12 },
|
|
@@ -3988,15 +4077,15 @@ function StatsBar({
|
|
|
3988
4077
|
!import_liquid_glass6.isLiquidGlassSupported && { backgroundColor: statsBgColor }
|
|
3989
4078
|
],
|
|
3990
4079
|
effect: "clear",
|
|
3991
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
4080
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_react_native30.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: 16 }, children: [
|
|
3992
4081
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
3993
|
-
|
|
4082
|
+
import_react_native30.Pressable,
|
|
3994
4083
|
{
|
|
3995
4084
|
disabled: !onPressLike,
|
|
3996
4085
|
onPress: onPressLike,
|
|
3997
4086
|
hitSlop: 8,
|
|
3998
4087
|
style: { paddingVertical: 8 },
|
|
3999
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
4088
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_react_native30.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
4000
4089
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
4001
4090
|
import_lucide_react_native5.Heart,
|
|
4002
4091
|
{
|
|
@@ -4006,7 +4095,7 @@ function StatsBar({
|
|
|
4006
4095
|
fill: isLiked ? theme.colors.danger : "transparent"
|
|
4007
4096
|
}
|
|
4008
4097
|
),
|
|
4009
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
4098
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react_native30.View, { style: { width: 4 } }),
|
|
4010
4099
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
4011
4100
|
Text,
|
|
4012
4101
|
{
|
|
@@ -4022,22 +4111,22 @@ function StatsBar({
|
|
|
4022
4111
|
}
|
|
4023
4112
|
),
|
|
4024
4113
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
4025
|
-
|
|
4114
|
+
import_react_native30.Pressable,
|
|
4026
4115
|
{
|
|
4027
4116
|
disabled: !onPressComments,
|
|
4028
4117
|
onPress: onPressComments,
|
|
4029
4118
|
hitSlop: 8,
|
|
4030
4119
|
style: { paddingVertical: 8 },
|
|
4031
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
4120
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_react_native30.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
4032
4121
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react_native5.MessageCircle, { size: 16, strokeWidth: 2.5, color: "#FFFFFF" }),
|
|
4033
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
4122
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react_native30.View, { style: { width: 4 } }),
|
|
4034
4123
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Text, { variant: "caption", style: { color: "#FFFFFF", fontWeight: theme.typography.fontWeight.bold }, children: commentCount })
|
|
4035
4124
|
] })
|
|
4036
4125
|
}
|
|
4037
4126
|
),
|
|
4038
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
4039
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
4040
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
4127
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_react_native30.View, { style: { flexDirection: "row", alignItems: "center", paddingVertical: 8 }, children: [
|
|
4128
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react_native30.View, { style: { transform: [{ scaleY: -1 }] }, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(MergeIcon, { width: 14, height: 14, color: "#FFFFFF" }) }),
|
|
4129
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react_native30.View, { style: { width: 4 } }),
|
|
4041
4130
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Text, { variant: "caption", style: { color: "#FFFFFF", fontWeight: theme.typography.fontWeight.bold }, children: forkCount })
|
|
4042
4131
|
] })
|
|
4043
4132
|
] })
|
|
@@ -4048,7 +4137,7 @@ function StatsBar({
|
|
|
4048
4137
|
}
|
|
4049
4138
|
|
|
4050
4139
|
// src/components/preview/PreviewStatusBadge.tsx
|
|
4051
|
-
var
|
|
4140
|
+
var import_react_native31 = require("react-native");
|
|
4052
4141
|
var import_lucide_react_native6 = require("lucide-react-native");
|
|
4053
4142
|
|
|
4054
4143
|
// src/data/apps/types.ts
|
|
@@ -4093,7 +4182,7 @@ function PreviewStatusBadge({ status }) {
|
|
|
4093
4182
|
const IconComp = STATUS_ICON[status];
|
|
4094
4183
|
const label = APP_STATUS_LABEL[status] ?? status;
|
|
4095
4184
|
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
4096
|
-
|
|
4185
|
+
import_react_native31.View,
|
|
4097
4186
|
{
|
|
4098
4187
|
style: {
|
|
4099
4188
|
flexDirection: "row",
|
|
@@ -4146,10 +4235,10 @@ function PreviewHeroSection({
|
|
|
4146
4235
|
}
|
|
4147
4236
|
|
|
4148
4237
|
// src/studio/ui/preview-panel/PreviewMetaSection.tsx
|
|
4149
|
-
var
|
|
4238
|
+
var import_react_native33 = require("react-native");
|
|
4150
4239
|
|
|
4151
4240
|
// src/components/preview/PreviewMetaRow.tsx
|
|
4152
|
-
var
|
|
4241
|
+
var import_react_native32 = require("react-native");
|
|
4153
4242
|
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
4154
4243
|
function PreviewMetaRow({
|
|
4155
4244
|
avatarUri,
|
|
@@ -4161,10 +4250,10 @@ function PreviewMetaRow({
|
|
|
4161
4250
|
style
|
|
4162
4251
|
}) {
|
|
4163
4252
|
const theme = useTheme();
|
|
4164
|
-
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
4165
|
-
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
4253
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react_native32.View, { style: [{ alignSelf: "stretch" }, style], children: [
|
|
4254
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react_native32.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
4166
4255
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Avatar, { uri: avatarUri, name: creatorName, size: 24, style: { marginRight: theme.spacing.sm } }),
|
|
4167
|
-
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
4256
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react_native32.View, { style: { flexDirection: "row", alignItems: "center", flex: 1, minWidth: 0, marginRight: theme.spacing.sm }, children: [
|
|
4168
4257
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
4169
4258
|
Text,
|
|
4170
4259
|
{
|
|
@@ -4179,9 +4268,9 @@ function PreviewMetaRow({
|
|
|
4179
4268
|
children: title
|
|
4180
4269
|
}
|
|
4181
4270
|
),
|
|
4182
|
-
tag ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
4271
|
+
tag ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react_native32.View, { style: { marginLeft: theme.spacing.sm }, children: tag }) : null
|
|
4183
4272
|
] }),
|
|
4184
|
-
rightMetric ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
4273
|
+
rightMetric ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react_native32.View, { children: rightMetric }) : null
|
|
4185
4274
|
] }),
|
|
4186
4275
|
subtitle ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
4187
4276
|
Text,
|
|
@@ -4237,9 +4326,9 @@ function PreviewMetaSection({ app, isOwner, creator, downloadsCount }) {
|
|
|
4237
4326
|
subtitle: app.description,
|
|
4238
4327
|
avatarUri: (creator == null ? void 0 : creator.avatar) ?? null,
|
|
4239
4328
|
creatorName: (creator == null ? void 0 : creator.name) ?? null,
|
|
4240
|
-
tag: isOwner || app.forkedFromAppId ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
4329
|
+
tag: isOwner || app.forkedFromAppId ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_react_native33.View, { style: { paddingHorizontal: 8, paddingVertical: 2, borderRadius: 999, backgroundColor: "#3700B3" }, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Text, { variant: "caption", style: { color: "#fff", fontWeight: theme.typography.fontWeight.semibold }, children: app.forkedFromAppId ? "Remix" : "Owner" }) }) : null,
|
|
4241
4330
|
rightMetric: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
4242
|
-
|
|
4331
|
+
import_react_native33.View,
|
|
4243
4332
|
{
|
|
4244
4333
|
style: {
|
|
4245
4334
|
flexDirection: "row",
|
|
@@ -4273,10 +4362,10 @@ function PreviewMetaSection({ app, isOwner, creator, downloadsCount }) {
|
|
|
4273
4362
|
}
|
|
4274
4363
|
|
|
4275
4364
|
// src/studio/ui/preview-panel/PreviewCustomizeSection.tsx
|
|
4276
|
-
var
|
|
4365
|
+
var import_react_native35 = require("react-native");
|
|
4277
4366
|
|
|
4278
4367
|
// src/studio/ui/preview-panel/PressableCardRow.tsx
|
|
4279
|
-
var
|
|
4368
|
+
var import_react_native34 = require("react-native");
|
|
4280
4369
|
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
4281
4370
|
function PressableCardRow({
|
|
4282
4371
|
accessibilityLabel,
|
|
@@ -4289,20 +4378,20 @@ function PressableCardRow({
|
|
|
4289
4378
|
style
|
|
4290
4379
|
}) {
|
|
4291
4380
|
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
4292
|
-
|
|
4381
|
+
import_react_native34.Pressable,
|
|
4293
4382
|
{
|
|
4294
4383
|
accessibilityRole: "button",
|
|
4295
4384
|
accessibilityLabel,
|
|
4296
4385
|
disabled,
|
|
4297
4386
|
onPress,
|
|
4298
4387
|
style: ({ pressed }) => ({ opacity: disabled ? 0.6 : pressed ? 0.85 : 1 }),
|
|
4299
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Card, { padded: false, border: false, style, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
4388
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Card, { padded: false, border: false, style, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react_native34.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
4300
4389
|
left,
|
|
4301
|
-
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
4390
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react_native34.View, { style: { flex: 1, minWidth: 0 }, children: [
|
|
4302
4391
|
title,
|
|
4303
4392
|
subtitle ? subtitle : null
|
|
4304
4393
|
] }),
|
|
4305
|
-
right ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
4394
|
+
right ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react_native34.View, { style: { marginLeft: 16 }, children: right }) : null
|
|
4306
4395
|
] }) })
|
|
4307
4396
|
}
|
|
4308
4397
|
);
|
|
@@ -4344,7 +4433,7 @@ function PreviewCustomizeSection({
|
|
|
4344
4433
|
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
|
|
4345
4434
|
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(SectionTitle, { children: "Customize" }),
|
|
4346
4435
|
showProcessing ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
4347
|
-
|
|
4436
|
+
import_react_native35.View,
|
|
4348
4437
|
{
|
|
4349
4438
|
style: {
|
|
4350
4439
|
flexDirection: "row",
|
|
@@ -4358,7 +4447,7 @@ function PreviewCustomizeSection({
|
|
|
4358
4447
|
},
|
|
4359
4448
|
children: [
|
|
4360
4449
|
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
4361
|
-
|
|
4450
|
+
import_react_native35.View,
|
|
4362
4451
|
{
|
|
4363
4452
|
style: {
|
|
4364
4453
|
width: 40,
|
|
@@ -4369,10 +4458,10 @@ function PreviewCustomizeSection({
|
|
|
4369
4458
|
backgroundColor: withAlpha(theme.colors.warning, 0.1),
|
|
4370
4459
|
marginRight: theme.spacing.lg
|
|
4371
4460
|
},
|
|
4372
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
4461
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react_native35.ActivityIndicator, { color: theme.colors.warning, size: "small" })
|
|
4373
4462
|
}
|
|
4374
4463
|
),
|
|
4375
|
-
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
4464
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_react_native35.View, { style: { flex: 1, minWidth: 0 }, children: [
|
|
4376
4465
|
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Text, { style: { color: theme.colors.text, fontSize: 16, lineHeight: 20, fontWeight: theme.typography.fontWeight.semibold }, children: app.status === "error" ? "Error" : "Processing" }),
|
|
4377
4466
|
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Text, { style: { color: theme.colors.textMuted, fontSize: 12, lineHeight: 16, marginTop: 2 }, children: statusDescription(app.status, app.statusError) })
|
|
4378
4467
|
] })
|
|
@@ -4393,7 +4482,7 @@ function PreviewCustomizeSection({
|
|
|
4393
4482
|
marginBottom: theme.spacing.sm
|
|
4394
4483
|
},
|
|
4395
4484
|
left: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
4396
|
-
|
|
4485
|
+
import_react_native35.View,
|
|
4397
4486
|
{
|
|
4398
4487
|
style: {
|
|
4399
4488
|
width: 40,
|
|
@@ -4426,7 +4515,7 @@ function PreviewCustomizeSection({
|
|
|
4426
4515
|
marginBottom: theme.spacing.sm
|
|
4427
4516
|
},
|
|
4428
4517
|
left: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
4429
|
-
|
|
4518
|
+
import_react_native35.View,
|
|
4430
4519
|
{
|
|
4431
4520
|
style: {
|
|
4432
4521
|
width: 40,
|
|
@@ -4450,16 +4539,16 @@ function PreviewCustomizeSection({
|
|
|
4450
4539
|
|
|
4451
4540
|
// src/studio/ui/preview-panel/PreviewCollaborateSection.tsx
|
|
4452
4541
|
var React29 = __toESM(require("react"));
|
|
4453
|
-
var
|
|
4542
|
+
var import_react_native41 = require("react-native");
|
|
4454
4543
|
var import_lucide_react_native9 = require("lucide-react-native");
|
|
4455
4544
|
|
|
4456
4545
|
// src/components/merge-requests/MergeRequestStatusCard.tsx
|
|
4457
4546
|
var React25 = __toESM(require("react"));
|
|
4458
|
-
var
|
|
4547
|
+
var import_react_native37 = require("react-native");
|
|
4459
4548
|
var import_lucide_react_native7 = require("lucide-react-native");
|
|
4460
4549
|
|
|
4461
4550
|
// src/components/primitives/MarkdownText.tsx
|
|
4462
|
-
var
|
|
4551
|
+
var import_react_native36 = require("react-native");
|
|
4463
4552
|
var import_react_native_markdown_display = __toESM(require("react-native-markdown-display"));
|
|
4464
4553
|
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
4465
4554
|
function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
|
|
@@ -4472,7 +4561,7 @@ function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
|
|
|
4472
4561
|
const codeTextColor = isDark ? "#FFFFFF" : theme.colors.text;
|
|
4473
4562
|
const paragraphBottom = variant === "mergeRequest" ? 8 : 6;
|
|
4474
4563
|
const baseLineHeight = variant === "mergeRequest" ? 22 : 20;
|
|
4475
|
-
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
4564
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_react_native36.View, { style, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
4476
4565
|
import_react_native_markdown_display.default,
|
|
4477
4566
|
{
|
|
4478
4567
|
style: {
|
|
@@ -4485,7 +4574,7 @@ function MarkdownText({ markdown, variant = "chat", bodyColor, style }) {
|
|
|
4485
4574
|
paddingHorizontal: variant === "mergeRequest" ? 6 : 4,
|
|
4486
4575
|
paddingVertical: variant === "mergeRequest" ? 2 : 0,
|
|
4487
4576
|
borderRadius: variant === "mergeRequest" ? 6 : 4,
|
|
4488
|
-
fontFamily:
|
|
4577
|
+
fontFamily: import_react_native36.Platform.OS === "ios" ? "Menlo" : "monospace",
|
|
4489
4578
|
fontSize: 13
|
|
4490
4579
|
},
|
|
4491
4580
|
code_block: {
|
|
@@ -4597,15 +4686,15 @@ function MergeRequestStatusCard({
|
|
|
4597
4686
|
const createdIso = toIsoString(mergeRequest.createdAt ?? null);
|
|
4598
4687
|
const headerTimeAgo = updatedIso ? formatTimeAgo(updatedIso) : "";
|
|
4599
4688
|
const createdTimeAgo = createdIso ? formatTimeAgo(createdIso) : "";
|
|
4600
|
-
const rotate = React25.useRef(new
|
|
4689
|
+
const rotate = React25.useRef(new import_react_native37.Animated.Value(expanded ? 1 : 0)).current;
|
|
4601
4690
|
React25.useEffect(() => {
|
|
4602
|
-
|
|
4691
|
+
import_react_native37.Animated.timing(rotate, {
|
|
4603
4692
|
toValue: expanded ? 1 : 0,
|
|
4604
4693
|
duration: 200,
|
|
4605
4694
|
useNativeDriver: true
|
|
4606
4695
|
}).start();
|
|
4607
4696
|
}, [expanded, rotate]);
|
|
4608
|
-
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
4697
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_react_native37.Pressable, { onPress: () => setExpanded(!expanded), style: ({ pressed }) => [{ opacity: pressed ? 0.95 : 1 }], children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
4609
4698
|
Card,
|
|
4610
4699
|
{
|
|
4611
4700
|
padded: false,
|
|
@@ -4618,10 +4707,10 @@ function MergeRequestStatusCard({
|
|
|
4618
4707
|
style
|
|
4619
4708
|
],
|
|
4620
4709
|
children: [
|
|
4621
|
-
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
4622
|
-
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
4623
|
-
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
4624
|
-
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
4710
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_react_native37.View, { style: { flexDirection: "row", alignItems: "center", gap: theme.spacing.lg }, children: [
|
|
4711
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_react_native37.View, { style: { width: 40, height: 40, borderRadius: 999, alignItems: "center", justifyContent: "center", backgroundColor: bgColor }, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(StatusIcon, { size: 20, color: iconColor }) }),
|
|
4712
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_react_native37.View, { style: { flex: 1, minWidth: 0 }, children: [
|
|
4713
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_react_native37.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
4625
4714
|
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
4626
4715
|
Text,
|
|
4627
4716
|
{
|
|
@@ -4640,8 +4729,8 @@ function MergeRequestStatusCard({
|
|
|
4640
4729
|
] }),
|
|
4641
4730
|
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Text, { style: { fontSize: 12, lineHeight: 16, color: theme.colors.textMuted }, numberOfLines: 1, children: mergeRequest.title ?? "Untitled merge request" })
|
|
4642
4731
|
] }),
|
|
4643
|
-
headerRight ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
4644
|
-
|
|
4732
|
+
headerRight ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_react_native37.View, { children: headerRight }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
4733
|
+
import_react_native37.Animated.View,
|
|
4645
4734
|
{
|
|
4646
4735
|
style: {
|
|
4647
4736
|
transform: [
|
|
@@ -4654,7 +4743,7 @@ function MergeRequestStatusCard({
|
|
|
4654
4743
|
}
|
|
4655
4744
|
)
|
|
4656
4745
|
] }),
|
|
4657
|
-
expanded ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
4746
|
+
expanded ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_react_native37.View, { style: { marginTop: 16, marginLeft: 56 }, children: [
|
|
4658
4747
|
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
4659
4748
|
Text,
|
|
4660
4749
|
{
|
|
@@ -4690,16 +4779,16 @@ function MergeRequestStatusCard({
|
|
|
4690
4779
|
|
|
4691
4780
|
// src/components/merge-requests/ReviewMergeRequestCarousel.tsx
|
|
4692
4781
|
var React28 = __toESM(require("react"));
|
|
4693
|
-
var
|
|
4782
|
+
var import_react_native40 = require("react-native");
|
|
4694
4783
|
|
|
4695
4784
|
// src/components/merge-requests/ReviewMergeRequestCard.tsx
|
|
4696
4785
|
var React27 = __toESM(require("react"));
|
|
4697
|
-
var
|
|
4786
|
+
var import_react_native39 = require("react-native");
|
|
4698
4787
|
var import_lucide_react_native8 = require("lucide-react-native");
|
|
4699
4788
|
|
|
4700
4789
|
// src/components/merge-requests/ReviewMergeRequestActionButton.tsx
|
|
4701
4790
|
var React26 = __toESM(require("react"));
|
|
4702
|
-
var
|
|
4791
|
+
var import_react_native38 = require("react-native");
|
|
4703
4792
|
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
4704
4793
|
function ReviewMergeRequestActionButton({
|
|
4705
4794
|
accessibilityLabel,
|
|
@@ -4716,7 +4805,7 @@ function ReviewMergeRequestActionButton({
|
|
|
4716
4805
|
const paddingVertical = iconOnly ? 0 : 8;
|
|
4717
4806
|
const opacity = disabled ? 0.5 : pressed ? 0.9 : 1;
|
|
4718
4807
|
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
4719
|
-
|
|
4808
|
+
import_react_native38.View,
|
|
4720
4809
|
{
|
|
4721
4810
|
style: {
|
|
4722
4811
|
width,
|
|
@@ -4731,7 +4820,7 @@ function ReviewMergeRequestActionButton({
|
|
|
4731
4820
|
justifyContent: "center"
|
|
4732
4821
|
},
|
|
4733
4822
|
children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
4734
|
-
|
|
4823
|
+
import_react_native38.Pressable,
|
|
4735
4824
|
{
|
|
4736
4825
|
accessibilityRole: "button",
|
|
4737
4826
|
accessibilityLabel,
|
|
@@ -4773,12 +4862,12 @@ function ReviewMergeRequestCard({
|
|
|
4773
4862
|
const theme = useTheme();
|
|
4774
4863
|
const status = React27.useMemo(() => getMergeRequestStatusDisplay(mr.status), [mr.status]);
|
|
4775
4864
|
const canAct = mr.status === "open";
|
|
4776
|
-
const rotate = React27.useRef(new
|
|
4865
|
+
const rotate = React27.useRef(new import_react_native39.Animated.Value(isExpanded ? 1 : 0)).current;
|
|
4777
4866
|
React27.useEffect(() => {
|
|
4778
|
-
|
|
4867
|
+
import_react_native39.Animated.timing(rotate, { toValue: isExpanded ? 1 : 0, duration: 200, useNativeDriver: true }).start();
|
|
4779
4868
|
}, [isExpanded, rotate]);
|
|
4780
4869
|
const position = total > 1 ? `${index + 1}/${total}` : "Merge request";
|
|
4781
|
-
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
4870
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_native39.Pressable, { onPress: onToggle, style: ({ pressed }) => ({ opacity: pressed ? 0.95 : 1 }), children: /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
4782
4871
|
Card,
|
|
4783
4872
|
{
|
|
4784
4873
|
padded: false,
|
|
@@ -4791,9 +4880,9 @@ function ReviewMergeRequestCard({
|
|
|
4791
4880
|
}
|
|
4792
4881
|
],
|
|
4793
4882
|
children: [
|
|
4794
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
4883
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native39.View, { style: { flexDirection: "row", alignItems: "center", gap: 12 }, children: [
|
|
4795
4884
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Avatar, { size: 40, uri: (creator == null ? void 0 : creator.avatar) ?? null, name: (creator == null ? void 0 : creator.name) ?? void 0 }),
|
|
4796
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
4885
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native39.View, { style: { flex: 1, minWidth: 0 }, children: [
|
|
4797
4886
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
4798
4887
|
Text,
|
|
4799
4888
|
{
|
|
@@ -4809,7 +4898,7 @@ function ReviewMergeRequestCard({
|
|
|
4809
4898
|
] })
|
|
4810
4899
|
] }),
|
|
4811
4900
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
4812
|
-
|
|
4901
|
+
import_react_native39.Animated.View,
|
|
4813
4902
|
{
|
|
4814
4903
|
style: {
|
|
4815
4904
|
transform: [{ rotate: rotate.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "180deg"] }) }]
|
|
@@ -4818,7 +4907,7 @@ function ReviewMergeRequestCard({
|
|
|
4818
4907
|
}
|
|
4819
4908
|
)
|
|
4820
4909
|
] }),
|
|
4821
|
-
isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
4910
|
+
isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native39.View, { style: { marginTop: 16 }, children: [
|
|
4822
4911
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
4823
4912
|
Text,
|
|
4824
4913
|
{
|
|
@@ -4836,9 +4925,9 @@ function ReviewMergeRequestCard({
|
|
|
4836
4925
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Text, { style: { color: theme.colors.textMuted, fontSize: 12, lineHeight: 16, marginBottom: 12 }, children: creator ? `${creator.approvedOpenedMergeRequests} approved merge${creator.approvedOpenedMergeRequests !== 1 ? "s" : ""}` : "Loading stats..." }),
|
|
4837
4926
|
mr.description ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(MarkdownText, { markdown: mr.description, variant: "mergeRequest" }) : null
|
|
4838
4927
|
] }) : null,
|
|
4839
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
4840
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
4841
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
4928
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_native39.View, { style: { height: 1, backgroundColor: withAlpha(theme.colors.borderStrong, 0.5), marginTop: 12, marginBottom: 12 } }),
|
|
4929
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native39.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
4930
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native39.View, { style: { flexDirection: "row", gap: 8 }, children: [
|
|
4842
4931
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
4843
4932
|
ReviewMergeRequestActionButton,
|
|
4844
4933
|
{
|
|
@@ -4847,7 +4936,7 @@ function ReviewMergeRequestCard({
|
|
|
4847
4936
|
disabled: !canAct || isAnyProcessing,
|
|
4848
4937
|
onPress: onReject,
|
|
4849
4938
|
iconOnly: !isExpanded,
|
|
4850
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
4939
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native39.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
|
|
4851
4940
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react_native8.X, { size: 18, color: "#FFFFFF" }),
|
|
4852
4941
|
isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Text, { style: { fontSize: 13, color: "#FFFFFF", fontWeight: theme.typography.fontWeight.semibold }, children: "Reject" }) : null
|
|
4853
4942
|
] })
|
|
@@ -4861,10 +4950,10 @@ function ReviewMergeRequestCard({
|
|
|
4861
4950
|
disabled: !canAct || isAnyProcessing,
|
|
4862
4951
|
onPress: onApprove,
|
|
4863
4952
|
iconOnly: !isExpanded,
|
|
4864
|
-
children: isProcessing ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
4865
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
4953
|
+
children: isProcessing ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native39.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
|
|
4954
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_native39.ActivityIndicator, { size: "small", color: "#FFFFFF" }),
|
|
4866
4955
|
isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Text, { style: { fontSize: 13, color: "#FFFFFF", fontWeight: theme.typography.fontWeight.semibold }, children: "Processing" }) : null
|
|
4867
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
4956
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native39.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
|
|
4868
4957
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react_native8.Check, { size: 18, color: "#FFFFFF" }),
|
|
4869
4958
|
isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Text, { style: { fontSize: 13, color: "#FFFFFF", fontWeight: theme.typography.fontWeight.semibold }, children: "Approve" }) : null
|
|
4870
4959
|
] })
|
|
@@ -4879,7 +4968,7 @@ function ReviewMergeRequestCard({
|
|
|
4879
4968
|
disabled: isBuilding || isTestingThis,
|
|
4880
4969
|
onPress: onTest,
|
|
4881
4970
|
iconOnly: !isExpanded,
|
|
4882
|
-
children: isTestingThis ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
4971
|
+
children: isTestingThis ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_native39.ActivityIndicator, { size: "small", color: "#888" }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native39.View, { style: { flexDirection: "row", alignItems: "center", gap: isExpanded ? 4 : 0 }, children: [
|
|
4883
4972
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react_native8.Play, { size: 14, color: theme.colors.text }),
|
|
4884
4973
|
isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Text, { style: { fontSize: 13, color: theme.colors.text, fontWeight: theme.typography.fontWeight.semibold }, children: "Test" }) : null
|
|
4885
4974
|
] })
|
|
@@ -4905,32 +4994,32 @@ function ReviewMergeRequestCarousel({
|
|
|
4905
4994
|
style
|
|
4906
4995
|
}) {
|
|
4907
4996
|
const theme = useTheme();
|
|
4908
|
-
const { width } = (0,
|
|
4997
|
+
const { width } = (0, import_react_native40.useWindowDimensions)();
|
|
4909
4998
|
const [expanded, setExpanded] = React28.useState({});
|
|
4910
|
-
const carouselScrollX = React28.useRef(new
|
|
4999
|
+
const carouselScrollX = React28.useRef(new import_react_native40.Animated.Value(0)).current;
|
|
4911
5000
|
const peekAmount = 24;
|
|
4912
5001
|
const gap = 16;
|
|
4913
5002
|
const cardWidth = React28.useMemo(() => Math.max(1, width - theme.spacing.lg * 2 - peekAmount), [peekAmount, theme.spacing.lg, width]);
|
|
4914
5003
|
const snapInterval = cardWidth + gap;
|
|
4915
5004
|
const dotColor = theme.scheme === "dark" ? "#FFFFFF" : "#000000";
|
|
4916
5005
|
if (mergeRequests.length === 0) return null;
|
|
4917
|
-
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
|
|
5006
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_react_native40.View, { style: [{ marginHorizontal: -theme.spacing.lg }, style], children: [
|
|
4918
5007
|
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
4919
|
-
|
|
5008
|
+
import_react_native40.FlatList,
|
|
4920
5009
|
{
|
|
4921
5010
|
horizontal: true,
|
|
4922
5011
|
data: mergeRequests,
|
|
4923
5012
|
keyExtractor: (mr) => mr.id,
|
|
4924
5013
|
showsHorizontalScrollIndicator: false,
|
|
4925
5014
|
contentContainerStyle: { paddingHorizontal: theme.spacing.lg, paddingVertical: theme.spacing.sm },
|
|
4926
|
-
ItemSeparatorComponent: () => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
5015
|
+
ItemSeparatorComponent: () => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_react_native40.View, { style: { width: gap } }),
|
|
4927
5016
|
snapToAlignment: "start",
|
|
4928
5017
|
decelerationRate: "fast",
|
|
4929
5018
|
snapToInterval: snapInterval,
|
|
4930
5019
|
disableIntervalMomentum: true,
|
|
4931
5020
|
style: { paddingRight: peekAmount },
|
|
4932
|
-
ListFooterComponent: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
4933
|
-
onScroll:
|
|
5021
|
+
ListFooterComponent: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_react_native40.View, { style: { width: peekAmount } }),
|
|
5022
|
+
onScroll: import_react_native40.Animated.event([{ nativeEvent: { contentOffset: { x: carouselScrollX } } }], {
|
|
4934
5023
|
useNativeDriver: false
|
|
4935
5024
|
}),
|
|
4936
5025
|
scrollEventThrottle: 16,
|
|
@@ -4941,7 +5030,7 @@ function ReviewMergeRequestCarousel({
|
|
|
4941
5030
|
const isProcessing = Boolean(processingMrId && processingMrId === item.id);
|
|
4942
5031
|
const isAnyProcessing = Boolean(processingMrId);
|
|
4943
5032
|
const isTestingThis = Boolean(testingMrId && testingMrId === item.id);
|
|
4944
|
-
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
5033
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_react_native40.View, { style: { width: cardWidth }, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
4945
5034
|
ReviewMergeRequestCard,
|
|
4946
5035
|
{
|
|
4947
5036
|
mr: item,
|
|
@@ -4962,7 +5051,7 @@ function ReviewMergeRequestCarousel({
|
|
|
4962
5051
|
}
|
|
4963
5052
|
}
|
|
4964
5053
|
),
|
|
4965
|
-
mergeRequests.length >= 1 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
5054
|
+
mergeRequests.length >= 1 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_react_native40.View, { style: { flexDirection: "row", justifyContent: "center", columnGap: 8, marginTop: theme.spacing.md }, children: mergeRequests.map((mr, index) => {
|
|
4966
5055
|
const inputRange = [(index - 1) * snapInterval, index * snapInterval, (index + 1) * snapInterval];
|
|
4967
5056
|
const scale = carouselScrollX.interpolate({
|
|
4968
5057
|
inputRange,
|
|
@@ -4975,7 +5064,7 @@ function ReviewMergeRequestCarousel({
|
|
|
4975
5064
|
extrapolate: "clamp"
|
|
4976
5065
|
});
|
|
4977
5066
|
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
4978
|
-
|
|
5067
|
+
import_react_native40.Animated.View,
|
|
4979
5068
|
{
|
|
4980
5069
|
style: {
|
|
4981
5070
|
width: 8,
|
|
@@ -5036,7 +5125,7 @@ function PreviewCollaborateSection({
|
|
|
5036
5125
|
accessibilityLabel: "Submit merge request",
|
|
5037
5126
|
disabled: submittingMr,
|
|
5038
5127
|
onPress: () => {
|
|
5039
|
-
|
|
5128
|
+
import_react_native41.Alert.alert(
|
|
5040
5129
|
"Submit Merge Request",
|
|
5041
5130
|
"Are you sure you want to submit your changes to the original app?",
|
|
5042
5131
|
[
|
|
@@ -5062,7 +5151,7 @@ function PreviewCollaborateSection({
|
|
|
5062
5151
|
marginBottom: theme.spacing.sm
|
|
5063
5152
|
},
|
|
5064
5153
|
left: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
5065
|
-
|
|
5154
|
+
import_react_native41.View,
|
|
5066
5155
|
{
|
|
5067
5156
|
style: {
|
|
5068
5157
|
width: 40,
|
|
@@ -5073,7 +5162,7 @@ function PreviewCollaborateSection({
|
|
|
5073
5162
|
backgroundColor: withAlpha("#03DAC6", 0.1),
|
|
5074
5163
|
marginRight: theme.spacing.lg
|
|
5075
5164
|
},
|
|
5076
|
-
children: submittingMr ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
5165
|
+
children: submittingMr ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_react_native41.ActivityIndicator, { color: "#03DAC6", size: "small" }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(MergeIcon, { width: 20, height: 20, color: "#03DAC6" })
|
|
5077
5166
|
}
|
|
5078
5167
|
),
|
|
5079
5168
|
title: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Text, { style: { color: theme.colors.text, fontSize: 16, lineHeight: 20, fontWeight: theme.typography.fontWeight.semibold }, children: "Submit your new changes" }),
|
|
@@ -5111,7 +5200,7 @@ function PreviewCollaborateSection({
|
|
|
5111
5200
|
children: "History"
|
|
5112
5201
|
}
|
|
5113
5202
|
),
|
|
5114
|
-
outgoingMergeRequests.map((mr) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
5203
|
+
outgoingMergeRequests.map((mr) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_react_native41.View, { style: { marginBottom: theme.spacing.sm }, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(MergeRequestStatusCard, { mergeRequest: toMergeRequestSummary(mr) }) }, mr.id))
|
|
5115
5204
|
] }) : null
|
|
5116
5205
|
] });
|
|
5117
5206
|
}
|
|
@@ -5435,9 +5524,9 @@ function PreviewPanel({
|
|
|
5435
5524
|
});
|
|
5436
5525
|
const header = /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(PreviewPanelHeader, { isOwner, onClose, onNavigateHome, onGoToChat });
|
|
5437
5526
|
if (loading || !app) {
|
|
5438
|
-
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(PreviewPage, { header, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
5439
|
-
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
5440
|
-
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
5527
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(PreviewPage, { header, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_react_native42.View, { style: { flex: 1, justifyContent: "center", alignItems: "center", padding: 24 }, children: [
|
|
5528
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native42.ActivityIndicator, {}),
|
|
5529
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native42.View, { style: { height: 12 } }),
|
|
5441
5530
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Text, { variant: "bodyMuted", children: "Loading app\u2026" })
|
|
5442
5531
|
] }) });
|
|
5443
5532
|
}
|
|
@@ -5494,21 +5583,20 @@ function PreviewPanel({
|
|
|
5494
5583
|
|
|
5495
5584
|
// src/studio/ui/ChatPanel.tsx
|
|
5496
5585
|
var React36 = __toESM(require("react"));
|
|
5497
|
-
var
|
|
5586
|
+
var import_react_native50 = require("react-native");
|
|
5498
5587
|
|
|
5499
5588
|
// src/components/chat/ChatPage.tsx
|
|
5500
5589
|
var React34 = __toESM(require("react"));
|
|
5501
|
-
var
|
|
5590
|
+
var import_react_native46 = require("react-native");
|
|
5502
5591
|
var import_react_native_safe_area_context4 = require("react-native-safe-area-context");
|
|
5503
|
-
var import_react_native_reanimated2 = __toESM(require("react-native-reanimated"));
|
|
5504
5592
|
|
|
5505
5593
|
// src/components/chat/ChatMessageList.tsx
|
|
5506
5594
|
var React33 = __toESM(require("react"));
|
|
5507
|
-
var
|
|
5595
|
+
var import_react_native45 = require("react-native");
|
|
5508
5596
|
var import_bottom_sheet5 = require("@gorhom/bottom-sheet");
|
|
5509
5597
|
|
|
5510
5598
|
// src/components/chat/ChatMessageBubble.tsx
|
|
5511
|
-
var
|
|
5599
|
+
var import_react_native43 = require("react-native");
|
|
5512
5600
|
var import_lucide_react_native10 = require("lucide-react-native");
|
|
5513
5601
|
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
5514
5602
|
function ChatMessageBubble({ message, renderContent, style }) {
|
|
@@ -5524,7 +5612,7 @@ function ChatMessageBubble({ message, renderContent, style }) {
|
|
|
5524
5612
|
const bubbleVariant = isHuman ? "surface" : "surfaceRaised";
|
|
5525
5613
|
const cornerStyle = isHuman ? { borderTopRightRadius: 0 } : { borderTopLeftRadius: 0 };
|
|
5526
5614
|
const bodyColor = metaStatus === "success" ? theme.colors.success : metaStatus === "error" ? theme.colors.danger : void 0;
|
|
5527
|
-
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
5615
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native43.View, { style: [align, style], children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
5528
5616
|
Surface,
|
|
5529
5617
|
{
|
|
5530
5618
|
variant: bubbleVariant,
|
|
@@ -5539,10 +5627,10 @@ function ChatMessageBubble({ message, renderContent, style }) {
|
|
|
5539
5627
|
},
|
|
5540
5628
|
cornerStyle
|
|
5541
5629
|
],
|
|
5542
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
5630
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_react_native43.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
5543
5631
|
isMergeCompleted ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react_native10.CheckCheck, { size: 16, color: theme.colors.success, style: { marginRight: theme.spacing.sm } }) : null,
|
|
5544
5632
|
isMergeApproved ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react_native10.GitMerge, { size: 16, color: theme.colors.text, style: { marginRight: theme.spacing.sm } }) : null,
|
|
5545
|
-
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
5633
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native43.View, { style: { flexShrink: 1, minWidth: 0 }, children: renderContent ? renderContent(message) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(MarkdownText, { markdown: message.content, variant: "chat", bodyColor }) })
|
|
5546
5634
|
] })
|
|
5547
5635
|
}
|
|
5548
5636
|
) });
|
|
@@ -5550,23 +5638,23 @@ function ChatMessageBubble({ message, renderContent, style }) {
|
|
|
5550
5638
|
|
|
5551
5639
|
// src/components/chat/TypingIndicator.tsx
|
|
5552
5640
|
var React32 = __toESM(require("react"));
|
|
5553
|
-
var
|
|
5641
|
+
var import_react_native44 = require("react-native");
|
|
5554
5642
|
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
5555
5643
|
function TypingIndicator({ style }) {
|
|
5556
5644
|
const theme = useTheme();
|
|
5557
5645
|
const dotColor = theme.colors.textSubtle;
|
|
5558
5646
|
const anims = React32.useMemo(
|
|
5559
|
-
() => [new
|
|
5647
|
+
() => [new import_react_native44.Animated.Value(0.3), new import_react_native44.Animated.Value(0.3), new import_react_native44.Animated.Value(0.3)],
|
|
5560
5648
|
[]
|
|
5561
5649
|
);
|
|
5562
5650
|
React32.useEffect(() => {
|
|
5563
5651
|
const loops = [];
|
|
5564
5652
|
anims.forEach((a, idx) => {
|
|
5565
|
-
const seq =
|
|
5566
|
-
|
|
5567
|
-
|
|
5653
|
+
const seq = import_react_native44.Animated.sequence([
|
|
5654
|
+
import_react_native44.Animated.timing(a, { toValue: 1, duration: 420, useNativeDriver: true, delay: idx * 140 }),
|
|
5655
|
+
import_react_native44.Animated.timing(a, { toValue: 0.3, duration: 420, useNativeDriver: true })
|
|
5568
5656
|
]);
|
|
5569
|
-
const loop =
|
|
5657
|
+
const loop = import_react_native44.Animated.loop(seq);
|
|
5570
5658
|
loops.push(loop);
|
|
5571
5659
|
loop.start();
|
|
5572
5660
|
});
|
|
@@ -5574,8 +5662,8 @@ function TypingIndicator({ style }) {
|
|
|
5574
5662
|
loops.forEach((l) => l.stop());
|
|
5575
5663
|
};
|
|
5576
5664
|
}, [anims]);
|
|
5577
|
-
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
5578
|
-
|
|
5665
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_react_native44.View, { style: [{ flexDirection: "row", alignItems: "center" }, style], children: anims.map((a, i) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
5666
|
+
import_react_native44.Animated.View,
|
|
5579
5667
|
{
|
|
5580
5668
|
style: {
|
|
5581
5669
|
width: 8,
|
|
@@ -5584,7 +5672,7 @@ function TypingIndicator({ style }) {
|
|
|
5584
5672
|
marginHorizontal: 3,
|
|
5585
5673
|
backgroundColor: dotColor,
|
|
5586
5674
|
opacity: a,
|
|
5587
|
-
transform: [{ translateY:
|
|
5675
|
+
transform: [{ translateY: import_react_native44.Animated.multiply(import_react_native44.Animated.subtract(a, 0.3), 2) }]
|
|
5588
5676
|
}
|
|
5589
5677
|
},
|
|
5590
5678
|
i
|
|
@@ -5608,19 +5696,19 @@ var ChatMessageList = React33.forwardRef(
|
|
|
5608
5696
|
const nearBottomRef = React33.useRef(true);
|
|
5609
5697
|
const initialScrollDoneRef = React33.useRef(false);
|
|
5610
5698
|
const lastMessageIdRef = React33.useRef(null);
|
|
5699
|
+
const data = React33.useMemo(() => {
|
|
5700
|
+
return [...messages].reverse();
|
|
5701
|
+
}, [messages]);
|
|
5611
5702
|
const scrollToBottom = React33.useCallback((options) => {
|
|
5612
5703
|
var _a;
|
|
5613
5704
|
const animated = (options == null ? void 0 : options.animated) ?? true;
|
|
5614
|
-
(_a = listRef.current) == null ? void 0 : _a.
|
|
5705
|
+
(_a = listRef.current) == null ? void 0 : _a.scrollToOffset({ offset: 0, animated });
|
|
5615
5706
|
}, []);
|
|
5616
5707
|
React33.useImperativeHandle(ref, () => ({ scrollToBottom }), [scrollToBottom]);
|
|
5617
5708
|
const handleScroll = React33.useCallback(
|
|
5618
5709
|
(e) => {
|
|
5619
5710
|
const { contentOffset, contentSize, layoutMeasurement } = e.nativeEvent;
|
|
5620
|
-
const distanceFromBottom = Math.max(
|
|
5621
|
-
contentSize.height - Math.max(bottomInset, 0) - (contentOffset.y + layoutMeasurement.height),
|
|
5622
|
-
0
|
|
5623
|
-
);
|
|
5711
|
+
const distanceFromBottom = Math.max(contentOffset.y - Math.max(bottomInset, 0), 0);
|
|
5624
5712
|
const isNear = distanceFromBottom <= nearBottomThreshold;
|
|
5625
5713
|
if (nearBottomRef.current !== isNear) {
|
|
5626
5714
|
nearBottomRef.current = isNear;
|
|
@@ -5629,15 +5717,6 @@ var ChatMessageList = React33.forwardRef(
|
|
|
5629
5717
|
},
|
|
5630
5718
|
[bottomInset, nearBottomThreshold, onNearBottomChange]
|
|
5631
5719
|
);
|
|
5632
|
-
React33.useEffect(() => {
|
|
5633
|
-
var _a;
|
|
5634
|
-
if (initialScrollDoneRef.current) return;
|
|
5635
|
-
if (messages.length === 0) return;
|
|
5636
|
-
initialScrollDoneRef.current = true;
|
|
5637
|
-
lastMessageIdRef.current = ((_a = messages[messages.length - 1]) == null ? void 0 : _a.id) ?? null;
|
|
5638
|
-
const id = requestAnimationFrame(() => scrollToBottom({ animated: false }));
|
|
5639
|
-
return () => cancelAnimationFrame(id);
|
|
5640
|
-
}, [messages, scrollToBottom]);
|
|
5641
5720
|
React33.useEffect(() => {
|
|
5642
5721
|
if (!initialScrollDoneRef.current) return;
|
|
5643
5722
|
const lastId = messages.length > 0 ? messages[messages.length - 1].id : null;
|
|
@@ -5655,33 +5734,37 @@ var ChatMessageList = React33.forwardRef(
|
|
|
5655
5734
|
}
|
|
5656
5735
|
return void 0;
|
|
5657
5736
|
}, [showTypingIndicator, scrollToBottom]);
|
|
5658
|
-
React33.useEffect(() => {
|
|
5659
|
-
if (!initialScrollDoneRef.current) return;
|
|
5660
|
-
if (!nearBottomRef.current) return;
|
|
5661
|
-
const id = requestAnimationFrame(() => scrollToBottom({ animated: false }));
|
|
5662
|
-
return () => cancelAnimationFrame(id);
|
|
5663
|
-
}, [bottomInset, scrollToBottom]);
|
|
5664
5737
|
return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
5665
5738
|
import_bottom_sheet5.BottomSheetFlatList,
|
|
5666
5739
|
{
|
|
5667
5740
|
ref: listRef,
|
|
5668
|
-
|
|
5741
|
+
inverted: true,
|
|
5742
|
+
data,
|
|
5669
5743
|
keyExtractor: (m) => m.id,
|
|
5744
|
+
keyboardShouldPersistTaps: "handled",
|
|
5670
5745
|
onScroll: handleScroll,
|
|
5671
5746
|
scrollEventThrottle: 16,
|
|
5672
5747
|
showsVerticalScrollIndicator: false,
|
|
5748
|
+
onContentSizeChange: () => {
|
|
5749
|
+
if (initialScrollDoneRef.current) return;
|
|
5750
|
+
initialScrollDoneRef.current = true;
|
|
5751
|
+
lastMessageIdRef.current = messages.length > 0 ? messages[messages.length - 1].id : null;
|
|
5752
|
+
nearBottomRef.current = true;
|
|
5753
|
+
onNearBottomChange == null ? void 0 : onNearBottomChange(true);
|
|
5754
|
+
requestAnimationFrame(() => scrollToBottom({ animated: false }));
|
|
5755
|
+
},
|
|
5673
5756
|
contentContainerStyle: [
|
|
5674
5757
|
{
|
|
5675
5758
|
paddingHorizontal: theme.spacing.lg,
|
|
5676
|
-
|
|
5677
|
-
paddingBottom: theme.spacing.sm
|
|
5759
|
+
paddingVertical: theme.spacing.sm
|
|
5678
5760
|
},
|
|
5679
5761
|
contentStyle
|
|
5680
5762
|
],
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5763
|
+
ItemSeparatorComponent: () => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_react_native45.View, { style: { height: theme.spacing.sm } }),
|
|
5764
|
+
renderItem: ({ item }) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ChatMessageBubble, { message: item, renderContent: renderMessageContent }),
|
|
5765
|
+
ListHeaderComponent: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_react_native45.View, { children: [
|
|
5766
|
+
showTypingIndicator ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_react_native45.View, { style: { marginTop: theme.spacing.sm, alignSelf: "flex-start", paddingHorizontal: theme.spacing.lg }, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(TypingIndicator, {}) }) : null,
|
|
5767
|
+
bottomInset > 0 ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_react_native45.View, { style: { height: bottomInset } }) : null
|
|
5685
5768
|
] })
|
|
5686
5769
|
}
|
|
5687
5770
|
);
|
|
@@ -5700,6 +5783,7 @@ function ChatPage({
|
|
|
5700
5783
|
composer,
|
|
5701
5784
|
overlay,
|
|
5702
5785
|
style,
|
|
5786
|
+
composerHorizontalPadding,
|
|
5703
5787
|
onNearBottomChange,
|
|
5704
5788
|
listRef
|
|
5705
5789
|
}) {
|
|
@@ -5707,21 +5791,16 @@ function ChatPage({
|
|
|
5707
5791
|
const insets = (0, import_react_native_safe_area_context4.useSafeAreaInsets)();
|
|
5708
5792
|
const [composerHeight, setComposerHeight] = React34.useState(0);
|
|
5709
5793
|
const [keyboardVisible, setKeyboardVisible] = React34.useState(false);
|
|
5710
|
-
const animatedKeyboard = (0, import_react_native_reanimated2.useAnimatedKeyboard)();
|
|
5711
5794
|
React34.useEffect(() => {
|
|
5712
|
-
if (
|
|
5713
|
-
const show =
|
|
5714
|
-
const hide =
|
|
5795
|
+
if (import_react_native46.Platform.OS !== "ios") return;
|
|
5796
|
+
const show = import_react_native46.Keyboard.addListener("keyboardWillShow", () => setKeyboardVisible(true));
|
|
5797
|
+
const hide = import_react_native46.Keyboard.addListener("keyboardWillHide", () => setKeyboardVisible(false));
|
|
5715
5798
|
return () => {
|
|
5716
5799
|
show.remove();
|
|
5717
5800
|
hide.remove();
|
|
5718
5801
|
};
|
|
5719
5802
|
}, []);
|
|
5720
|
-
const footerBottomPadding =
|
|
5721
|
-
const footerAnimatedStyle = (0, import_react_native_reanimated2.useAnimatedStyle)(() => {
|
|
5722
|
-
if (import_react_native45.Platform.OS !== "ios") return { paddingBottom: insets.bottom + 10 };
|
|
5723
|
-
return { paddingBottom: animatedKeyboard.height.value > 0 ? 0 : insets.bottom };
|
|
5724
|
-
});
|
|
5803
|
+
const footerBottomPadding = import_react_native46.Platform.OS === "ios" ? keyboardVisible ? 0 : insets.bottom : insets.bottom + 10;
|
|
5725
5804
|
const overlayBottom = composerHeight + footerBottomPadding + theme.spacing.lg;
|
|
5726
5805
|
const bottomInset = composerHeight + footerBottomPadding + theme.spacing.xl;
|
|
5727
5806
|
const resolvedOverlay = React34.useMemo(() => {
|
|
@@ -5733,36 +5812,42 @@ function ChatPage({
|
|
|
5733
5812
|
style: [prevStyle, { bottom: overlayBottom }]
|
|
5734
5813
|
});
|
|
5735
5814
|
}, [overlay, overlayBottom]);
|
|
5736
|
-
return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
|
|
5737
|
-
header ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
5738
|
-
topBanner ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
5739
|
-
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
|
|
5740
|
-
/* @__PURE__ */ (0, import_jsx_runtime47.
|
|
5741
|
-
|
|
5815
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native46.View, { style: [{ flex: 1 }, style], children: [
|
|
5816
|
+
header ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native46.View, { children: header }) : null,
|
|
5817
|
+
topBanner ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native46.View, { style: { paddingHorizontal: theme.spacing.lg, paddingTop: theme.spacing.sm }, children: topBanner }) : null,
|
|
5818
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native46.View, { style: { flex: 1 }, children: [
|
|
5819
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
|
|
5820
|
+
import_react_native46.View,
|
|
5742
5821
|
{
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5822
|
+
style: { flex: 1 },
|
|
5823
|
+
children: [
|
|
5824
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
5825
|
+
ChatMessageList,
|
|
5826
|
+
{
|
|
5827
|
+
ref: listRef,
|
|
5828
|
+
messages,
|
|
5829
|
+
showTypingIndicator,
|
|
5830
|
+
renderMessageContent,
|
|
5831
|
+
onNearBottomChange,
|
|
5832
|
+
bottomInset
|
|
5833
|
+
}
|
|
5834
|
+
),
|
|
5835
|
+
resolvedOverlay
|
|
5836
|
+
]
|
|
5749
5837
|
}
|
|
5750
5838
|
),
|
|
5751
|
-
resolvedOverlay,
|
|
5752
5839
|
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
5753
|
-
|
|
5840
|
+
import_react_native46.View,
|
|
5754
5841
|
{
|
|
5755
|
-
style:
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
footerAnimatedStyle
|
|
5765
|
-
],
|
|
5842
|
+
style: {
|
|
5843
|
+
position: "absolute",
|
|
5844
|
+
left: 0,
|
|
5845
|
+
right: 0,
|
|
5846
|
+
bottom: 0,
|
|
5847
|
+
paddingHorizontal: composerHorizontalPadding ?? theme.spacing.md,
|
|
5848
|
+
paddingTop: theme.spacing.sm,
|
|
5849
|
+
paddingBottom: footerBottomPadding
|
|
5850
|
+
},
|
|
5766
5851
|
children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
5767
5852
|
ChatComposer,
|
|
5768
5853
|
{
|
|
@@ -5779,24 +5864,24 @@ function ChatPage({
|
|
|
5779
5864
|
|
|
5780
5865
|
// src/components/chat/ScrollToBottomButton.tsx
|
|
5781
5866
|
var React35 = __toESM(require("react"));
|
|
5782
|
-
var
|
|
5783
|
-
var
|
|
5867
|
+
var import_react_native47 = require("react-native");
|
|
5868
|
+
var import_react_native_reanimated2 = __toESM(require("react-native-reanimated"));
|
|
5784
5869
|
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
5785
5870
|
function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
5786
5871
|
const theme = useTheme();
|
|
5787
|
-
const progress = (0,
|
|
5872
|
+
const progress = (0, import_react_native_reanimated2.useSharedValue)(visible ? 1 : 0);
|
|
5788
5873
|
const [pressed, setPressed] = React35.useState(false);
|
|
5789
5874
|
React35.useEffect(() => {
|
|
5790
|
-
progress.value = (0,
|
|
5875
|
+
progress.value = (0, import_react_native_reanimated2.withTiming)(visible ? 1 : 0, { duration: 200, easing: import_react_native_reanimated2.Easing.out(import_react_native_reanimated2.Easing.ease) });
|
|
5791
5876
|
}, [progress, visible]);
|
|
5792
|
-
const animStyle = (0,
|
|
5877
|
+
const animStyle = (0, import_react_native_reanimated2.useAnimatedStyle)(() => ({
|
|
5793
5878
|
opacity: progress.value,
|
|
5794
5879
|
transform: [{ translateY: (1 - progress.value) * 20 }]
|
|
5795
5880
|
}));
|
|
5796
5881
|
const bg = theme.scheme === "dark" ? "rgba(39,39,42,0.9)" : "rgba(244,244,245,0.95)";
|
|
5797
5882
|
const border = theme.scheme === "dark" ? withAlpha("#FFFFFF", 0.12) : withAlpha("#000000", 0.08);
|
|
5798
5883
|
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
5799
|
-
|
|
5884
|
+
import_react_native_reanimated2.default.View,
|
|
5800
5885
|
{
|
|
5801
5886
|
pointerEvents: visible ? "auto" : "none",
|
|
5802
5887
|
style: [
|
|
@@ -5810,7 +5895,7 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
|
5810
5895
|
animStyle
|
|
5811
5896
|
],
|
|
5812
5897
|
children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
5813
|
-
|
|
5898
|
+
import_react_native47.View,
|
|
5814
5899
|
{
|
|
5815
5900
|
style: {
|
|
5816
5901
|
width: 44,
|
|
@@ -5829,7 +5914,7 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
|
5829
5914
|
opacity: pressed ? 0.85 : 1
|
|
5830
5915
|
},
|
|
5831
5916
|
children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
5832
|
-
|
|
5917
|
+
import_react_native47.Pressable,
|
|
5833
5918
|
{
|
|
5834
5919
|
onPress,
|
|
5835
5920
|
onPressIn: () => setPressed(true),
|
|
@@ -5846,10 +5931,10 @@ function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
|
5846
5931
|
}
|
|
5847
5932
|
|
|
5848
5933
|
// src/components/chat/ChatHeader.tsx
|
|
5849
|
-
var
|
|
5934
|
+
var import_react_native48 = require("react-native");
|
|
5850
5935
|
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
5851
5936
|
function ChatHeader({ left, right, center, style }) {
|
|
5852
|
-
const flattenedStyle =
|
|
5937
|
+
const flattenedStyle = import_react_native48.StyleSheet.flatten([
|
|
5853
5938
|
{
|
|
5854
5939
|
paddingTop: 0
|
|
5855
5940
|
},
|
|
@@ -5867,7 +5952,7 @@ function ChatHeader({ left, right, center, style }) {
|
|
|
5867
5952
|
}
|
|
5868
5953
|
|
|
5869
5954
|
// src/components/chat/ForkNoticeBanner.tsx
|
|
5870
|
-
var
|
|
5955
|
+
var import_react_native49 = require("react-native");
|
|
5871
5956
|
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
5872
5957
|
function ForkNoticeBanner({ isOwner = true, title, description, style }) {
|
|
5873
5958
|
const theme = useTheme();
|
|
@@ -5888,7 +5973,7 @@ function ForkNoticeBanner({ isOwner = true, title, description, style }) {
|
|
|
5888
5973
|
},
|
|
5889
5974
|
style
|
|
5890
5975
|
],
|
|
5891
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
|
|
5976
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_react_native49.View, { style: { minWidth: 0 }, children: [
|
|
5892
5977
|
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
5893
5978
|
Text,
|
|
5894
5979
|
{
|
|
@@ -5964,11 +6049,11 @@ function ChatPanel({
|
|
|
5964
6049
|
const header = /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
5965
6050
|
ChatHeader,
|
|
5966
6051
|
{
|
|
5967
|
-
left: /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
|
|
6052
|
+
left: /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_react_native50.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
5968
6053
|
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(StudioSheetHeaderIconButton, { onPress: onBack, accessibilityLabel: "Back", style: { marginRight: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(IconBack, { size: 20, colorToken: "floatingContent" }) }),
|
|
5969
6054
|
onNavigateHome ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(StudioSheetHeaderIconButton, { onPress: onNavigateHome, accessibilityLabel: "Home", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(IconHome, { size: 20, colorToken: "floatingContent" }) }) : null
|
|
5970
6055
|
] }),
|
|
5971
|
-
right: /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
|
|
6056
|
+
right: /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_react_native50.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
5972
6057
|
onStartDraw ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(StudioSheetHeaderIconButton, { onPress: onStartDraw, accessibilityLabel: "Draw", intent: "danger", style: { marginRight: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(IconDraw, { size: 20, colorToken: "onDanger" }) }) : null,
|
|
5973
6058
|
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(StudioSheetHeaderIconButton, { onPress: onClose, accessibilityLabel: "Close", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(IconClose, { size: 20, colorToken: "floatingContent" }) })
|
|
5974
6059
|
] }),
|
|
@@ -5984,12 +6069,12 @@ function ChatPanel({
|
|
|
5984
6069
|
) : null;
|
|
5985
6070
|
const showMessagesLoading = Boolean(loading) && messages.length === 0 || forking;
|
|
5986
6071
|
if (showMessagesLoading) {
|
|
5987
|
-
return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
|
|
5988
|
-
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
5989
|
-
topBanner ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
5990
|
-
/* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
|
|
5991
|
-
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
5992
|
-
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
6072
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_react_native50.View, { style: { flex: 1 }, children: [
|
|
6073
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native50.View, { children: header }),
|
|
6074
|
+
topBanner ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native50.View, { style: { paddingHorizontal: 16, paddingTop: 8 }, children: topBanner }) : null,
|
|
6075
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_react_native50.View, { style: { flex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 24, paddingVertical: 12 }, children: [
|
|
6076
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native50.ActivityIndicator, {}),
|
|
6077
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native50.View, { style: { height: 12 } }),
|
|
5993
6078
|
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Text, { variant: "bodyMuted", children: forking ? "Creating your copy\u2026" : "Loading messages\u2026" })
|
|
5994
6079
|
] })
|
|
5995
6080
|
] });
|
|
@@ -6001,6 +6086,7 @@ function ChatPanel({
|
|
|
6001
6086
|
messages,
|
|
6002
6087
|
showTypingIndicator,
|
|
6003
6088
|
topBanner,
|
|
6089
|
+
composerHorizontalPadding: 0,
|
|
6004
6090
|
listRef,
|
|
6005
6091
|
onNearBottomChange: setNearBottom,
|
|
6006
6092
|
overlay: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
@@ -6031,10 +6117,10 @@ function ChatPanel({
|
|
|
6031
6117
|
|
|
6032
6118
|
// src/components/dialogs/ConfirmMergeRequestDialog.tsx
|
|
6033
6119
|
var React37 = __toESM(require("react"));
|
|
6034
|
-
var
|
|
6120
|
+
var import_react_native52 = require("react-native");
|
|
6035
6121
|
|
|
6036
6122
|
// src/components/primitives/Modal.tsx
|
|
6037
|
-
var
|
|
6123
|
+
var import_react_native51 = require("react-native");
|
|
6038
6124
|
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
6039
6125
|
function Modal({
|
|
6040
6126
|
visible,
|
|
@@ -6045,15 +6131,15 @@ function Modal({
|
|
|
6045
6131
|
}) {
|
|
6046
6132
|
const theme = useTheme();
|
|
6047
6133
|
return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
6048
|
-
|
|
6134
|
+
import_react_native51.Modal,
|
|
6049
6135
|
{
|
|
6050
6136
|
visible,
|
|
6051
6137
|
transparent: true,
|
|
6052
6138
|
animationType: "fade",
|
|
6053
6139
|
onRequestClose,
|
|
6054
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
|
|
6140
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_react_native51.View, { style: { flex: 1, backgroundColor: theme.colors.backdrop, justifyContent: "center", padding: theme.spacing.lg }, children: [
|
|
6055
6141
|
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
6056
|
-
|
|
6142
|
+
import_react_native51.Pressable,
|
|
6057
6143
|
{
|
|
6058
6144
|
accessibilityRole: "button",
|
|
6059
6145
|
onPress: dismissOnBackdropPress ? onRequestClose : void 0,
|
|
@@ -6108,7 +6194,7 @@ function ConfirmMergeRequestDialog({
|
|
|
6108
6194
|
backgroundColor: theme.colors.background
|
|
6109
6195
|
},
|
|
6110
6196
|
children: [
|
|
6111
|
-
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
6197
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_react_native52.View, { children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
6112
6198
|
Text,
|
|
6113
6199
|
{
|
|
6114
6200
|
style: {
|
|
@@ -6120,9 +6206,9 @@ function ConfirmMergeRequestDialog({
|
|
|
6120
6206
|
children: "Are you sure you want to approve this merge request?"
|
|
6121
6207
|
}
|
|
6122
6208
|
) }),
|
|
6123
|
-
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
6209
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_react_native52.View, { style: { marginTop: 16 }, children: [
|
|
6124
6210
|
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
6125
|
-
|
|
6211
|
+
import_react_native52.View,
|
|
6126
6212
|
{
|
|
6127
6213
|
style: [
|
|
6128
6214
|
fullWidthButtonBase,
|
|
@@ -6132,7 +6218,7 @@ function ConfirmMergeRequestDialog({
|
|
|
6132
6218
|
}
|
|
6133
6219
|
],
|
|
6134
6220
|
children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
6135
|
-
|
|
6221
|
+
import_react_native52.Pressable,
|
|
6136
6222
|
{
|
|
6137
6223
|
accessibilityRole: "button",
|
|
6138
6224
|
accessibilityLabel: "Approve Merge",
|
|
@@ -6144,9 +6230,9 @@ function ConfirmMergeRequestDialog({
|
|
|
6144
6230
|
)
|
|
6145
6231
|
}
|
|
6146
6232
|
),
|
|
6147
|
-
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
6233
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_react_native52.View, { style: { height: 8 } }),
|
|
6148
6234
|
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
6149
|
-
|
|
6235
|
+
import_react_native52.View,
|
|
6150
6236
|
{
|
|
6151
6237
|
style: [
|
|
6152
6238
|
fullWidthButtonBase,
|
|
@@ -6158,7 +6244,7 @@ function ConfirmMergeRequestDialog({
|
|
|
6158
6244
|
}
|
|
6159
6245
|
],
|
|
6160
6246
|
children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
6161
|
-
|
|
6247
|
+
import_react_native52.Pressable,
|
|
6162
6248
|
{
|
|
6163
6249
|
accessibilityRole: "button",
|
|
6164
6250
|
accessibilityLabel: isBuilding ? "Preparing\u2026" : "Test edits first",
|
|
@@ -6170,9 +6256,9 @@ function ConfirmMergeRequestDialog({
|
|
|
6170
6256
|
)
|
|
6171
6257
|
}
|
|
6172
6258
|
),
|
|
6173
|
-
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
6259
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_react_native52.View, { style: { height: 8 } }),
|
|
6174
6260
|
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
6175
|
-
|
|
6261
|
+
import_react_native52.View,
|
|
6176
6262
|
{
|
|
6177
6263
|
style: [
|
|
6178
6264
|
fullWidthButtonBase,
|
|
@@ -6183,7 +6269,7 @@ function ConfirmMergeRequestDialog({
|
|
|
6183
6269
|
}
|
|
6184
6270
|
],
|
|
6185
6271
|
children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
6186
|
-
|
|
6272
|
+
import_react_native52.Pressable,
|
|
6187
6273
|
{
|
|
6188
6274
|
accessibilityRole: "button",
|
|
6189
6275
|
accessibilityLabel: "Cancel",
|
|
@@ -6233,6 +6319,92 @@ function ConfirmMergeFlow({
|
|
|
6233
6319
|
);
|
|
6234
6320
|
}
|
|
6235
6321
|
|
|
6322
|
+
// src/studio/hooks/useOptimisticChatMessages.ts
|
|
6323
|
+
var React38 = __toESM(require("react"));
|
|
6324
|
+
function makeOptimisticId() {
|
|
6325
|
+
return `optimistic:${Date.now().toString(36)}:${Math.random().toString(36).slice(2, 10)}`;
|
|
6326
|
+
}
|
|
6327
|
+
function toEpochMs(createdAt) {
|
|
6328
|
+
if (createdAt == null) return 0;
|
|
6329
|
+
if (typeof createdAt === "number") return createdAt;
|
|
6330
|
+
if (createdAt instanceof Date) return createdAt.getTime();
|
|
6331
|
+
const t = Date.parse(String(createdAt));
|
|
6332
|
+
return Number.isFinite(t) ? t : 0;
|
|
6333
|
+
}
|
|
6334
|
+
function isOptimisticResolvedByServer(chatMessages, o) {
|
|
6335
|
+
if (o.failed) return false;
|
|
6336
|
+
const normalize = (s) => s.trim();
|
|
6337
|
+
let startIndex = -1;
|
|
6338
|
+
if (o.baseServerLastId) {
|
|
6339
|
+
startIndex = chatMessages.findIndex((m) => m.id === o.baseServerLastId);
|
|
6340
|
+
}
|
|
6341
|
+
const candidates = startIndex >= 0 ? chatMessages.slice(startIndex + 1) : chatMessages;
|
|
6342
|
+
const target = normalize(o.content);
|
|
6343
|
+
for (const m of candidates) {
|
|
6344
|
+
if (m.author !== "human") continue;
|
|
6345
|
+
if (normalize(m.content) !== target) continue;
|
|
6346
|
+
const serverMs = toEpochMs(m.createdAt);
|
|
6347
|
+
const optimisticMs = Date.parse(o.createdAtIso);
|
|
6348
|
+
if (Number.isFinite(optimisticMs) && optimisticMs > 0 && serverMs > 0) {
|
|
6349
|
+
if (serverMs + 12e4 < optimisticMs) continue;
|
|
6350
|
+
}
|
|
6351
|
+
return true;
|
|
6352
|
+
}
|
|
6353
|
+
return false;
|
|
6354
|
+
}
|
|
6355
|
+
function useOptimisticChatMessages({
|
|
6356
|
+
threadId,
|
|
6357
|
+
shouldForkOnEdit,
|
|
6358
|
+
chatMessages,
|
|
6359
|
+
onSendChat
|
|
6360
|
+
}) {
|
|
6361
|
+
const [optimisticChat, setOptimisticChat] = React38.useState([]);
|
|
6362
|
+
React38.useEffect(() => {
|
|
6363
|
+
setOptimisticChat([]);
|
|
6364
|
+
}, [threadId]);
|
|
6365
|
+
const messages = React38.useMemo(() => {
|
|
6366
|
+
if (!optimisticChat || optimisticChat.length === 0) return chatMessages;
|
|
6367
|
+
const unresolved = optimisticChat.filter((o) => !isOptimisticResolvedByServer(chatMessages, o));
|
|
6368
|
+
if (unresolved.length === 0) return chatMessages;
|
|
6369
|
+
const optimisticAsChat = unresolved.map((o) => ({
|
|
6370
|
+
id: o.id,
|
|
6371
|
+
author: "human",
|
|
6372
|
+
content: o.content,
|
|
6373
|
+
createdAt: o.createdAtIso,
|
|
6374
|
+
kind: "optimistic",
|
|
6375
|
+
meta: o.failed ? { kind: "optimistic", event: "send.failed", status: "error" } : { kind: "optimistic", event: "send.pending", status: "info" }
|
|
6376
|
+
}));
|
|
6377
|
+
const merged = [...chatMessages, ...optimisticAsChat];
|
|
6378
|
+
merged.sort((a, b) => String(a.createdAt).localeCompare(String(b.createdAt)));
|
|
6379
|
+
return merged;
|
|
6380
|
+
}, [chatMessages, optimisticChat]);
|
|
6381
|
+
React38.useEffect(() => {
|
|
6382
|
+
if (optimisticChat.length === 0) return;
|
|
6383
|
+
setOptimisticChat((prev) => {
|
|
6384
|
+
if (prev.length === 0) return prev;
|
|
6385
|
+
const next = prev.filter((o) => !isOptimisticResolvedByServer(chatMessages, o) || o.failed);
|
|
6386
|
+
return next.length === prev.length ? prev : next;
|
|
6387
|
+
});
|
|
6388
|
+
}, [chatMessages, optimisticChat.length]);
|
|
6389
|
+
const onSend = React38.useCallback(
|
|
6390
|
+
async (text, attachments) => {
|
|
6391
|
+
if (shouldForkOnEdit) {
|
|
6392
|
+
await onSendChat(text, attachments);
|
|
6393
|
+
return;
|
|
6394
|
+
}
|
|
6395
|
+
const createdAtIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
6396
|
+
const baseServerLastId = chatMessages.length > 0 ? chatMessages[chatMessages.length - 1].id : null;
|
|
6397
|
+
const id = makeOptimisticId();
|
|
6398
|
+
setOptimisticChat((prev) => [...prev, { id, content: text, createdAtIso, baseServerLastId, failed: false }]);
|
|
6399
|
+
void Promise.resolve(onSendChat(text, attachments)).catch(() => {
|
|
6400
|
+
setOptimisticChat((prev) => prev.map((m) => m.id === id ? { ...m, failed: true } : m));
|
|
6401
|
+
});
|
|
6402
|
+
},
|
|
6403
|
+
[chatMessages, onSendChat, shouldForkOnEdit]
|
|
6404
|
+
);
|
|
6405
|
+
return { messages, onSend };
|
|
6406
|
+
}
|
|
6407
|
+
|
|
6236
6408
|
// src/studio/ui/StudioOverlay.tsx
|
|
6237
6409
|
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
6238
6410
|
function StudioOverlay({
|
|
@@ -6264,30 +6436,40 @@ function StudioOverlay({
|
|
|
6264
6436
|
onNavigateHome
|
|
6265
6437
|
}) {
|
|
6266
6438
|
const theme = useTheme();
|
|
6267
|
-
const { width } = (0,
|
|
6268
|
-
const [sheetOpen, setSheetOpen] =
|
|
6269
|
-
const [activePage, setActivePage] =
|
|
6270
|
-
const [drawing, setDrawing] =
|
|
6271
|
-
const [chatAttachments, setChatAttachments] =
|
|
6272
|
-
const [commentsAppId, setCommentsAppId] =
|
|
6273
|
-
const [commentsCount, setCommentsCount] =
|
|
6274
|
-
const
|
|
6275
|
-
const
|
|
6439
|
+
const { width } = (0, import_react_native53.useWindowDimensions)();
|
|
6440
|
+
const [sheetOpen, setSheetOpen] = React39.useState(false);
|
|
6441
|
+
const [activePage, setActivePage] = React39.useState("preview");
|
|
6442
|
+
const [drawing, setDrawing] = React39.useState(false);
|
|
6443
|
+
const [chatAttachments, setChatAttachments] = React39.useState([]);
|
|
6444
|
+
const [commentsAppId, setCommentsAppId] = React39.useState(null);
|
|
6445
|
+
const [commentsCount, setCommentsCount] = React39.useState(null);
|
|
6446
|
+
const threadId = (app == null ? void 0 : app.threadId) ?? null;
|
|
6447
|
+
const optimistic = useOptimisticChatMessages({
|
|
6448
|
+
threadId,
|
|
6449
|
+
shouldForkOnEdit,
|
|
6450
|
+
chatMessages,
|
|
6451
|
+
onSendChat
|
|
6452
|
+
});
|
|
6453
|
+
const [confirmMrId, setConfirmMrId] = React39.useState(null);
|
|
6454
|
+
const confirmMr = React39.useMemo(
|
|
6276
6455
|
() => confirmMrId ? incomingMergeRequests.find((m) => m.id === confirmMrId) ?? null : null,
|
|
6277
6456
|
[confirmMrId, incomingMergeRequests]
|
|
6278
6457
|
);
|
|
6279
|
-
const
|
|
6280
|
-
setSheetOpen(
|
|
6281
|
-
|
|
6458
|
+
const handleSheetOpenChange = React39.useCallback((open) => {
|
|
6459
|
+
setSheetOpen(open);
|
|
6460
|
+
if (!open) import_react_native53.Keyboard.dismiss();
|
|
6282
6461
|
}, []);
|
|
6283
|
-
const
|
|
6284
|
-
|
|
6462
|
+
const closeSheet = React39.useCallback(() => {
|
|
6463
|
+
handleSheetOpenChange(false);
|
|
6464
|
+
}, [handleSheetOpenChange]);
|
|
6465
|
+
const openSheet = React39.useCallback(() => setSheetOpen(true), []);
|
|
6466
|
+
const goToChat = React39.useCallback(() => {
|
|
6285
6467
|
setActivePage("chat");
|
|
6286
6468
|
openSheet();
|
|
6287
6469
|
}, [openSheet]);
|
|
6288
|
-
const backToPreview =
|
|
6289
|
-
if (
|
|
6290
|
-
|
|
6470
|
+
const backToPreview = React39.useCallback(() => {
|
|
6471
|
+
if (import_react_native53.Platform.OS !== "ios") {
|
|
6472
|
+
import_react_native53.Keyboard.dismiss();
|
|
6291
6473
|
setActivePage("preview");
|
|
6292
6474
|
return;
|
|
6293
6475
|
}
|
|
@@ -6299,15 +6481,15 @@ function StudioOverlay({
|
|
|
6299
6481
|
clearTimeout(t);
|
|
6300
6482
|
setActivePage("preview");
|
|
6301
6483
|
};
|
|
6302
|
-
const sub =
|
|
6484
|
+
const sub = import_react_native53.Keyboard.addListener("keyboardDidHide", finalize);
|
|
6303
6485
|
const t = setTimeout(finalize, 350);
|
|
6304
|
-
|
|
6486
|
+
import_react_native53.Keyboard.dismiss();
|
|
6305
6487
|
}, []);
|
|
6306
|
-
const startDraw =
|
|
6488
|
+
const startDraw = React39.useCallback(() => {
|
|
6307
6489
|
setDrawing(true);
|
|
6308
6490
|
closeSheet();
|
|
6309
6491
|
}, [closeSheet]);
|
|
6310
|
-
const handleDrawCapture =
|
|
6492
|
+
const handleDrawCapture = React39.useCallback(
|
|
6311
6493
|
(dataUrl) => {
|
|
6312
6494
|
setChatAttachments((prev) => [...prev, dataUrl]);
|
|
6313
6495
|
setDrawing(false);
|
|
@@ -6316,7 +6498,7 @@ function StudioOverlay({
|
|
|
6316
6498
|
},
|
|
6317
6499
|
[openSheet]
|
|
6318
6500
|
);
|
|
6319
|
-
const toggleSheet =
|
|
6501
|
+
const toggleSheet = React39.useCallback(async () => {
|
|
6320
6502
|
if (!sheetOpen) {
|
|
6321
6503
|
const shouldExitTest = Boolean(testingMrId) || isTesting;
|
|
6322
6504
|
if (shouldExitTest) {
|
|
@@ -6328,7 +6510,7 @@ function StudioOverlay({
|
|
|
6328
6510
|
closeSheet();
|
|
6329
6511
|
}
|
|
6330
6512
|
}, [closeSheet, isTesting, onRestoreBase, sheetOpen, testingMrId]);
|
|
6331
|
-
const handleTestMr =
|
|
6513
|
+
const handleTestMr = React39.useCallback(
|
|
6332
6514
|
async (mr) => {
|
|
6333
6515
|
if (!onTestMr) return;
|
|
6334
6516
|
await onTestMr(mr);
|
|
@@ -6338,7 +6520,7 @@ function StudioOverlay({
|
|
|
6338
6520
|
);
|
|
6339
6521
|
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_jsx_runtime55.Fragment, { children: [
|
|
6340
6522
|
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(EdgeGlowFrame, { visible: isTesting, role: "accent", thickness: 40, intensity: 1 }),
|
|
6341
|
-
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(StudioBottomSheet, { open: sheetOpen, onOpenChange:
|
|
6523
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(StudioBottomSheet, { open: sheetOpen, onOpenChange: handleSheetOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
6342
6524
|
StudioSheetPager,
|
|
6343
6525
|
{
|
|
6344
6526
|
activePage,
|
|
@@ -6372,7 +6554,7 @@ function StudioOverlay({
|
|
|
6372
6554
|
chat: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
6373
6555
|
ChatPanel,
|
|
6374
6556
|
{
|
|
6375
|
-
messages:
|
|
6557
|
+
messages: optimistic.messages,
|
|
6376
6558
|
showTypingIndicator: chatShowTypingIndicator,
|
|
6377
6559
|
loading: chatLoading,
|
|
6378
6560
|
sendDisabled: chatSendDisabled,
|
|
@@ -6387,7 +6569,7 @@ function StudioOverlay({
|
|
|
6387
6569
|
onClose: closeSheet,
|
|
6388
6570
|
onNavigateHome,
|
|
6389
6571
|
onStartDraw: startDraw,
|
|
6390
|
-
onSend:
|
|
6572
|
+
onSend: optimistic.onSend
|
|
6391
6573
|
}
|
|
6392
6574
|
)
|
|
6393
6575
|
}
|
|
@@ -6400,7 +6582,7 @@ function StudioOverlay({
|
|
|
6400
6582
|
badgeCount: incomingMergeRequests.length,
|
|
6401
6583
|
onPress: toggleSheet,
|
|
6402
6584
|
isLoading: (app == null ? void 0 : app.status) === "editing",
|
|
6403
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
6585
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_react_native53.View, { style: { width: 28, height: 28, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(MergeIcon, { width: 24, height: 24, color: theme.colors.floatingContent }) })
|
|
6404
6586
|
}
|
|
6405
6587
|
),
|
|
6406
6588
|
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
@@ -6446,16 +6628,16 @@ function ComergeStudio({
|
|
|
6446
6628
|
onNavigateHome,
|
|
6447
6629
|
style
|
|
6448
6630
|
}) {
|
|
6449
|
-
const [activeAppId, setActiveAppId] =
|
|
6450
|
-
const [runtimeAppId, setRuntimeAppId] =
|
|
6451
|
-
const [pendingRuntimeTargetAppId, setPendingRuntimeTargetAppId] =
|
|
6452
|
-
const platform =
|
|
6453
|
-
|
|
6631
|
+
const [activeAppId, setActiveAppId] = React40.useState(appId);
|
|
6632
|
+
const [runtimeAppId, setRuntimeAppId] = React40.useState(appId);
|
|
6633
|
+
const [pendingRuntimeTargetAppId, setPendingRuntimeTargetAppId] = React40.useState(null);
|
|
6634
|
+
const platform = React40.useMemo(() => import_react_native54.Platform.OS === "ios" ? "ios" : "android", []);
|
|
6635
|
+
React40.useEffect(() => {
|
|
6454
6636
|
setActiveAppId(appId);
|
|
6455
6637
|
setRuntimeAppId(appId);
|
|
6456
6638
|
setPendingRuntimeTargetAppId(null);
|
|
6457
6639
|
}, [appId]);
|
|
6458
|
-
const captureTargetRef =
|
|
6640
|
+
const captureTargetRef = React40.useRef(null);
|
|
6459
6641
|
return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(StudioBootstrap, { apiKey, children: ({ userId }) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_bottom_sheet6.BottomSheetModalProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
6460
6642
|
ComergeStudioInner,
|
|
6461
6643
|
{
|
|
@@ -6491,11 +6673,11 @@ function ComergeStudioInner({
|
|
|
6491
6673
|
const { app, loading: appLoading } = useApp(activeAppId);
|
|
6492
6674
|
const { app: runtimeAppFromHook } = useApp(runtimeAppId, { enabled: runtimeAppId !== activeAppId });
|
|
6493
6675
|
const runtimeApp = runtimeAppId === activeAppId ? app : runtimeAppFromHook;
|
|
6494
|
-
const sawEditingOnPendingTargetRef =
|
|
6495
|
-
|
|
6676
|
+
const sawEditingOnPendingTargetRef = React40.useRef(false);
|
|
6677
|
+
React40.useEffect(() => {
|
|
6496
6678
|
sawEditingOnPendingTargetRef.current = false;
|
|
6497
6679
|
}, [pendingRuntimeTargetAppId]);
|
|
6498
|
-
|
|
6680
|
+
React40.useEffect(() => {
|
|
6499
6681
|
if (!pendingRuntimeTargetAppId) return;
|
|
6500
6682
|
if (activeAppId !== pendingRuntimeTargetAppId) return;
|
|
6501
6683
|
if ((app == null ? void 0 : app.status) === "editing") {
|
|
@@ -6512,13 +6694,38 @@ function ComergeStudioInner({
|
|
|
6512
6694
|
platform,
|
|
6513
6695
|
canRequestLatest: (runtimeApp == null ? void 0 : runtimeApp.status) === "ready"
|
|
6514
6696
|
});
|
|
6697
|
+
const sawEditingOnActiveAppRef = React40.useRef(false);
|
|
6698
|
+
const [showPostEditPreparing, setShowPostEditPreparing] = React40.useState(false);
|
|
6699
|
+
React40.useEffect(() => {
|
|
6700
|
+
sawEditingOnActiveAppRef.current = false;
|
|
6701
|
+
setShowPostEditPreparing(false);
|
|
6702
|
+
}, [activeAppId]);
|
|
6703
|
+
React40.useEffect(() => {
|
|
6704
|
+
if (!(app == null ? void 0 : app.id)) return;
|
|
6705
|
+
if (app.status === "editing") {
|
|
6706
|
+
sawEditingOnActiveAppRef.current = true;
|
|
6707
|
+
setShowPostEditPreparing(false);
|
|
6708
|
+
return;
|
|
6709
|
+
}
|
|
6710
|
+
if (app.status === "ready" && sawEditingOnActiveAppRef.current) {
|
|
6711
|
+
setShowPostEditPreparing(true);
|
|
6712
|
+
sawEditingOnActiveAppRef.current = false;
|
|
6713
|
+
}
|
|
6714
|
+
}, [app == null ? void 0 : app.id, app == null ? void 0 : app.status]);
|
|
6715
|
+
React40.useEffect(() => {
|
|
6716
|
+
if (!showPostEditPreparing) return;
|
|
6717
|
+
const stillProcessingBaseBundle = bundle.loading && bundle.loadingMode === "base" && !bundle.isTesting;
|
|
6718
|
+
if (!stillProcessingBaseBundle) {
|
|
6719
|
+
setShowPostEditPreparing(false);
|
|
6720
|
+
}
|
|
6721
|
+
}, [showPostEditPreparing, bundle.loading, bundle.loadingMode, bundle.isTesting]);
|
|
6515
6722
|
const threadId = (app == null ? void 0 : app.threadId) ?? "";
|
|
6516
6723
|
const thread = useThreadMessages(threadId);
|
|
6517
6724
|
const mergeRequests = useMergeRequests({ appId: activeAppId });
|
|
6518
|
-
const hasOpenOutgoingMr =
|
|
6725
|
+
const hasOpenOutgoingMr = React40.useMemo(() => {
|
|
6519
6726
|
return mergeRequests.lists.outgoing.some((mr) => mr.status === "open");
|
|
6520
6727
|
}, [mergeRequests.lists.outgoing]);
|
|
6521
|
-
const incomingReviewMrs =
|
|
6728
|
+
const incomingReviewMrs = React40.useMemo(() => {
|
|
6522
6729
|
if (!userId) return mergeRequests.lists.incoming;
|
|
6523
6730
|
return mergeRequests.lists.incoming.filter((mr) => mr.createdBy !== userId);
|
|
6524
6731
|
}, [mergeRequests.lists.incoming, userId]);
|
|
@@ -6540,17 +6747,25 @@ function ComergeStudioInner({
|
|
|
6540
6747
|
uploadAttachments: uploader.uploadBase64Images
|
|
6541
6748
|
});
|
|
6542
6749
|
const chatSendDisabled = hasNoOutcomeAfterLastHuman(thread.raw);
|
|
6543
|
-
const [processingMrId, setProcessingMrId] =
|
|
6544
|
-
const [testingMrId, setTestingMrId] =
|
|
6545
|
-
const chatShowTypingIndicator =
|
|
6750
|
+
const [processingMrId, setProcessingMrId] = React40.useState(null);
|
|
6751
|
+
const [testingMrId, setTestingMrId] = React40.useState(null);
|
|
6752
|
+
const chatShowTypingIndicator = React40.useMemo(() => {
|
|
6546
6753
|
var _a;
|
|
6547
6754
|
if (!thread.raw || thread.raw.length === 0) return false;
|
|
6548
6755
|
const last = thread.raw[thread.raw.length - 1];
|
|
6549
6756
|
const payloadType = typeof ((_a = last.payload) == null ? void 0 : _a.type) === "string" ? String(last.payload.type) : void 0;
|
|
6550
6757
|
return payloadType !== "outcome";
|
|
6551
6758
|
}, [thread.raw]);
|
|
6552
|
-
return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
6553
|
-
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
6759
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_react_native54.View, { style: [{ flex: 1 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_react_native54.View, { ref: captureTargetRef, style: { flex: 1 }, collapsable: false, children: [
|
|
6760
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
6761
|
+
RuntimeRenderer,
|
|
6762
|
+
{
|
|
6763
|
+
appKey,
|
|
6764
|
+
bundlePath: bundle.bundlePath,
|
|
6765
|
+
forcePreparing: showPostEditPreparing,
|
|
6766
|
+
renderToken: bundle.renderToken
|
|
6767
|
+
}
|
|
6768
|
+
),
|
|
6554
6769
|
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
6555
6770
|
StudioOverlay,
|
|
6556
6771
|
{
|