@comergehq/studio 0.1.12 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +20 -3
- package/dist/index.d.ts +20 -3
- package/dist/index.js +333 -297
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +339 -303
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
- package/src/components/{floating-draggable-button/FloatingDraggableButton.tsx → bubble/Bubble.tsx} +3 -3
- package/src/components/{floating-draggable-button → bubble}/constants.ts +2 -2
- package/src/components/bubble/index.ts +4 -0
- package/src/components/{floating-draggable-button → bubble}/types.ts +3 -3
- package/src/components/index.ts +2 -2
- package/src/core/services/http/baseUrl.ts +1 -1
- package/src/core/services/http/public.ts +7 -7
- package/src/studio/ComergeStudio.tsx +17 -9
- package/src/studio/bootstrap/StudioBootstrap.tsx +2 -2
- package/src/studio/bootstrap/useStudioBootstrap.ts +7 -7
- package/src/studio/hooks/useBundleManager.ts +55 -2
- package/src/studio/ui/RuntimeRenderer.tsx +24 -1
- package/src/studio/ui/StudioOverlay.tsx +6 -6
- package/src/components/floating-draggable-button/index.ts +0 -4
package/dist/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
// src/studio/ComergeStudio.tsx
|
|
9
|
-
import * as
|
|
9
|
+
import * as React43 from "react";
|
|
10
10
|
import { Platform as RNPlatform, View as View45 } from "react-native";
|
|
11
11
|
import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";
|
|
12
12
|
|
|
@@ -188,11 +188,11 @@ import * as React from "react";
|
|
|
188
188
|
import axios from "axios";
|
|
189
189
|
|
|
190
190
|
// src/core/services/http/baseUrl.ts
|
|
191
|
-
var BASE_URL = "https://comerge.ai";
|
|
191
|
+
var BASE_URL = "https://api.comerge.ai";
|
|
192
192
|
|
|
193
193
|
// src/core/services/http/public.ts
|
|
194
194
|
var CLIENT_KEY_HEADER = "x-comerge-api-key";
|
|
195
|
-
var
|
|
195
|
+
var clientKey = null;
|
|
196
196
|
var publicApi = axios.create({
|
|
197
197
|
baseURL: BASE_URL,
|
|
198
198
|
timeout: 3e4,
|
|
@@ -201,19 +201,19 @@ var publicApi = axios.create({
|
|
|
201
201
|
"Content-Type": "application/json"
|
|
202
202
|
}
|
|
203
203
|
});
|
|
204
|
-
function
|
|
204
|
+
function setClientKey(clientKeyInput) {
|
|
205
205
|
var _a;
|
|
206
|
-
const trimmed = ((_a =
|
|
206
|
+
const trimmed = ((_a = clientKeyInput == null ? void 0 : clientKeyInput.trim) == null ? void 0 : _a.call(clientKeyInput)) ?? "";
|
|
207
207
|
if (!trimmed) {
|
|
208
|
-
throw new Error("comerge-studio:
|
|
208
|
+
throw new Error("comerge-studio: clientKey is required");
|
|
209
209
|
}
|
|
210
|
-
|
|
210
|
+
clientKey = trimmed;
|
|
211
211
|
publicApi.defaults.headers.common[CLIENT_KEY_HEADER] = trimmed;
|
|
212
212
|
}
|
|
213
213
|
publicApi.interceptors.request.use((config) => {
|
|
214
|
-
if (!
|
|
214
|
+
if (!clientKey) return config;
|
|
215
215
|
config.headers = config.headers ?? {};
|
|
216
|
-
config.headers[CLIENT_KEY_HEADER] =
|
|
216
|
+
config.headers[CLIENT_KEY_HEADER] = clientKey;
|
|
217
217
|
return config;
|
|
218
218
|
});
|
|
219
219
|
|
|
@@ -278,42 +278,9 @@ async function ensureAnonymousSession() {
|
|
|
278
278
|
return { user: data.user, isNew: true };
|
|
279
279
|
}
|
|
280
280
|
|
|
281
|
-
// src/data/base-repository.ts
|
|
282
|
-
var BaseRepository = class {
|
|
283
|
-
unwrapOrThrow(res) {
|
|
284
|
-
if (res.success && res.responseObject) return res.responseObject;
|
|
285
|
-
const msg = res.message || "Request failed";
|
|
286
|
-
throw new Error(msg);
|
|
287
|
-
}
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
// src/data/base-remote.ts
|
|
291
|
-
var BaseRemote = class {
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
// src/data/public/studio-config/remote.ts
|
|
295
|
-
var StudioConfigRemoteDataSourceImpl = class extends BaseRemote {
|
|
296
|
-
async get() {
|
|
297
|
-
const { data } = await publicApi.get("/v1/public/studio-config");
|
|
298
|
-
return data;
|
|
299
|
-
}
|
|
300
|
-
};
|
|
301
|
-
var studioConfigRemoteDataSource = new StudioConfigRemoteDataSourceImpl();
|
|
302
|
-
|
|
303
|
-
// src/data/public/studio-config/repository.ts
|
|
304
|
-
var StudioConfigRepositoryImpl = class extends BaseRepository {
|
|
305
|
-
constructor(remote) {
|
|
306
|
-
super();
|
|
307
|
-
this.remote = remote;
|
|
308
|
-
}
|
|
309
|
-
async get() {
|
|
310
|
-
const res = await this.remote.get();
|
|
311
|
-
return this.unwrapOrThrow(res);
|
|
312
|
-
}
|
|
313
|
-
};
|
|
314
|
-
var studioConfigRepository = new StudioConfigRepositoryImpl(studioConfigRemoteDataSource);
|
|
315
|
-
|
|
316
281
|
// src/studio/bootstrap/useStudioBootstrap.ts
|
|
282
|
+
var SUPABASE_URL = "https://xtfxwbckjpfmqubnsusu.supabase.co";
|
|
283
|
+
var SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inh0Znh3YmNranBmbXF1Ym5zdXN1Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjA2MDEyMzAsImV4cCI6MjA3NjE3NzIzMH0.dzWGAWrK4CvrmHVHzf8w7JlUZohdap0ZPnLZnABMV8s";
|
|
317
284
|
function useStudioBootstrap(options) {
|
|
318
285
|
const [state, setState] = React.useState({
|
|
319
286
|
ready: false,
|
|
@@ -324,11 +291,10 @@ function useStudioBootstrap(options) {
|
|
|
324
291
|
let cancelled = false;
|
|
325
292
|
(async () => {
|
|
326
293
|
try {
|
|
327
|
-
|
|
294
|
+
setClientKey(options.clientKey);
|
|
328
295
|
const requireAuth = isSupabaseClientInjected();
|
|
329
296
|
if (!requireAuth) {
|
|
330
|
-
|
|
331
|
-
setSupabaseConfig(cfg);
|
|
297
|
+
setSupabaseConfig({ url: SUPABASE_URL, anonKey: SUPABASE_ANON_KEY });
|
|
332
298
|
}
|
|
333
299
|
const { user } = requireAuth ? await ensureAuthenticatedSession() : await ensureAnonymousSession();
|
|
334
300
|
if (cancelled) return;
|
|
@@ -342,14 +308,14 @@ function useStudioBootstrap(options) {
|
|
|
342
308
|
return () => {
|
|
343
309
|
cancelled = true;
|
|
344
310
|
};
|
|
345
|
-
}, [options.
|
|
311
|
+
}, [options.clientKey]);
|
|
346
312
|
return state;
|
|
347
313
|
}
|
|
348
314
|
|
|
349
315
|
// src/studio/bootstrap/StudioBootstrap.tsx
|
|
350
316
|
import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
|
|
351
|
-
function StudioBootstrap({ children, fallback, renderError,
|
|
352
|
-
const { ready, error, userId } = useStudioBootstrap({
|
|
317
|
+
function StudioBootstrap({ children, fallback, renderError, clientKey: clientKey2 }) {
|
|
318
|
+
const { ready, error, userId } = useStudioBootstrap({ clientKey: clientKey2 });
|
|
353
319
|
if (error) {
|
|
354
320
|
return /* @__PURE__ */ jsx2(View, { style: { flex: 1, justifyContent: "center", alignItems: "center", padding: 24 }, children: renderError ? renderError(error) : /* @__PURE__ */ jsx2(Text, { variant: "bodyMuted", children: error.message }) });
|
|
355
321
|
}
|
|
@@ -497,6 +463,10 @@ var createApiClient = (baseURL) => {
|
|
|
497
463
|
};
|
|
498
464
|
var api = createApiClient(BASE_URL);
|
|
499
465
|
|
|
466
|
+
// src/data/base-remote.ts
|
|
467
|
+
var BaseRemote = class {
|
|
468
|
+
};
|
|
469
|
+
|
|
500
470
|
// src/data/apps/remote.ts
|
|
501
471
|
var AppsRemoteDataSourceImpl = class extends BaseRemote {
|
|
502
472
|
async list(projectId) {
|
|
@@ -552,6 +522,15 @@ var AppsRemoteDataSourceImpl = class extends BaseRemote {
|
|
|
552
522
|
};
|
|
553
523
|
var appsRemoteDataSource = new AppsRemoteDataSourceImpl();
|
|
554
524
|
|
|
525
|
+
// src/data/base-repository.ts
|
|
526
|
+
var BaseRepository = class {
|
|
527
|
+
unwrapOrThrow(res) {
|
|
528
|
+
if (res.success && res.responseObject) return res.responseObject;
|
|
529
|
+
const msg = res.message || "Request failed";
|
|
530
|
+
throw new Error(msg);
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
|
|
555
534
|
// src/data/apps/repository.ts
|
|
556
535
|
function mapDbAppRow(row) {
|
|
557
536
|
return {
|
|
@@ -904,6 +883,7 @@ function useThreadMessages(threadId) {
|
|
|
904
883
|
// src/studio/hooks/useBundleManager.ts
|
|
905
884
|
import * as React5 from "react";
|
|
906
885
|
import * as FileSystem from "expo-file-system/legacy";
|
|
886
|
+
import { Asset } from "expo-asset";
|
|
907
887
|
|
|
908
888
|
// src/data/apps/bundles/remote.ts
|
|
909
889
|
var BundlesRemoteDataSourceImpl = class extends BaseRemote {
|
|
@@ -1062,6 +1042,24 @@ async function deleteFileIfExists(fileUri) {
|
|
|
1062
1042
|
} catch {
|
|
1063
1043
|
}
|
|
1064
1044
|
}
|
|
1045
|
+
async function hydrateBaseFromEmbeddedAsset(appId, platform, embedded) {
|
|
1046
|
+
if (!(embedded == null ? void 0 : embedded.module)) return null;
|
|
1047
|
+
const key = baseBundleKey(appId, platform);
|
|
1048
|
+
const targetUri = toBundleFileUri(key);
|
|
1049
|
+
const existing = await getExistingNonEmptyFileUri(targetUri);
|
|
1050
|
+
if (existing) return { bundlePath: existing, meta: embedded.meta ?? null };
|
|
1051
|
+
const asset = Asset.fromModule(embedded.module);
|
|
1052
|
+
await asset.downloadAsync();
|
|
1053
|
+
const sourceUri = asset.localUri ?? asset.uri;
|
|
1054
|
+
if (!sourceUri) return null;
|
|
1055
|
+
const info = await FileSystem.getInfoAsync(sourceUri);
|
|
1056
|
+
if (!info.exists) return null;
|
|
1057
|
+
await deleteFileIfExists(targetUri);
|
|
1058
|
+
await FileSystem.copyAsync({ from: sourceUri, to: targetUri });
|
|
1059
|
+
const finalUri = await getExistingNonEmptyFileUri(targetUri);
|
|
1060
|
+
if (!finalUri) return null;
|
|
1061
|
+
return { bundlePath: finalUri, meta: embedded.meta ?? null };
|
|
1062
|
+
}
|
|
1065
1063
|
async function safeReplaceFileFromUrl(url, targetUri, tmpKey) {
|
|
1066
1064
|
const tmpUri = toBundleFileUri(`tmp:${tmpKey}:${Date.now()}`);
|
|
1067
1065
|
try {
|
|
@@ -1134,7 +1132,8 @@ async function resolveBundlePath(src, platform, mode) {
|
|
|
1134
1132
|
function useBundleManager({
|
|
1135
1133
|
base,
|
|
1136
1134
|
platform,
|
|
1137
|
-
canRequestLatest = true
|
|
1135
|
+
canRequestLatest = true,
|
|
1136
|
+
embeddedBaseBundles
|
|
1138
1137
|
}) {
|
|
1139
1138
|
const [bundlePath, setBundlePath] = React5.useState(null);
|
|
1140
1139
|
const [renderToken, setRenderToken] = React5.useState(0);
|
|
@@ -1145,6 +1144,8 @@ function useBundleManager({
|
|
|
1145
1144
|
const [isTesting, setIsTesting] = React5.useState(false);
|
|
1146
1145
|
const baseRef = React5.useRef(base);
|
|
1147
1146
|
baseRef.current = base;
|
|
1147
|
+
const embeddedBaseBundlesRef = React5.useRef(embeddedBaseBundles);
|
|
1148
|
+
embeddedBaseBundlesRef.current = embeddedBaseBundles;
|
|
1148
1149
|
const baseOpIdRef = React5.useRef(0);
|
|
1149
1150
|
const testOpIdRef = React5.useRef(0);
|
|
1150
1151
|
const activeLoadModeRef = React5.useRef(null);
|
|
@@ -1167,16 +1168,29 @@ function useBundleManager({
|
|
|
1167
1168
|
const hasCompletedFirstNetworkBaseLoadRef = React5.useRef(false);
|
|
1168
1169
|
const hydrateBaseFromDisk = React5.useCallback(
|
|
1169
1170
|
async (appId, reason) => {
|
|
1171
|
+
var _a;
|
|
1170
1172
|
try {
|
|
1171
1173
|
const dir = bundlesCacheDir();
|
|
1172
1174
|
await ensureDir(dir);
|
|
1173
1175
|
const key = baseBundleKey(appId, platform);
|
|
1174
1176
|
const uri = toBundleFileUri(key);
|
|
1175
|
-
|
|
1177
|
+
let existing = await getExistingNonEmptyFileUri(uri);
|
|
1178
|
+
let embeddedMeta = null;
|
|
1179
|
+
if (!existing) {
|
|
1180
|
+
const embedded = (_a = embeddedBaseBundlesRef.current) == null ? void 0 : _a[platform];
|
|
1181
|
+
const hydrated = await hydrateBaseFromEmbeddedAsset(appId, platform, embedded);
|
|
1182
|
+
if (hydrated == null ? void 0 : hydrated.bundlePath) {
|
|
1183
|
+
existing = hydrated.bundlePath;
|
|
1184
|
+
embeddedMeta = hydrated.meta ?? null;
|
|
1185
|
+
if (embeddedMeta) {
|
|
1186
|
+
await writeJsonFile(toBundleMetaFileUri(key), embeddedMeta);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1176
1190
|
if (existing) {
|
|
1177
1191
|
lastBaseBundlePathRef.current = existing;
|
|
1178
1192
|
setBundlePath(existing);
|
|
1179
|
-
const meta = await readJsonFile(toBundleMetaFileUri(key));
|
|
1193
|
+
const meta = embeddedMeta ?? await readJsonFile(toBundleMetaFileUri(key));
|
|
1180
1194
|
if (meta == null ? void 0 : meta.fingerprint) {
|
|
1181
1195
|
lastBaseFingerprintRef.current = meta.fingerprint;
|
|
1182
1196
|
}
|
|
@@ -1763,11 +1777,28 @@ function hasNoOutcomeAfterLastHuman(messages) {
|
|
|
1763
1777
|
}
|
|
1764
1778
|
|
|
1765
1779
|
// src/studio/ui/RuntimeRenderer.tsx
|
|
1780
|
+
import * as React9 from "react";
|
|
1766
1781
|
import { View as View2 } from "react-native";
|
|
1767
1782
|
import { ComergeRuntimeRenderer } from "@comergehq/runtime";
|
|
1768
1783
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
1769
|
-
function RuntimeRenderer({
|
|
1784
|
+
function RuntimeRenderer({
|
|
1785
|
+
appKey,
|
|
1786
|
+
bundlePath,
|
|
1787
|
+
forcePreparing,
|
|
1788
|
+
renderToken,
|
|
1789
|
+
style,
|
|
1790
|
+
allowInitialPreparing = true
|
|
1791
|
+
}) {
|
|
1792
|
+
const [hasRenderedOnce, setHasRenderedOnce] = React9.useState(false);
|
|
1793
|
+
React9.useEffect(() => {
|
|
1794
|
+
if (bundlePath) {
|
|
1795
|
+
setHasRenderedOnce(true);
|
|
1796
|
+
}
|
|
1797
|
+
}, [bundlePath]);
|
|
1770
1798
|
if (!bundlePath || forcePreparing) {
|
|
1799
|
+
if (!hasRenderedOnce && !forcePreparing && !allowInitialPreparing) {
|
|
1800
|
+
return /* @__PURE__ */ jsx3(View2, { style: [{ flex: 1 }, style] });
|
|
1801
|
+
}
|
|
1771
1802
|
return /* @__PURE__ */ jsx3(View2, { style: [{ flex: 1, justifyContent: "center", alignItems: "center", padding: 24 }, style], children: /* @__PURE__ */ jsx3(Text, { variant: "bodyMuted", children: "Preparing app\u2026" }) });
|
|
1772
1803
|
}
|
|
1773
1804
|
return /* @__PURE__ */ jsx3(View2, { style: [{ flex: 1 }, style], children: /* @__PURE__ */ jsx3(
|
|
@@ -1782,11 +1813,11 @@ function RuntimeRenderer({ appKey, bundlePath, forcePreparing, renderToken, styl
|
|
|
1782
1813
|
}
|
|
1783
1814
|
|
|
1784
1815
|
// src/studio/ui/StudioOverlay.tsx
|
|
1785
|
-
import * as
|
|
1816
|
+
import * as React42 from "react";
|
|
1786
1817
|
import { Keyboard as Keyboard5, Platform as Platform10, View as View44, useWindowDimensions as useWindowDimensions4 } from "react-native";
|
|
1787
1818
|
|
|
1788
1819
|
// src/components/studio-sheet/StudioBottomSheet.tsx
|
|
1789
|
-
import * as
|
|
1820
|
+
import * as React12 from "react";
|
|
1790
1821
|
import { AppState as AppState3, Keyboard, View as View4 } from "react-native";
|
|
1791
1822
|
import BottomSheet from "@gorhom/bottom-sheet";
|
|
1792
1823
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
@@ -1796,20 +1827,20 @@ import { Platform as Platform3, View as View3 } from "react-native";
|
|
|
1796
1827
|
import { isLiquidGlassSupported } from "@callstack/liquid-glass";
|
|
1797
1828
|
|
|
1798
1829
|
// src/components/utils/ResettableLiquidGlassView.tsx
|
|
1799
|
-
import * as
|
|
1830
|
+
import * as React11 from "react";
|
|
1800
1831
|
import { LiquidGlassView } from "@callstack/liquid-glass";
|
|
1801
1832
|
|
|
1802
1833
|
// src/components/utils/liquidGlassReset.tsx
|
|
1803
|
-
import * as
|
|
1834
|
+
import * as React10 from "react";
|
|
1804
1835
|
import { AppState as AppState2, Platform as Platform2 } from "react-native";
|
|
1805
1836
|
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
1806
|
-
var LiquidGlassResetContext =
|
|
1837
|
+
var LiquidGlassResetContext = React10.createContext(0);
|
|
1807
1838
|
function LiquidGlassResetProvider({
|
|
1808
1839
|
children,
|
|
1809
1840
|
resetTriggers = []
|
|
1810
1841
|
}) {
|
|
1811
|
-
const [token, setToken] =
|
|
1812
|
-
|
|
1842
|
+
const [token, setToken] = React10.useState(0);
|
|
1843
|
+
React10.useEffect(() => {
|
|
1813
1844
|
if (Platform2.OS !== "ios") return;
|
|
1814
1845
|
const onChange = (state) => {
|
|
1815
1846
|
if (state === "active") setToken((t) => t + 1);
|
|
@@ -1817,21 +1848,21 @@ function LiquidGlassResetProvider({
|
|
|
1817
1848
|
const sub = AppState2.addEventListener("change", onChange);
|
|
1818
1849
|
return () => sub.remove();
|
|
1819
1850
|
}, []);
|
|
1820
|
-
|
|
1851
|
+
React10.useEffect(() => {
|
|
1821
1852
|
setToken((t) => t + 1);
|
|
1822
1853
|
}, resetTriggers);
|
|
1823
1854
|
return /* @__PURE__ */ jsx4(LiquidGlassResetContext.Provider, { value: token, children });
|
|
1824
1855
|
}
|
|
1825
1856
|
function useLiquidGlassResetToken() {
|
|
1826
|
-
return
|
|
1857
|
+
return React10.useContext(LiquidGlassResetContext);
|
|
1827
1858
|
}
|
|
1828
1859
|
|
|
1829
1860
|
// src/components/utils/ResettableLiquidGlassView.tsx
|
|
1830
1861
|
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
1831
1862
|
function ResettableLiquidGlassView({ children, ...props }) {
|
|
1832
1863
|
const token = useLiquidGlassResetToken();
|
|
1833
|
-
const [layoutBootKey, setLayoutBootKey] =
|
|
1834
|
-
const sawNonZeroLayoutRef =
|
|
1864
|
+
const [layoutBootKey, setLayoutBootKey] = React11.useState(0);
|
|
1865
|
+
const sawNonZeroLayoutRef = React11.useRef(false);
|
|
1835
1866
|
const onLayout = (e) => {
|
|
1836
1867
|
var _a;
|
|
1837
1868
|
(_a = props.onLayout) == null ? void 0 : _a.call(props, e);
|
|
@@ -1905,11 +1936,11 @@ function StudioBottomSheet({
|
|
|
1905
1936
|
}) {
|
|
1906
1937
|
const theme = useTheme();
|
|
1907
1938
|
const insets = useSafeAreaInsets();
|
|
1908
|
-
const internalSheetRef =
|
|
1939
|
+
const internalSheetRef = React12.useRef(null);
|
|
1909
1940
|
const resolvedSheetRef = sheetRef ?? internalSheetRef;
|
|
1910
|
-
const currentIndexRef =
|
|
1911
|
-
const lastAppStateRef =
|
|
1912
|
-
|
|
1941
|
+
const currentIndexRef = React12.useRef(open ? snapPoints.length - 1 : -1);
|
|
1942
|
+
const lastAppStateRef = React12.useRef(AppState3.currentState);
|
|
1943
|
+
React12.useEffect(() => {
|
|
1913
1944
|
const sub = AppState3.addEventListener("change", (state) => {
|
|
1914
1945
|
const prev = lastAppStateRef.current;
|
|
1915
1946
|
lastAppStateRef.current = state;
|
|
@@ -1929,7 +1960,7 @@ function StudioBottomSheet({
|
|
|
1929
1960
|
});
|
|
1930
1961
|
return () => sub.remove();
|
|
1931
1962
|
}, [open, resolvedSheetRef]);
|
|
1932
|
-
|
|
1963
|
+
React12.useEffect(() => {
|
|
1933
1964
|
const sheet = resolvedSheetRef.current;
|
|
1934
1965
|
if (!sheet) return;
|
|
1935
1966
|
if (open) {
|
|
@@ -1938,7 +1969,7 @@ function StudioBottomSheet({
|
|
|
1938
1969
|
sheet.close();
|
|
1939
1970
|
}
|
|
1940
1971
|
}, [open, resolvedSheetRef, snapPoints.length]);
|
|
1941
|
-
const handleChange =
|
|
1972
|
+
const handleChange = React12.useCallback(
|
|
1942
1973
|
(index) => {
|
|
1943
1974
|
currentIndexRef.current = index;
|
|
1944
1975
|
onOpenChange == null ? void 0 : onOpenChange(index >= 0);
|
|
@@ -1967,12 +1998,12 @@ function StudioBottomSheet({
|
|
|
1967
1998
|
}
|
|
1968
1999
|
|
|
1969
2000
|
// src/components/studio-sheet/StudioSheetPager.tsx
|
|
1970
|
-
import * as
|
|
2001
|
+
import * as React13 from "react";
|
|
1971
2002
|
import { Animated } from "react-native";
|
|
1972
2003
|
import { jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1973
2004
|
function StudioSheetPager({ activePage, width, preview, chat, style }) {
|
|
1974
|
-
const anim =
|
|
1975
|
-
|
|
2005
|
+
const anim = React13.useRef(new Animated.Value(activePage === "chat" ? 1 : 0)).current;
|
|
2006
|
+
React13.useEffect(() => {
|
|
1976
2007
|
Animated.spring(anim, {
|
|
1977
2008
|
toValue: activePage === "chat" ? 1 : 0,
|
|
1978
2009
|
useNativeDriver: true,
|
|
@@ -2020,8 +2051,8 @@ function StudioSheetPager({ activePage, width, preview, chat, style }) {
|
|
|
2020
2051
|
] });
|
|
2021
2052
|
}
|
|
2022
2053
|
|
|
2023
|
-
// src/components/
|
|
2024
|
-
import { useCallback as useCallback8, useEffect as
|
|
2054
|
+
// src/components/bubble/Bubble.tsx
|
|
2055
|
+
import { useCallback as useCallback8, useEffect as useEffect11, useMemo as useMemo3, useRef as useRef7 } from "react";
|
|
2025
2056
|
import {
|
|
2026
2057
|
PanResponder,
|
|
2027
2058
|
Pressable,
|
|
@@ -2044,7 +2075,7 @@ import Animated2, {
|
|
|
2044
2075
|
} from "react-native-reanimated";
|
|
2045
2076
|
import { isLiquidGlassSupported as isLiquidGlassSupported2 } from "@callstack/liquid-glass";
|
|
2046
2077
|
|
|
2047
|
-
// src/components/
|
|
2078
|
+
// src/components/bubble/constants.ts
|
|
2048
2079
|
var DEFAULT_SIZE = 48;
|
|
2049
2080
|
var DEFAULT_EDGE_PADDING = 10;
|
|
2050
2081
|
var DEFAULT_OFFSET = {
|
|
@@ -2055,7 +2086,7 @@ var ENTER_SCALE_FROM = 0.3;
|
|
|
2055
2086
|
var ENTER_ROTATION_FROM_DEG = -180;
|
|
2056
2087
|
var PULSE_DURATION_MS = 900;
|
|
2057
2088
|
|
|
2058
|
-
// src/components/
|
|
2089
|
+
// src/components/bubble/Bubble.tsx
|
|
2059
2090
|
import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
2060
2091
|
var HIDDEN_OFFSET_X = 20;
|
|
2061
2092
|
var SPRING_POSITION = { damping: 12, stiffness: 100, mass: 0.8 };
|
|
@@ -2077,7 +2108,7 @@ function getHiddenTranslateY(height) {
|
|
|
2077
2108
|
function getFinalTranslateY(height, size, bottomOffset) {
|
|
2078
2109
|
return height - size - bottomOffset;
|
|
2079
2110
|
}
|
|
2080
|
-
function
|
|
2111
|
+
function Bubble({
|
|
2081
2112
|
onPress,
|
|
2082
2113
|
size = DEFAULT_SIZE,
|
|
2083
2114
|
disabled = false,
|
|
@@ -2098,7 +2129,7 @@ function FloatingDraggableButton({
|
|
|
2098
2129
|
const { width, height } = useWindowDimensions();
|
|
2099
2130
|
const isDanger = variant === "danger";
|
|
2100
2131
|
const onPressRef = useRef7(onPress);
|
|
2101
|
-
|
|
2132
|
+
useEffect11(() => {
|
|
2102
2133
|
onPressRef.current = onPress;
|
|
2103
2134
|
}, [onPress]);
|
|
2104
2135
|
const fallbackBgColor = useMemo3(() => {
|
|
@@ -2139,7 +2170,7 @@ function FloatingDraggableButton({
|
|
|
2139
2170
|
}
|
|
2140
2171
|
});
|
|
2141
2172
|
}, [animateToHidden]);
|
|
2142
|
-
|
|
2173
|
+
useEffect11(() => {
|
|
2143
2174
|
if (isLoading) {
|
|
2144
2175
|
borderPulse.value = withRepeat(
|
|
2145
2176
|
withSequence(
|
|
@@ -2164,7 +2195,7 @@ function FloatingDraggableButton({
|
|
|
2164
2195
|
);
|
|
2165
2196
|
rotation.value = withSpring(0, SPRING_ROTATION_IN);
|
|
2166
2197
|
}, [height, offset.bottom, offset.left, rotation, scale, size, translateX, translateY]);
|
|
2167
|
-
|
|
2198
|
+
useEffect11(() => {
|
|
2168
2199
|
const timer = setTimeout(() => {
|
|
2169
2200
|
if (visible) {
|
|
2170
2201
|
animateIn();
|
|
@@ -2172,7 +2203,7 @@ function FloatingDraggableButton({
|
|
|
2172
2203
|
}, 100);
|
|
2173
2204
|
return () => clearTimeout(timer);
|
|
2174
2205
|
}, []);
|
|
2175
|
-
|
|
2206
|
+
useEffect11(() => {
|
|
2176
2207
|
if (visible && isAnimatingOut.current) {
|
|
2177
2208
|
animateIn();
|
|
2178
2209
|
} else if (!visible && !isAnimatingOut.current) {
|
|
@@ -2180,7 +2211,7 @@ function FloatingDraggableButton({
|
|
|
2180
2211
|
isAnimatingOut.current = true;
|
|
2181
2212
|
}
|
|
2182
2213
|
}, [visible, animateIn, animateToHidden]);
|
|
2183
|
-
|
|
2214
|
+
useEffect11(() => {
|
|
2184
2215
|
if (forceShowTrigger > 0 && visible) {
|
|
2185
2216
|
isAnimatingOut.current = false;
|
|
2186
2217
|
animateIn();
|
|
@@ -2302,7 +2333,7 @@ var styles = StyleSheet.create({
|
|
|
2302
2333
|
});
|
|
2303
2334
|
|
|
2304
2335
|
// src/components/overlays/EdgeGlowFrame.tsx
|
|
2305
|
-
import * as
|
|
2336
|
+
import * as React14 from "react";
|
|
2306
2337
|
import { Animated as Animated3, View as View6 } from "react-native";
|
|
2307
2338
|
import { LinearGradient } from "expo-linear-gradient";
|
|
2308
2339
|
|
|
@@ -2345,8 +2376,8 @@ function EdgeGlowFrame({
|
|
|
2345
2376
|
}) {
|
|
2346
2377
|
const theme = useTheme();
|
|
2347
2378
|
const alpha = Math.max(0, Math.min(1, intensity));
|
|
2348
|
-
const anim =
|
|
2349
|
-
|
|
2379
|
+
const anim = React14.useRef(new Animated3.Value(visible ? 1 : 0)).current;
|
|
2380
|
+
React14.useEffect(() => {
|
|
2350
2381
|
Animated3.timing(anim, {
|
|
2351
2382
|
toValue: visible ? 1 : 0,
|
|
2352
2383
|
duration: 300,
|
|
@@ -2397,12 +2428,12 @@ function EdgeGlowFrame({
|
|
|
2397
2428
|
}
|
|
2398
2429
|
|
|
2399
2430
|
// src/components/draw/DrawModeOverlay.tsx
|
|
2400
|
-
import * as
|
|
2431
|
+
import * as React17 from "react";
|
|
2401
2432
|
import { StyleSheet as StyleSheet3, View as View10 } from "react-native";
|
|
2402
2433
|
import { captureRef } from "react-native-view-shot";
|
|
2403
2434
|
|
|
2404
2435
|
// src/components/draw/DrawSurface.tsx
|
|
2405
|
-
import * as
|
|
2436
|
+
import * as React15 from "react";
|
|
2406
2437
|
import { PanResponder as PanResponder2, StyleSheet as StyleSheet2, View as View7 } from "react-native";
|
|
2407
2438
|
import Svg, { Path } from "react-native-svg";
|
|
2408
2439
|
|
|
@@ -2434,25 +2465,25 @@ function DrawSurface({
|
|
|
2434
2465
|
style,
|
|
2435
2466
|
minDistance = 1
|
|
2436
2467
|
}) {
|
|
2437
|
-
const [renderTick, setRenderTick] =
|
|
2438
|
-
const currentPointsRef =
|
|
2439
|
-
const rafRef =
|
|
2440
|
-
const triggerRender =
|
|
2468
|
+
const [renderTick, setRenderTick] = React15.useState(0);
|
|
2469
|
+
const currentPointsRef = React15.useRef([]);
|
|
2470
|
+
const rafRef = React15.useRef(null);
|
|
2471
|
+
const triggerRender = React15.useCallback(() => {
|
|
2441
2472
|
if (rafRef.current !== null) return;
|
|
2442
2473
|
rafRef.current = requestAnimationFrame(() => {
|
|
2443
2474
|
rafRef.current = null;
|
|
2444
2475
|
setRenderTick((n) => n + 1);
|
|
2445
2476
|
});
|
|
2446
2477
|
}, []);
|
|
2447
|
-
|
|
2478
|
+
React15.useEffect(() => () => {
|
|
2448
2479
|
if (rafRef.current !== null) cancelAnimationFrame(rafRef.current);
|
|
2449
2480
|
}, []);
|
|
2450
|
-
const onStart =
|
|
2481
|
+
const onStart = React15.useCallback((e) => {
|
|
2451
2482
|
const { locationX, locationY } = e.nativeEvent;
|
|
2452
2483
|
currentPointsRef.current = [{ x: locationX, y: locationY }];
|
|
2453
2484
|
triggerRender();
|
|
2454
2485
|
}, [triggerRender]);
|
|
2455
|
-
const onMove =
|
|
2486
|
+
const onMove = React15.useCallback((e, _g) => {
|
|
2456
2487
|
const { locationX, locationY } = e.nativeEvent;
|
|
2457
2488
|
const pts = currentPointsRef.current;
|
|
2458
2489
|
if (pts.length > 0) {
|
|
@@ -2465,7 +2496,7 @@ function DrawSurface({
|
|
|
2465
2496
|
currentPointsRef.current = [...pts, { x: locationX, y: locationY }];
|
|
2466
2497
|
triggerRender();
|
|
2467
2498
|
}, [minDistance, triggerRender]);
|
|
2468
|
-
const onEnd =
|
|
2499
|
+
const onEnd = React15.useCallback(() => {
|
|
2469
2500
|
const points = currentPointsRef.current;
|
|
2470
2501
|
if (points.length > 0) {
|
|
2471
2502
|
onAddStroke({ points, color, width: strokeWidth });
|
|
@@ -2473,7 +2504,7 @@ function DrawSurface({
|
|
|
2473
2504
|
currentPointsRef.current = [];
|
|
2474
2505
|
triggerRender();
|
|
2475
2506
|
}, [color, onAddStroke, strokeWidth, triggerRender]);
|
|
2476
|
-
const panResponder =
|
|
2507
|
+
const panResponder = React15.useMemo(
|
|
2477
2508
|
() => PanResponder2.create({
|
|
2478
2509
|
onStartShouldSetPanResponder: () => true,
|
|
2479
2510
|
onMoveShouldSetPanResponder: () => true,
|
|
@@ -2523,7 +2554,7 @@ var styles2 = StyleSheet2.create({
|
|
|
2523
2554
|
});
|
|
2524
2555
|
|
|
2525
2556
|
// src/components/draw/DrawToolbar.tsx
|
|
2526
|
-
import * as
|
|
2557
|
+
import * as React16 from "react";
|
|
2527
2558
|
import {
|
|
2528
2559
|
ActivityIndicator,
|
|
2529
2560
|
Animated as Animated4,
|
|
@@ -2620,11 +2651,11 @@ function DrawToolbar({
|
|
|
2620
2651
|
}) {
|
|
2621
2652
|
const insets = useSafeAreaInsets2();
|
|
2622
2653
|
const { width: screenWidth, height: screenHeight } = useWindowDimensions2();
|
|
2623
|
-
const [expanded, setExpanded] =
|
|
2624
|
-
const pos =
|
|
2625
|
-
const start =
|
|
2626
|
-
const currentPos =
|
|
2627
|
-
|
|
2654
|
+
const [expanded, setExpanded] = React16.useState(false);
|
|
2655
|
+
const pos = React16.useRef(new Animated4.ValueXY({ x: screenWidth / 2 - 110, y: -140 })).current;
|
|
2656
|
+
const start = React16.useRef({ x: 0, y: 0 });
|
|
2657
|
+
const currentPos = React16.useRef({ x: 0, y: 0 });
|
|
2658
|
+
React16.useEffect(() => {
|
|
2628
2659
|
if (hidden) return;
|
|
2629
2660
|
Animated4.spring(pos.y, {
|
|
2630
2661
|
toValue: insets.top + 60,
|
|
@@ -2634,7 +2665,7 @@ function DrawToolbar({
|
|
|
2634
2665
|
mass: 0.8
|
|
2635
2666
|
}).start();
|
|
2636
2667
|
}, [hidden, insets.top, pos.y]);
|
|
2637
|
-
|
|
2668
|
+
React16.useEffect(() => {
|
|
2638
2669
|
const id = pos.addListener((v) => {
|
|
2639
2670
|
currentPos.current = { x: v.x ?? 0, y: v.y ?? 0 };
|
|
2640
2671
|
});
|
|
@@ -2642,7 +2673,7 @@ function DrawToolbar({
|
|
|
2642
2673
|
pos.removeListener(id);
|
|
2643
2674
|
};
|
|
2644
2675
|
}, [pos]);
|
|
2645
|
-
const clamp2 =
|
|
2676
|
+
const clamp2 = React16.useCallback(
|
|
2646
2677
|
(x, y) => {
|
|
2647
2678
|
const minX = 10;
|
|
2648
2679
|
const maxX = Math.max(10, screenWidth - 230);
|
|
@@ -2652,7 +2683,7 @@ function DrawToolbar({
|
|
|
2652
2683
|
},
|
|
2653
2684
|
[insets.top, screenHeight, screenWidth]
|
|
2654
2685
|
);
|
|
2655
|
-
const panResponder =
|
|
2686
|
+
const panResponder = React16.useMemo(
|
|
2656
2687
|
() => PanResponder3.create({
|
|
2657
2688
|
onStartShouldSetPanResponder: () => false,
|
|
2658
2689
|
onMoveShouldSetPanResponder: (_e, g) => Math.abs(g.dx) > 5 || Math.abs(g.dy) > 5,
|
|
@@ -2680,7 +2711,7 @@ function DrawToolbar({
|
|
|
2680
2711
|
children
|
|
2681
2712
|
}) {
|
|
2682
2713
|
const isDisabled = Boolean(disabled) || Boolean(capturingDisabled);
|
|
2683
|
-
const [pressed, setPressed] =
|
|
2714
|
+
const [pressed, setPressed] = React16.useState(false);
|
|
2684
2715
|
return /* @__PURE__ */ jsx13(
|
|
2685
2716
|
View9,
|
|
2686
2717
|
{
|
|
@@ -2818,7 +2849,7 @@ function DrawModeOverlay({
|
|
|
2818
2849
|
renderDragHandle
|
|
2819
2850
|
}) {
|
|
2820
2851
|
const theme = useTheme();
|
|
2821
|
-
const defaultPalette =
|
|
2852
|
+
const defaultPalette = React17.useMemo(
|
|
2822
2853
|
() => [
|
|
2823
2854
|
"#EF4444",
|
|
2824
2855
|
// Red
|
|
@@ -2836,11 +2867,11 @@ function DrawModeOverlay({
|
|
|
2836
2867
|
[]
|
|
2837
2868
|
);
|
|
2838
2869
|
const colors = palette && palette.length > 0 ? palette : defaultPalette;
|
|
2839
|
-
const [selectedColor, setSelectedColor] =
|
|
2840
|
-
const [strokes, setStrokes] =
|
|
2841
|
-
const [capturing, setCapturing] =
|
|
2842
|
-
const [hideUi, setHideUi] =
|
|
2843
|
-
|
|
2870
|
+
const [selectedColor, setSelectedColor] = React17.useState(colors[0] ?? "#EF4444");
|
|
2871
|
+
const [strokes, setStrokes] = React17.useState([]);
|
|
2872
|
+
const [capturing, setCapturing] = React17.useState(false);
|
|
2873
|
+
const [hideUi, setHideUi] = React17.useState(false);
|
|
2874
|
+
React17.useEffect(() => {
|
|
2844
2875
|
if (!visible) return;
|
|
2845
2876
|
setStrokes([]);
|
|
2846
2877
|
setSelectedColor(colors[0] ?? "#EF4444");
|
|
@@ -2848,14 +2879,14 @@ function DrawModeOverlay({
|
|
|
2848
2879
|
setHideUi(false);
|
|
2849
2880
|
}, [colors, visible]);
|
|
2850
2881
|
const canUndo = strokes.length > 0;
|
|
2851
|
-
const handleUndo =
|
|
2882
|
+
const handleUndo = React17.useCallback(() => {
|
|
2852
2883
|
setStrokes((prev) => prev.slice(0, -1));
|
|
2853
2884
|
}, []);
|
|
2854
|
-
const handleCancel =
|
|
2885
|
+
const handleCancel = React17.useCallback(() => {
|
|
2855
2886
|
setStrokes([]);
|
|
2856
2887
|
onCancel();
|
|
2857
2888
|
}, [onCancel]);
|
|
2858
|
-
const handleDone =
|
|
2889
|
+
const handleDone = React17.useCallback(async () => {
|
|
2859
2890
|
if (!captureTargetRef.current || capturing) return;
|
|
2860
2891
|
try {
|
|
2861
2892
|
setCapturing(true);
|
|
@@ -2915,7 +2946,7 @@ var styles3 = StyleSheet3.create({
|
|
|
2915
2946
|
});
|
|
2916
2947
|
|
|
2917
2948
|
// src/components/comments/AppCommentsSheet.tsx
|
|
2918
|
-
import * as
|
|
2949
|
+
import * as React24 from "react";
|
|
2919
2950
|
import { ActivityIndicator as ActivityIndicator3, Keyboard as Keyboard3, Platform as Platform6, Pressable as Pressable5, View as View14 } from "react-native";
|
|
2920
2951
|
import {
|
|
2921
2952
|
BottomSheetBackdrop,
|
|
@@ -2927,7 +2958,7 @@ import { isLiquidGlassSupported as isLiquidGlassSupported4 } from "@callstack/li
|
|
|
2927
2958
|
import { Play as Play2 } from "lucide-react-native";
|
|
2928
2959
|
|
|
2929
2960
|
// src/components/chat/ChatComposer.tsx
|
|
2930
|
-
import * as
|
|
2961
|
+
import * as React19 from "react";
|
|
2931
2962
|
import {
|
|
2932
2963
|
ActivityIndicator as ActivityIndicator2,
|
|
2933
2964
|
Animated as Animated5,
|
|
@@ -2941,11 +2972,11 @@ import { isLiquidGlassSupported as isLiquidGlassSupported3 } from "@callstack/li
|
|
|
2941
2972
|
import { Plus } from "lucide-react-native";
|
|
2942
2973
|
|
|
2943
2974
|
// src/components/chat/MultilineTextInput.tsx
|
|
2944
|
-
import * as
|
|
2975
|
+
import * as React18 from "react";
|
|
2945
2976
|
import { TextInput } from "react-native";
|
|
2946
2977
|
import { BottomSheetTextInput } from "@gorhom/bottom-sheet";
|
|
2947
2978
|
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
2948
|
-
var MultilineTextInput =
|
|
2979
|
+
var MultilineTextInput = React18.forwardRef(function MultilineTextInput2({ useBottomSheetTextInput = false, placeholder, placeholderTextColor, style, ...props }, ref) {
|
|
2949
2980
|
const theme = useTheme();
|
|
2950
2981
|
const baseStyle = {
|
|
2951
2982
|
minHeight: 44,
|
|
@@ -3029,7 +3060,7 @@ function AspectRatioThumbnail({
|
|
|
3029
3060
|
onRemove,
|
|
3030
3061
|
renderRemoveIcon
|
|
3031
3062
|
}) {
|
|
3032
|
-
const [aspectRatio, setAspectRatio] =
|
|
3063
|
+
const [aspectRatio, setAspectRatio] = React19.useState(1);
|
|
3033
3064
|
return /* @__PURE__ */ jsxs8(View11, { style: { height: THUMBNAIL_HEIGHT, aspectRatio, position: "relative" }, children: [
|
|
3034
3065
|
/* @__PURE__ */ jsx17(View11, { style: { flex: 1, borderRadius: 8, overflow: "hidden" }, children: /* @__PURE__ */ jsx17(
|
|
3035
3066
|
Image,
|
|
@@ -3086,19 +3117,19 @@ function ChatComposer({
|
|
|
3086
3117
|
style
|
|
3087
3118
|
}) {
|
|
3088
3119
|
const theme = useTheme();
|
|
3089
|
-
const [internal, setInternal] =
|
|
3120
|
+
const [internal, setInternal] = React19.useState("");
|
|
3090
3121
|
const text = value ?? internal;
|
|
3091
3122
|
const setText = onChangeValue ?? setInternal;
|
|
3092
3123
|
const hasAttachments = attachments.length > 0;
|
|
3093
3124
|
const hasText = text.trim().length > 0;
|
|
3094
3125
|
const composerMinHeight = hasAttachments ? THUMBNAIL_HEIGHT + 44 + 24 : 44;
|
|
3095
3126
|
const isButtonDisabled = sending || disabled || sendDisabled;
|
|
3096
|
-
const maxInputHeight =
|
|
3097
|
-
const shakeAnim =
|
|
3098
|
-
const [sendPressed, setSendPressed] =
|
|
3099
|
-
const inputRef =
|
|
3100
|
-
const prevAutoFocusRef =
|
|
3101
|
-
|
|
3127
|
+
const maxInputHeight = React19.useMemo(() => Dimensions.get("window").height * 0.5, []);
|
|
3128
|
+
const shakeAnim = React19.useRef(new Animated5.Value(0)).current;
|
|
3129
|
+
const [sendPressed, setSendPressed] = React19.useState(false);
|
|
3130
|
+
const inputRef = React19.useRef(null);
|
|
3131
|
+
const prevAutoFocusRef = React19.useRef(false);
|
|
3132
|
+
React19.useEffect(() => {
|
|
3102
3133
|
const shouldFocus = autoFocus && !prevAutoFocusRef.current && !disabled && !sending;
|
|
3103
3134
|
prevAutoFocusRef.current = autoFocus;
|
|
3104
3135
|
if (!shouldFocus) return;
|
|
@@ -3108,7 +3139,7 @@ function ChatComposer({
|
|
|
3108
3139
|
}, 75);
|
|
3109
3140
|
return () => clearTimeout(t);
|
|
3110
3141
|
}, [autoFocus, disabled, sending]);
|
|
3111
|
-
const triggerShake =
|
|
3142
|
+
const triggerShake = React19.useCallback(() => {
|
|
3112
3143
|
shakeAnim.setValue(0);
|
|
3113
3144
|
Animated5.sequence([
|
|
3114
3145
|
Animated5.timing(shakeAnim, { toValue: 10, duration: 50, useNativeDriver: true }),
|
|
@@ -3118,7 +3149,7 @@ function ChatComposer({
|
|
|
3118
3149
|
Animated5.timing(shakeAnim, { toValue: 0, duration: 50, useNativeDriver: true })
|
|
3119
3150
|
]).start();
|
|
3120
3151
|
}, [shakeAnim]);
|
|
3121
|
-
const handleSend =
|
|
3152
|
+
const handleSend = React19.useCallback(async () => {
|
|
3122
3153
|
if (isButtonDisabled) return;
|
|
3123
3154
|
if (!hasText) {
|
|
3124
3155
|
triggerShake();
|
|
@@ -3251,7 +3282,7 @@ function ChatComposer({
|
|
|
3251
3282
|
}
|
|
3252
3283
|
|
|
3253
3284
|
// src/components/comments/CommentRow.tsx
|
|
3254
|
-
import * as
|
|
3285
|
+
import * as React20 from "react";
|
|
3255
3286
|
import { View as View13 } from "react-native";
|
|
3256
3287
|
|
|
3257
3288
|
// src/components/primitives/Avatar.tsx
|
|
@@ -3323,9 +3354,9 @@ function formatTimeAgo(iso) {
|
|
|
3323
3354
|
import { jsx as jsx19, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3324
3355
|
function CommentRow({ comment, showDivider }) {
|
|
3325
3356
|
const theme = useTheme();
|
|
3326
|
-
const [authorName, setAuthorName] =
|
|
3327
|
-
const [authorAvatar, setAuthorAvatar] =
|
|
3328
|
-
|
|
3357
|
+
const [authorName, setAuthorName] = React20.useState(null);
|
|
3358
|
+
const [authorAvatar, setAuthorAvatar] = React20.useState(null);
|
|
3359
|
+
React20.useEffect(() => {
|
|
3329
3360
|
let cancelled = false;
|
|
3330
3361
|
(async () => {
|
|
3331
3362
|
try {
|
|
@@ -3365,7 +3396,7 @@ function CommentRow({ comment, showDivider }) {
|
|
|
3365
3396
|
}
|
|
3366
3397
|
|
|
3367
3398
|
// src/components/comments/useAppComments.ts
|
|
3368
|
-
import * as
|
|
3399
|
+
import * as React21 from "react";
|
|
3369
3400
|
|
|
3370
3401
|
// src/data/comments/remote.ts
|
|
3371
3402
|
var AppCommentsRemoteDataSourceImpl = class extends BaseRemote {
|
|
@@ -3437,18 +3468,18 @@ var appCommentsRepository = new AppCommentsRepositoryImpl(appCommentsRemoteDataS
|
|
|
3437
3468
|
|
|
3438
3469
|
// src/components/comments/useAppComments.ts
|
|
3439
3470
|
function useAppComments(appId) {
|
|
3440
|
-
const [comments, setComments] =
|
|
3441
|
-
const [loading, setLoading] =
|
|
3442
|
-
const [sending, setSending] =
|
|
3443
|
-
const [error, setError] =
|
|
3444
|
-
const sortByCreatedAtAsc =
|
|
3471
|
+
const [comments, setComments] = React21.useState([]);
|
|
3472
|
+
const [loading, setLoading] = React21.useState(false);
|
|
3473
|
+
const [sending, setSending] = React21.useState(false);
|
|
3474
|
+
const [error, setError] = React21.useState(null);
|
|
3475
|
+
const sortByCreatedAtAsc = React21.useCallback((items) => {
|
|
3445
3476
|
return [...items].sort((a, b) => {
|
|
3446
3477
|
const at = a.createdAt ? new Date(a.createdAt).getTime() : 0;
|
|
3447
3478
|
const bt = b.createdAt ? new Date(b.createdAt).getTime() : 0;
|
|
3448
3479
|
return at - bt;
|
|
3449
3480
|
});
|
|
3450
3481
|
}, []);
|
|
3451
|
-
const refresh =
|
|
3482
|
+
const refresh = React21.useCallback(async () => {
|
|
3452
3483
|
if (!appId) {
|
|
3453
3484
|
setComments([]);
|
|
3454
3485
|
return;
|
|
@@ -3465,10 +3496,10 @@ function useAppComments(appId) {
|
|
|
3465
3496
|
setLoading(false);
|
|
3466
3497
|
}
|
|
3467
3498
|
}, [appId, sortByCreatedAtAsc]);
|
|
3468
|
-
|
|
3499
|
+
React21.useEffect(() => {
|
|
3469
3500
|
void refresh();
|
|
3470
3501
|
}, [refresh]);
|
|
3471
|
-
const create =
|
|
3502
|
+
const create = React21.useCallback(
|
|
3472
3503
|
async (text) => {
|
|
3473
3504
|
if (!appId) return;
|
|
3474
3505
|
const trimmed = text.trim();
|
|
@@ -3491,11 +3522,11 @@ function useAppComments(appId) {
|
|
|
3491
3522
|
}
|
|
3492
3523
|
|
|
3493
3524
|
// src/components/comments/useAppDetails.ts
|
|
3494
|
-
import * as
|
|
3525
|
+
import * as React22 from "react";
|
|
3495
3526
|
function useAppDetails(appId) {
|
|
3496
|
-
const [app, setApp] =
|
|
3497
|
-
const [loading, setLoading] =
|
|
3498
|
-
|
|
3527
|
+
const [app, setApp] = React22.useState(null);
|
|
3528
|
+
const [loading, setLoading] = React22.useState(false);
|
|
3529
|
+
React22.useEffect(() => {
|
|
3499
3530
|
if (!appId) {
|
|
3500
3531
|
setApp(null);
|
|
3501
3532
|
return;
|
|
@@ -3520,11 +3551,11 @@ function useAppDetails(appId) {
|
|
|
3520
3551
|
}
|
|
3521
3552
|
|
|
3522
3553
|
// src/components/comments/useIosKeyboardSnapFix.ts
|
|
3523
|
-
import * as
|
|
3554
|
+
import * as React23 from "react";
|
|
3524
3555
|
import { Keyboard as Keyboard2, Platform as Platform5 } from "react-native";
|
|
3525
3556
|
function useIosKeyboardSnapFix(sheetRef, options) {
|
|
3526
|
-
const [keyboardVisible, setKeyboardVisible] =
|
|
3527
|
-
|
|
3557
|
+
const [keyboardVisible, setKeyboardVisible] = React23.useState(false);
|
|
3558
|
+
React23.useEffect(() => {
|
|
3528
3559
|
if (Platform5.OS !== "ios") return;
|
|
3529
3560
|
const show = Keyboard2.addListener("keyboardWillShow", () => setKeyboardVisible(true));
|
|
3530
3561
|
const hide = Keyboard2.addListener("keyboardWillHide", () => {
|
|
@@ -3552,16 +3583,16 @@ import { jsx as jsx20, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
|
3552
3583
|
function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
3553
3584
|
const theme = useTheme();
|
|
3554
3585
|
const insets = useSafeAreaInsets3();
|
|
3555
|
-
const sheetRef =
|
|
3556
|
-
const snapPoints =
|
|
3557
|
-
const currentIndexRef =
|
|
3586
|
+
const sheetRef = React24.useRef(null);
|
|
3587
|
+
const snapPoints = React24.useMemo(() => ["50%", "90%"], []);
|
|
3588
|
+
const currentIndexRef = React24.useRef(1);
|
|
3558
3589
|
const { comments, loading, sending, error, create, refresh } = useAppComments(appId);
|
|
3559
3590
|
const { app, loading: loadingApp } = useAppDetails(appId);
|
|
3560
3591
|
const { keyboardVisible } = useIosKeyboardSnapFix(sheetRef, {
|
|
3561
3592
|
getCurrentIndex: () => currentIndexRef.current,
|
|
3562
3593
|
targetIndex: 1
|
|
3563
3594
|
});
|
|
3564
|
-
|
|
3595
|
+
React24.useEffect(() => {
|
|
3565
3596
|
var _a, _b;
|
|
3566
3597
|
if (appId) {
|
|
3567
3598
|
(_a = sheetRef.current) == null ? void 0 : _a.present();
|
|
@@ -3570,22 +3601,22 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
3570
3601
|
(_b = sheetRef.current) == null ? void 0 : _b.dismiss();
|
|
3571
3602
|
}
|
|
3572
3603
|
}, [appId, refresh]);
|
|
3573
|
-
|
|
3604
|
+
React24.useEffect(() => {
|
|
3574
3605
|
if (!appId) return;
|
|
3575
3606
|
onCountChange == null ? void 0 : onCountChange(comments.length);
|
|
3576
3607
|
}, [appId, comments.length, onCountChange]);
|
|
3577
|
-
const renderBackdrop =
|
|
3608
|
+
const renderBackdrop = React24.useCallback(
|
|
3578
3609
|
(props) => /* @__PURE__ */ jsx20(BottomSheetBackdrop, { ...props, disappearsOnIndex: -1, appearsOnIndex: 0, opacity: 0.5 }),
|
|
3579
3610
|
[]
|
|
3580
3611
|
);
|
|
3581
|
-
const handleChange =
|
|
3612
|
+
const handleChange = React24.useCallback(
|
|
3582
3613
|
(index) => {
|
|
3583
3614
|
currentIndexRef.current = index;
|
|
3584
3615
|
if (index === -1) onClose();
|
|
3585
3616
|
},
|
|
3586
3617
|
[onClose]
|
|
3587
3618
|
);
|
|
3588
|
-
const handlePlay =
|
|
3619
|
+
const handlePlay = React24.useCallback(async () => {
|
|
3589
3620
|
var _a;
|
|
3590
3621
|
if (!appId) return;
|
|
3591
3622
|
(_a = sheetRef.current) == null ? void 0 : _a.dismiss();
|
|
@@ -3795,7 +3826,7 @@ function StudioSheetHeader({ left, center, right, style }) {
|
|
|
3795
3826
|
}
|
|
3796
3827
|
|
|
3797
3828
|
// src/components/studio-sheet/StudioSheetHeaderIconButton.tsx
|
|
3798
|
-
import * as
|
|
3829
|
+
import * as React25 from "react";
|
|
3799
3830
|
import { Pressable as Pressable6, View as View17 } from "react-native";
|
|
3800
3831
|
import { isLiquidGlassSupported as isLiquidGlassSupported5 } from "@callstack/liquid-glass";
|
|
3801
3832
|
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
@@ -3810,7 +3841,7 @@ function StudioSheetHeaderIconButton({
|
|
|
3810
3841
|
}) {
|
|
3811
3842
|
const theme = useTheme();
|
|
3812
3843
|
const size = 44;
|
|
3813
|
-
const [pressed, setPressed] =
|
|
3844
|
+
const [pressed, setPressed] = React25.useState(false);
|
|
3814
3845
|
const solidBg = intent === "danger" ? theme.colors.danger : intent === "primary" ? theme.colors.primary : theme.colors.neutral;
|
|
3815
3846
|
const glassFallbackBg = theme.scheme === "dark" ? "#18181B" : "#F6F6F6";
|
|
3816
3847
|
const glassInnerBg = intent === "danger" ? theme.colors.danger : theme.colors.primary;
|
|
@@ -4000,14 +4031,14 @@ function PreviewHeroCard({
|
|
|
4000
4031
|
}
|
|
4001
4032
|
|
|
4002
4033
|
// src/components/preview/PreviewPlaceholder.tsx
|
|
4003
|
-
import * as
|
|
4034
|
+
import * as React26 from "react";
|
|
4004
4035
|
import { Animated as Animated6 } from "react-native";
|
|
4005
4036
|
import { LinearGradient as LinearGradient2 } from "expo-linear-gradient";
|
|
4006
4037
|
import { Fragment as Fragment3, jsx as jsx28, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
4007
4038
|
function PreviewPlaceholder({ visible, style }) {
|
|
4008
4039
|
if (!visible) return null;
|
|
4009
|
-
const opacityAnim =
|
|
4010
|
-
|
|
4040
|
+
const opacityAnim = React26.useRef(new Animated6.Value(0)).current;
|
|
4041
|
+
React26.useEffect(() => {
|
|
4011
4042
|
if (!visible) return;
|
|
4012
4043
|
const animation = Animated6.loop(
|
|
4013
4044
|
Animated6.sequence([
|
|
@@ -4599,12 +4630,12 @@ function PreviewCustomizeSection({
|
|
|
4599
4630
|
}
|
|
4600
4631
|
|
|
4601
4632
|
// src/studio/ui/preview-panel/PreviewCollaborateSection.tsx
|
|
4602
|
-
import * as
|
|
4633
|
+
import * as React32 from "react";
|
|
4603
4634
|
import { ActivityIndicator as ActivityIndicator6, Alert, View as View32 } from "react-native";
|
|
4604
4635
|
import { Send as Send2 } from "lucide-react-native";
|
|
4605
4636
|
|
|
4606
4637
|
// src/components/merge-requests/MergeRequestStatusCard.tsx
|
|
4607
|
-
import * as
|
|
4638
|
+
import * as React28 from "react";
|
|
4608
4639
|
import { Animated as Animated7, Pressable as Pressable9, View as View28 } from "react-native";
|
|
4609
4640
|
import { Ban, Check as Check3, CheckCheck, ChevronDown as ChevronDown2 } from "lucide-react-native";
|
|
4610
4641
|
|
|
@@ -4686,11 +4717,11 @@ function toIsoString(input) {
|
|
|
4686
4717
|
}
|
|
4687
4718
|
|
|
4688
4719
|
// src/components/merge-requests/useControlledExpansion.ts
|
|
4689
|
-
import * as
|
|
4720
|
+
import * as React27 from "react";
|
|
4690
4721
|
function useControlledExpansion(props) {
|
|
4691
|
-
const [uncontrolled, setUncontrolled] =
|
|
4722
|
+
const [uncontrolled, setUncontrolled] = React27.useState(false);
|
|
4692
4723
|
const expanded = props.expanded ?? uncontrolled;
|
|
4693
|
-
const setExpanded =
|
|
4724
|
+
const setExpanded = React27.useCallback(
|
|
4694
4725
|
(next) => {
|
|
4695
4726
|
var _a;
|
|
4696
4727
|
(_a = props.onExpandedChange) == null ? void 0 : _a.call(props, next);
|
|
@@ -4715,8 +4746,8 @@ function MergeRequestStatusCard({
|
|
|
4715
4746
|
const isDark = theme.scheme === "dark";
|
|
4716
4747
|
const textColor = isDark ? "#FFFFFF" : "#000000";
|
|
4717
4748
|
const subTextColor = isDark ? "#A1A1AA" : "#71717A";
|
|
4718
|
-
const status =
|
|
4719
|
-
const { StatusIcon, iconColor, bgColor, statusText } =
|
|
4749
|
+
const status = React28.useMemo(() => getMergeRequestStatusDisplay(String(mergeRequest.status)), [mergeRequest.status]);
|
|
4750
|
+
const { StatusIcon, iconColor, bgColor, statusText } = React28.useMemo(() => {
|
|
4720
4751
|
switch (mergeRequest.status) {
|
|
4721
4752
|
case "approved":
|
|
4722
4753
|
case "merged":
|
|
@@ -4747,8 +4778,8 @@ function MergeRequestStatusCard({
|
|
|
4747
4778
|
const createdIso = toIsoString(mergeRequest.createdAt ?? null);
|
|
4748
4779
|
const headerTimeAgo = updatedIso ? formatTimeAgo(updatedIso) : "";
|
|
4749
4780
|
const createdTimeAgo = createdIso ? formatTimeAgo(createdIso) : "";
|
|
4750
|
-
const rotate =
|
|
4751
|
-
|
|
4781
|
+
const rotate = React28.useRef(new Animated7.Value(expanded ? 1 : 0)).current;
|
|
4782
|
+
React28.useEffect(() => {
|
|
4752
4783
|
Animated7.timing(rotate, {
|
|
4753
4784
|
toValue: expanded ? 1 : 0,
|
|
4754
4785
|
duration: 200,
|
|
@@ -4839,16 +4870,16 @@ function MergeRequestStatusCard({
|
|
|
4839
4870
|
}
|
|
4840
4871
|
|
|
4841
4872
|
// src/components/merge-requests/ReviewMergeRequestCarousel.tsx
|
|
4842
|
-
import * as
|
|
4873
|
+
import * as React31 from "react";
|
|
4843
4874
|
import { Animated as Animated9, FlatList, View as View31, useWindowDimensions as useWindowDimensions3 } from "react-native";
|
|
4844
4875
|
|
|
4845
4876
|
// src/components/merge-requests/ReviewMergeRequestCard.tsx
|
|
4846
|
-
import * as
|
|
4877
|
+
import * as React30 from "react";
|
|
4847
4878
|
import { ActivityIndicator as ActivityIndicator5, Animated as Animated8, Pressable as Pressable11, View as View30 } from "react-native";
|
|
4848
4879
|
import { Check as Check4, ChevronDown as ChevronDown3, Play as Play3, X as X3 } from "lucide-react-native";
|
|
4849
4880
|
|
|
4850
4881
|
// src/components/merge-requests/ReviewMergeRequestActionButton.tsx
|
|
4851
|
-
import * as
|
|
4882
|
+
import * as React29 from "react";
|
|
4852
4883
|
import { Pressable as Pressable10, View as View29 } from "react-native";
|
|
4853
4884
|
import { jsx as jsx41 } from "react/jsx-runtime";
|
|
4854
4885
|
function ReviewMergeRequestActionButton({
|
|
@@ -4859,7 +4890,7 @@ function ReviewMergeRequestActionButton({
|
|
|
4859
4890
|
children,
|
|
4860
4891
|
iconOnly
|
|
4861
4892
|
}) {
|
|
4862
|
-
const [pressed, setPressed] =
|
|
4893
|
+
const [pressed, setPressed] = React29.useState(false);
|
|
4863
4894
|
const height = iconOnly ? 36 : 40;
|
|
4864
4895
|
const width = iconOnly ? 36 : void 0;
|
|
4865
4896
|
const paddingHorizontal = iconOnly ? 0 : 16;
|
|
@@ -4921,10 +4952,10 @@ function ReviewMergeRequestCard({
|
|
|
4921
4952
|
onTest
|
|
4922
4953
|
}) {
|
|
4923
4954
|
const theme = useTheme();
|
|
4924
|
-
const status =
|
|
4955
|
+
const status = React30.useMemo(() => getMergeRequestStatusDisplay(mr.status), [mr.status]);
|
|
4925
4956
|
const canAct = mr.status === "open";
|
|
4926
|
-
const rotate =
|
|
4927
|
-
|
|
4957
|
+
const rotate = React30.useRef(new Animated8.Value(isExpanded ? 1 : 0)).current;
|
|
4958
|
+
React30.useEffect(() => {
|
|
4928
4959
|
Animated8.timing(rotate, { toValue: isExpanded ? 1 : 0, duration: 200, useNativeDriver: true }).start();
|
|
4929
4960
|
}, [isExpanded, rotate]);
|
|
4930
4961
|
const position = total > 1 ? `${index + 1}/${total}` : "Merge request";
|
|
@@ -5056,11 +5087,11 @@ function ReviewMergeRequestCarousel({
|
|
|
5056
5087
|
}) {
|
|
5057
5088
|
const theme = useTheme();
|
|
5058
5089
|
const { width } = useWindowDimensions3();
|
|
5059
|
-
const [expanded, setExpanded] =
|
|
5060
|
-
const carouselScrollX =
|
|
5090
|
+
const [expanded, setExpanded] = React31.useState({});
|
|
5091
|
+
const carouselScrollX = React31.useRef(new Animated9.Value(0)).current;
|
|
5061
5092
|
const peekAmount = 24;
|
|
5062
5093
|
const gap = 16;
|
|
5063
|
-
const cardWidth =
|
|
5094
|
+
const cardWidth = React31.useMemo(() => Math.max(1, width - theme.spacing.lg * 2 - peekAmount), [peekAmount, theme.spacing.lg, width]);
|
|
5064
5095
|
const snapInterval = cardWidth + gap;
|
|
5065
5096
|
const dotColor = theme.scheme === "dark" ? "#FFFFFF" : "#000000";
|
|
5066
5097
|
if (mergeRequests.length === 0) return null;
|
|
@@ -5159,7 +5190,7 @@ function PreviewCollaborateSection({
|
|
|
5159
5190
|
onTestMr
|
|
5160
5191
|
}) {
|
|
5161
5192
|
const theme = useTheme();
|
|
5162
|
-
const [submittingMr, setSubmittingMr] =
|
|
5193
|
+
const [submittingMr, setSubmittingMr] = React32.useState(false);
|
|
5163
5194
|
const hasSection = canSubmitMergeRequest || incomingMergeRequests.length > 0 || outgoingMergeRequests.length > 0;
|
|
5164
5195
|
if (!hasSection) return null;
|
|
5165
5196
|
const showActionsSubtitle = canSubmitMergeRequest && onSubmitMergeRequest || onTestMr && incomingMergeRequests.length > 0;
|
|
@@ -5267,7 +5298,7 @@ function PreviewCollaborateSection({
|
|
|
5267
5298
|
}
|
|
5268
5299
|
|
|
5269
5300
|
// src/studio/ui/preview-panel/usePreviewPanelData.ts
|
|
5270
|
-
import * as
|
|
5301
|
+
import * as React34 from "react";
|
|
5271
5302
|
|
|
5272
5303
|
// src/data/apps/images/remote.ts
|
|
5273
5304
|
var AppImagesRemoteDataSourceImpl = class extends BaseRemote {
|
|
@@ -5318,7 +5349,7 @@ var AppImagesRepositoryImpl = class extends BaseRepository {
|
|
|
5318
5349
|
var appImagesRepository = new AppImagesRepositoryImpl(appImagesRemoteDataSource);
|
|
5319
5350
|
|
|
5320
5351
|
// src/studio/hooks/useAppStats.ts
|
|
5321
|
-
import * as
|
|
5352
|
+
import * as React33 from "react";
|
|
5322
5353
|
import * as Haptics2 from "expo-haptics";
|
|
5323
5354
|
|
|
5324
5355
|
// src/data/likes/remote.ts
|
|
@@ -5387,34 +5418,34 @@ function useAppStats({
|
|
|
5387
5418
|
initialIsLiked = false,
|
|
5388
5419
|
onOpenComments
|
|
5389
5420
|
}) {
|
|
5390
|
-
const [likeCount, setLikeCount] =
|
|
5391
|
-
const [commentCount, setCommentCount] =
|
|
5392
|
-
const [forkCount, setForkCount] =
|
|
5393
|
-
const [isLiked, setIsLiked] =
|
|
5394
|
-
const didMutateRef =
|
|
5395
|
-
const lastAppIdRef =
|
|
5396
|
-
|
|
5421
|
+
const [likeCount, setLikeCount] = React33.useState(initialLikes);
|
|
5422
|
+
const [commentCount, setCommentCount] = React33.useState(initialComments);
|
|
5423
|
+
const [forkCount, setForkCount] = React33.useState(initialForks);
|
|
5424
|
+
const [isLiked, setIsLiked] = React33.useState(initialIsLiked);
|
|
5425
|
+
const didMutateRef = React33.useRef(false);
|
|
5426
|
+
const lastAppIdRef = React33.useRef("");
|
|
5427
|
+
React33.useEffect(() => {
|
|
5397
5428
|
if (lastAppIdRef.current === appId) return;
|
|
5398
5429
|
lastAppIdRef.current = appId;
|
|
5399
5430
|
didMutateRef.current = false;
|
|
5400
5431
|
}, [appId]);
|
|
5401
|
-
|
|
5432
|
+
React33.useEffect(() => {
|
|
5402
5433
|
if (didMutateRef.current) return;
|
|
5403
5434
|
setLikeCount(initialLikes);
|
|
5404
5435
|
}, [appId, initialLikes]);
|
|
5405
|
-
|
|
5436
|
+
React33.useEffect(() => {
|
|
5406
5437
|
if (didMutateRef.current) return;
|
|
5407
5438
|
setCommentCount(initialComments);
|
|
5408
5439
|
}, [appId, initialComments]);
|
|
5409
|
-
|
|
5440
|
+
React33.useEffect(() => {
|
|
5410
5441
|
if (didMutateRef.current) return;
|
|
5411
5442
|
setForkCount(initialForks);
|
|
5412
5443
|
}, [appId, initialForks]);
|
|
5413
|
-
|
|
5444
|
+
React33.useEffect(() => {
|
|
5414
5445
|
if (didMutateRef.current) return;
|
|
5415
5446
|
setIsLiked(initialIsLiked);
|
|
5416
5447
|
}, [appId, initialIsLiked]);
|
|
5417
|
-
const handleLike =
|
|
5448
|
+
const handleLike = React33.useCallback(async () => {
|
|
5418
5449
|
var _a, _b;
|
|
5419
5450
|
if (!appId) return;
|
|
5420
5451
|
didMutateRef.current = true;
|
|
@@ -5438,7 +5469,7 @@ function useAppStats({
|
|
|
5438
5469
|
setLikeCount((prev) => Math.max(0, prev + (newIsLiked ? -1 : 1)));
|
|
5439
5470
|
}
|
|
5440
5471
|
}, [appId, isLiked, likeCount]);
|
|
5441
|
-
const handleOpenComments =
|
|
5472
|
+
const handleOpenComments = React33.useCallback(() => {
|
|
5442
5473
|
if (!appId) return;
|
|
5443
5474
|
try {
|
|
5444
5475
|
void Haptics2.impactAsync(Haptics2.ImpactFeedbackStyle.Light);
|
|
@@ -5453,11 +5484,11 @@ function useAppStats({
|
|
|
5453
5484
|
var LIKE_DEBUG_PREFIX = "[COMERGE_LIKE_DEBUG]";
|
|
5454
5485
|
function usePreviewPanelData(params) {
|
|
5455
5486
|
const { app, isOwner, outgoingMergeRequests, onOpenComments, commentCountOverride } = params;
|
|
5456
|
-
const [imageUrl, setImageUrl] =
|
|
5457
|
-
const [imageLoaded, setImageLoaded] =
|
|
5458
|
-
const [insights, setInsights] =
|
|
5459
|
-
const [creator, setCreator] =
|
|
5460
|
-
|
|
5487
|
+
const [imageUrl, setImageUrl] = React34.useState(null);
|
|
5488
|
+
const [imageLoaded, setImageLoaded] = React34.useState(false);
|
|
5489
|
+
const [insights, setInsights] = React34.useState({ likes: 0, comments: 0, forks: 0, downloads: 0 });
|
|
5490
|
+
const [creator, setCreator] = React34.useState(null);
|
|
5491
|
+
React34.useEffect(() => {
|
|
5461
5492
|
if (!(app == null ? void 0 : app.id)) return;
|
|
5462
5493
|
let cancelled = false;
|
|
5463
5494
|
(async () => {
|
|
@@ -5472,7 +5503,7 @@ function usePreviewPanelData(params) {
|
|
|
5472
5503
|
cancelled = true;
|
|
5473
5504
|
};
|
|
5474
5505
|
}, [app == null ? void 0 : app.id]);
|
|
5475
|
-
|
|
5506
|
+
React34.useEffect(() => {
|
|
5476
5507
|
if (!(app == null ? void 0 : app.createdBy)) return;
|
|
5477
5508
|
let cancelled = false;
|
|
5478
5509
|
(async () => {
|
|
@@ -5488,10 +5519,10 @@ function usePreviewPanelData(params) {
|
|
|
5488
5519
|
cancelled = true;
|
|
5489
5520
|
};
|
|
5490
5521
|
}, [app == null ? void 0 : app.createdBy]);
|
|
5491
|
-
|
|
5522
|
+
React34.useEffect(() => {
|
|
5492
5523
|
setImageLoaded(false);
|
|
5493
5524
|
}, [app == null ? void 0 : app.id]);
|
|
5494
|
-
|
|
5525
|
+
React34.useEffect(() => {
|
|
5495
5526
|
if (!(app == null ? void 0 : app.id)) return;
|
|
5496
5527
|
let cancelled = false;
|
|
5497
5528
|
(async () => {
|
|
@@ -5516,7 +5547,7 @@ function usePreviewPanelData(params) {
|
|
|
5516
5547
|
cancelled = true;
|
|
5517
5548
|
};
|
|
5518
5549
|
}, [app == null ? void 0 : app.id]);
|
|
5519
|
-
|
|
5550
|
+
React34.useEffect(() => {
|
|
5520
5551
|
if (!(app == null ? void 0 : app.id)) return;
|
|
5521
5552
|
log.debug(
|
|
5522
5553
|
`${LIKE_DEBUG_PREFIX} usePreviewPanelData.appChanged appId=${app.id} app.isLiked=${String(app.isLiked)}`
|
|
@@ -5530,7 +5561,7 @@ function usePreviewPanelData(params) {
|
|
|
5530
5561
|
initialIsLiked: Boolean(app == null ? void 0 : app.isLiked),
|
|
5531
5562
|
onOpenComments
|
|
5532
5563
|
});
|
|
5533
|
-
const canSubmitMergeRequest =
|
|
5564
|
+
const canSubmitMergeRequest = React34.useMemo(() => {
|
|
5534
5565
|
if (!isOwner) return false;
|
|
5535
5566
|
if (!app) return false;
|
|
5536
5567
|
if (!app.forkedFromAppId) return false;
|
|
@@ -5643,16 +5674,16 @@ function PreviewPanel({
|
|
|
5643
5674
|
}
|
|
5644
5675
|
|
|
5645
5676
|
// src/studio/ui/ChatPanel.tsx
|
|
5646
|
-
import * as
|
|
5677
|
+
import * as React39 from "react";
|
|
5647
5678
|
import { ActivityIndicator as ActivityIndicator8, View as View41 } from "react-native";
|
|
5648
5679
|
|
|
5649
5680
|
// src/components/chat/ChatPage.tsx
|
|
5650
|
-
import * as
|
|
5681
|
+
import * as React37 from "react";
|
|
5651
5682
|
import { Keyboard as Keyboard4, Platform as Platform9, View as View37 } from "react-native";
|
|
5652
5683
|
import { useSafeAreaInsets as useSafeAreaInsets4 } from "react-native-safe-area-context";
|
|
5653
5684
|
|
|
5654
5685
|
// src/components/chat/ChatMessageList.tsx
|
|
5655
|
-
import * as
|
|
5686
|
+
import * as React36 from "react";
|
|
5656
5687
|
import { View as View36 } from "react-native";
|
|
5657
5688
|
import { BottomSheetFlatList } from "@gorhom/bottom-sheet";
|
|
5658
5689
|
|
|
@@ -5698,17 +5729,17 @@ function ChatMessageBubble({ message, renderContent, style }) {
|
|
|
5698
5729
|
}
|
|
5699
5730
|
|
|
5700
5731
|
// src/components/chat/TypingIndicator.tsx
|
|
5701
|
-
import * as
|
|
5732
|
+
import * as React35 from "react";
|
|
5702
5733
|
import { Animated as Animated10, View as View35 } from "react-native";
|
|
5703
5734
|
import { jsx as jsx47 } from "react/jsx-runtime";
|
|
5704
5735
|
function TypingIndicator({ style }) {
|
|
5705
5736
|
const theme = useTheme();
|
|
5706
5737
|
const dotColor = theme.colors.textSubtle;
|
|
5707
|
-
const anims =
|
|
5738
|
+
const anims = React35.useMemo(
|
|
5708
5739
|
() => [new Animated10.Value(0.3), new Animated10.Value(0.3), new Animated10.Value(0.3)],
|
|
5709
5740
|
[]
|
|
5710
5741
|
);
|
|
5711
|
-
|
|
5742
|
+
React35.useEffect(() => {
|
|
5712
5743
|
const loops = [];
|
|
5713
5744
|
anims.forEach((a, idx) => {
|
|
5714
5745
|
const seq = Animated10.sequence([
|
|
@@ -5742,7 +5773,7 @@ function TypingIndicator({ style }) {
|
|
|
5742
5773
|
|
|
5743
5774
|
// src/components/chat/ChatMessageList.tsx
|
|
5744
5775
|
import { jsx as jsx48, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
5745
|
-
var ChatMessageList =
|
|
5776
|
+
var ChatMessageList = React36.forwardRef(
|
|
5746
5777
|
({
|
|
5747
5778
|
messages,
|
|
5748
5779
|
showTypingIndicator = false,
|
|
@@ -5753,20 +5784,20 @@ var ChatMessageList = React35.forwardRef(
|
|
|
5753
5784
|
nearBottomThreshold = 200
|
|
5754
5785
|
}, ref) => {
|
|
5755
5786
|
const theme = useTheme();
|
|
5756
|
-
const listRef =
|
|
5757
|
-
const nearBottomRef =
|
|
5758
|
-
const initialScrollDoneRef =
|
|
5759
|
-
const lastMessageIdRef =
|
|
5760
|
-
const data =
|
|
5787
|
+
const listRef = React36.useRef(null);
|
|
5788
|
+
const nearBottomRef = React36.useRef(true);
|
|
5789
|
+
const initialScrollDoneRef = React36.useRef(false);
|
|
5790
|
+
const lastMessageIdRef = React36.useRef(null);
|
|
5791
|
+
const data = React36.useMemo(() => {
|
|
5761
5792
|
return [...messages].reverse();
|
|
5762
5793
|
}, [messages]);
|
|
5763
|
-
const scrollToBottom =
|
|
5794
|
+
const scrollToBottom = React36.useCallback((options) => {
|
|
5764
5795
|
var _a;
|
|
5765
5796
|
const animated = (options == null ? void 0 : options.animated) ?? true;
|
|
5766
5797
|
(_a = listRef.current) == null ? void 0 : _a.scrollToOffset({ offset: 0, animated });
|
|
5767
5798
|
}, []);
|
|
5768
|
-
|
|
5769
|
-
const handleScroll =
|
|
5799
|
+
React36.useImperativeHandle(ref, () => ({ scrollToBottom }), [scrollToBottom]);
|
|
5800
|
+
const handleScroll = React36.useCallback(
|
|
5770
5801
|
(e) => {
|
|
5771
5802
|
const { contentOffset, contentSize, layoutMeasurement } = e.nativeEvent;
|
|
5772
5803
|
const distanceFromBottom = Math.max(contentOffset.y - Math.max(bottomInset, 0), 0);
|
|
@@ -5778,7 +5809,7 @@ var ChatMessageList = React35.forwardRef(
|
|
|
5778
5809
|
},
|
|
5779
5810
|
[bottomInset, nearBottomThreshold, onNearBottomChange]
|
|
5780
5811
|
);
|
|
5781
|
-
|
|
5812
|
+
React36.useEffect(() => {
|
|
5782
5813
|
if (!initialScrollDoneRef.current) return;
|
|
5783
5814
|
const lastId = messages.length > 0 ? messages[messages.length - 1].id : null;
|
|
5784
5815
|
const prevLastId = lastMessageIdRef.current;
|
|
@@ -5788,7 +5819,7 @@ var ChatMessageList = React35.forwardRef(
|
|
|
5788
5819
|
const id = requestAnimationFrame(() => scrollToBottom({ animated: true }));
|
|
5789
5820
|
return () => cancelAnimationFrame(id);
|
|
5790
5821
|
}, [messages, scrollToBottom]);
|
|
5791
|
-
|
|
5822
|
+
React36.useEffect(() => {
|
|
5792
5823
|
if (showTypingIndicator && nearBottomRef.current) {
|
|
5793
5824
|
const id = requestAnimationFrame(() => scrollToBottom({ animated: true }));
|
|
5794
5825
|
return () => cancelAnimationFrame(id);
|
|
@@ -5850,9 +5881,9 @@ function ChatPage({
|
|
|
5850
5881
|
}) {
|
|
5851
5882
|
const theme = useTheme();
|
|
5852
5883
|
const insets = useSafeAreaInsets4();
|
|
5853
|
-
const [composerHeight, setComposerHeight] =
|
|
5854
|
-
const [keyboardVisible, setKeyboardVisible] =
|
|
5855
|
-
|
|
5884
|
+
const [composerHeight, setComposerHeight] = React37.useState(0);
|
|
5885
|
+
const [keyboardVisible, setKeyboardVisible] = React37.useState(false);
|
|
5886
|
+
React37.useEffect(() => {
|
|
5856
5887
|
if (Platform9.OS !== "ios") return;
|
|
5857
5888
|
const show = Keyboard4.addListener("keyboardWillShow", () => setKeyboardVisible(true));
|
|
5858
5889
|
const hide = Keyboard4.addListener("keyboardWillHide", () => setKeyboardVisible(false));
|
|
@@ -5864,12 +5895,12 @@ function ChatPage({
|
|
|
5864
5895
|
const footerBottomPadding = Platform9.OS === "ios" ? keyboardVisible ? 0 : insets.bottom : insets.bottom + 10;
|
|
5865
5896
|
const overlayBottom = composerHeight + footerBottomPadding + theme.spacing.lg;
|
|
5866
5897
|
const bottomInset = composerHeight + footerBottomPadding + theme.spacing.xl;
|
|
5867
|
-
const resolvedOverlay =
|
|
5898
|
+
const resolvedOverlay = React37.useMemo(() => {
|
|
5868
5899
|
var _a;
|
|
5869
5900
|
if (!overlay) return null;
|
|
5870
|
-
if (!
|
|
5901
|
+
if (!React37.isValidElement(overlay)) return overlay;
|
|
5871
5902
|
const prevStyle = (_a = overlay.props) == null ? void 0 : _a.style;
|
|
5872
|
-
return
|
|
5903
|
+
return React37.cloneElement(overlay, {
|
|
5873
5904
|
style: [prevStyle, { bottom: overlayBottom }]
|
|
5874
5905
|
});
|
|
5875
5906
|
}, [overlay, overlayBottom]);
|
|
@@ -5924,15 +5955,15 @@ function ChatPage({
|
|
|
5924
5955
|
}
|
|
5925
5956
|
|
|
5926
5957
|
// src/components/chat/ScrollToBottomButton.tsx
|
|
5927
|
-
import * as
|
|
5958
|
+
import * as React38 from "react";
|
|
5928
5959
|
import { Pressable as Pressable12, View as View38 } from "react-native";
|
|
5929
5960
|
import Animated11, { Easing as Easing2, useAnimatedStyle as useAnimatedStyle2, useSharedValue as useSharedValue2, withTiming as withTiming2 } from "react-native-reanimated";
|
|
5930
5961
|
import { jsx as jsx50 } from "react/jsx-runtime";
|
|
5931
5962
|
function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
5932
5963
|
const theme = useTheme();
|
|
5933
5964
|
const progress = useSharedValue2(visible ? 1 : 0);
|
|
5934
|
-
const [pressed, setPressed] =
|
|
5935
|
-
|
|
5965
|
+
const [pressed, setPressed] = React38.useState(false);
|
|
5966
|
+
React38.useEffect(() => {
|
|
5936
5967
|
progress.value = withTiming2(visible ? 1 : 0, { duration: 200, easing: Easing2.out(Easing2.ease) });
|
|
5937
5968
|
}, [progress, visible]);
|
|
5938
5969
|
const animStyle = useAnimatedStyle2(() => ({
|
|
@@ -6087,9 +6118,9 @@ function ChatPanel({
|
|
|
6087
6118
|
onStartDraw,
|
|
6088
6119
|
onSend
|
|
6089
6120
|
}) {
|
|
6090
|
-
const listRef =
|
|
6091
|
-
const [nearBottom, setNearBottom] =
|
|
6092
|
-
const handleSend =
|
|
6121
|
+
const listRef = React39.useRef(null);
|
|
6122
|
+
const [nearBottom, setNearBottom] = React39.useState(true);
|
|
6123
|
+
const handleSend = React39.useCallback(
|
|
6093
6124
|
async (text, composerAttachments) => {
|
|
6094
6125
|
const all = composerAttachments ?? attachments;
|
|
6095
6126
|
await onSend(text, all.length > 0 ? all : void 0);
|
|
@@ -6103,7 +6134,7 @@ function ChatPanel({
|
|
|
6103
6134
|
},
|
|
6104
6135
|
[attachments, nearBottom, onClearAttachments, onSend]
|
|
6105
6136
|
);
|
|
6106
|
-
const handleScrollToBottom =
|
|
6137
|
+
const handleScrollToBottom = React39.useCallback(() => {
|
|
6107
6138
|
var _a;
|
|
6108
6139
|
(_a = listRef.current) == null ? void 0 : _a.scrollToBottom({ animated: true });
|
|
6109
6140
|
}, []);
|
|
@@ -6177,7 +6208,7 @@ function ChatPanel({
|
|
|
6177
6208
|
}
|
|
6178
6209
|
|
|
6179
6210
|
// src/components/dialogs/ConfirmMergeRequestDialog.tsx
|
|
6180
|
-
import * as
|
|
6211
|
+
import * as React40 from "react";
|
|
6181
6212
|
import { Pressable as Pressable14, View as View43 } from "react-native";
|
|
6182
6213
|
|
|
6183
6214
|
// src/components/primitives/Modal.tsx
|
|
@@ -6229,14 +6260,14 @@ function ConfirmMergeRequestDialog({
|
|
|
6229
6260
|
onTestFirst
|
|
6230
6261
|
}) {
|
|
6231
6262
|
const theme = useTheme();
|
|
6232
|
-
const close =
|
|
6263
|
+
const close = React40.useCallback(() => onOpenChange(false), [onOpenChange]);
|
|
6233
6264
|
const canConfirm = Boolean(mergeRequest) && !approveDisabled;
|
|
6234
|
-
const handleConfirm =
|
|
6265
|
+
const handleConfirm = React40.useCallback(() => {
|
|
6235
6266
|
if (!mergeRequest) return;
|
|
6236
6267
|
onOpenChange(false);
|
|
6237
6268
|
void onConfirm();
|
|
6238
6269
|
}, [mergeRequest, onConfirm, onOpenChange]);
|
|
6239
|
-
const handleTestFirst =
|
|
6270
|
+
const handleTestFirst = React40.useCallback(() => {
|
|
6240
6271
|
if (!mergeRequest) return;
|
|
6241
6272
|
onOpenChange(false);
|
|
6242
6273
|
void onTestFirst(mergeRequest);
|
|
@@ -6385,7 +6416,7 @@ function ConfirmMergeFlow({
|
|
|
6385
6416
|
}
|
|
6386
6417
|
|
|
6387
6418
|
// src/studio/hooks/useOptimisticChatMessages.ts
|
|
6388
|
-
import * as
|
|
6419
|
+
import * as React41 from "react";
|
|
6389
6420
|
function makeOptimisticId() {
|
|
6390
6421
|
return `optimistic:${Date.now().toString(36)}:${Math.random().toString(36).slice(2, 10)}`;
|
|
6391
6422
|
}
|
|
@@ -6423,11 +6454,11 @@ function useOptimisticChatMessages({
|
|
|
6423
6454
|
chatMessages,
|
|
6424
6455
|
onSendChat
|
|
6425
6456
|
}) {
|
|
6426
|
-
const [optimisticChat, setOptimisticChat] =
|
|
6427
|
-
|
|
6457
|
+
const [optimisticChat, setOptimisticChat] = React41.useState([]);
|
|
6458
|
+
React41.useEffect(() => {
|
|
6428
6459
|
setOptimisticChat([]);
|
|
6429
6460
|
}, [threadId]);
|
|
6430
|
-
const messages =
|
|
6461
|
+
const messages = React41.useMemo(() => {
|
|
6431
6462
|
if (!optimisticChat || optimisticChat.length === 0) return chatMessages;
|
|
6432
6463
|
const unresolved = optimisticChat.filter((o) => !isOptimisticResolvedByServer(chatMessages, o));
|
|
6433
6464
|
if (unresolved.length === 0) return chatMessages;
|
|
@@ -6443,7 +6474,7 @@ function useOptimisticChatMessages({
|
|
|
6443
6474
|
merged.sort((a, b) => String(a.createdAt).localeCompare(String(b.createdAt)));
|
|
6444
6475
|
return merged;
|
|
6445
6476
|
}, [chatMessages, optimisticChat]);
|
|
6446
|
-
|
|
6477
|
+
React41.useEffect(() => {
|
|
6447
6478
|
if (optimisticChat.length === 0) return;
|
|
6448
6479
|
setOptimisticChat((prev) => {
|
|
6449
6480
|
if (prev.length === 0) return prev;
|
|
@@ -6451,7 +6482,7 @@ function useOptimisticChatMessages({
|
|
|
6451
6482
|
return next.length === prev.length ? prev : next;
|
|
6452
6483
|
});
|
|
6453
6484
|
}, [chatMessages, optimisticChat.length]);
|
|
6454
|
-
const onSend =
|
|
6485
|
+
const onSend = React41.useCallback(
|
|
6455
6486
|
async (text, attachments) => {
|
|
6456
6487
|
if (shouldForkOnEdit) {
|
|
6457
6488
|
await onSendChat(text, attachments);
|
|
@@ -6503,18 +6534,18 @@ function StudioOverlay({
|
|
|
6503
6534
|
chatShowTypingIndicator,
|
|
6504
6535
|
onSendChat,
|
|
6505
6536
|
onNavigateHome,
|
|
6506
|
-
|
|
6537
|
+
showBubble,
|
|
6507
6538
|
studioControlOptions
|
|
6508
6539
|
}) {
|
|
6509
6540
|
const theme = useTheme();
|
|
6510
6541
|
const { width } = useWindowDimensions4();
|
|
6511
|
-
const [sheetOpen, setSheetOpen] =
|
|
6512
|
-
const sheetOpenRef =
|
|
6513
|
-
const [activePage, setActivePage] =
|
|
6514
|
-
const [drawing, setDrawing] =
|
|
6515
|
-
const [chatAttachments, setChatAttachments] =
|
|
6516
|
-
const [commentsAppId, setCommentsAppId] =
|
|
6517
|
-
const [commentsCount, setCommentsCount] =
|
|
6542
|
+
const [sheetOpen, setSheetOpen] = React42.useState(false);
|
|
6543
|
+
const sheetOpenRef = React42.useRef(sheetOpen);
|
|
6544
|
+
const [activePage, setActivePage] = React42.useState("preview");
|
|
6545
|
+
const [drawing, setDrawing] = React42.useState(false);
|
|
6546
|
+
const [chatAttachments, setChatAttachments] = React42.useState([]);
|
|
6547
|
+
const [commentsAppId, setCommentsAppId] = React42.useState(null);
|
|
6548
|
+
const [commentsCount, setCommentsCount] = React42.useState(null);
|
|
6518
6549
|
const threadId = (app == null ? void 0 : app.threadId) ?? null;
|
|
6519
6550
|
const optimistic = useOptimisticChatMessages({
|
|
6520
6551
|
threadId,
|
|
@@ -6522,24 +6553,24 @@ function StudioOverlay({
|
|
|
6522
6553
|
chatMessages,
|
|
6523
6554
|
onSendChat
|
|
6524
6555
|
});
|
|
6525
|
-
const [confirmMrId, setConfirmMrId] =
|
|
6526
|
-
const confirmMr =
|
|
6556
|
+
const [confirmMrId, setConfirmMrId] = React42.useState(null);
|
|
6557
|
+
const confirmMr = React42.useMemo(
|
|
6527
6558
|
() => confirmMrId ? incomingMergeRequests.find((m) => m.id === confirmMrId) ?? null : null,
|
|
6528
6559
|
[confirmMrId, incomingMergeRequests]
|
|
6529
6560
|
);
|
|
6530
|
-
const handleSheetOpenChange =
|
|
6561
|
+
const handleSheetOpenChange = React42.useCallback((open) => {
|
|
6531
6562
|
setSheetOpen(open);
|
|
6532
6563
|
if (!open) Keyboard5.dismiss();
|
|
6533
6564
|
}, []);
|
|
6534
|
-
const closeSheet =
|
|
6565
|
+
const closeSheet = React42.useCallback(() => {
|
|
6535
6566
|
handleSheetOpenChange(false);
|
|
6536
6567
|
}, [handleSheetOpenChange]);
|
|
6537
|
-
const openSheet =
|
|
6538
|
-
const goToChat =
|
|
6568
|
+
const openSheet = React42.useCallback(() => setSheetOpen(true), []);
|
|
6569
|
+
const goToChat = React42.useCallback(() => {
|
|
6539
6570
|
setActivePage("chat");
|
|
6540
6571
|
openSheet();
|
|
6541
6572
|
}, [openSheet]);
|
|
6542
|
-
const backToPreview =
|
|
6573
|
+
const backToPreview = React42.useCallback(() => {
|
|
6543
6574
|
if (Platform10.OS !== "ios") {
|
|
6544
6575
|
Keyboard5.dismiss();
|
|
6545
6576
|
setActivePage("preview");
|
|
@@ -6557,11 +6588,11 @@ function StudioOverlay({
|
|
|
6557
6588
|
const t = setTimeout(finalize, 350);
|
|
6558
6589
|
Keyboard5.dismiss();
|
|
6559
6590
|
}, []);
|
|
6560
|
-
const startDraw =
|
|
6591
|
+
const startDraw = React42.useCallback(() => {
|
|
6561
6592
|
setDrawing(true);
|
|
6562
6593
|
closeSheet();
|
|
6563
6594
|
}, [closeSheet]);
|
|
6564
|
-
const handleDrawCapture =
|
|
6595
|
+
const handleDrawCapture = React42.useCallback(
|
|
6565
6596
|
(dataUrl) => {
|
|
6566
6597
|
setChatAttachments((prev) => [...prev, dataUrl]);
|
|
6567
6598
|
setDrawing(false);
|
|
@@ -6570,7 +6601,7 @@ function StudioOverlay({
|
|
|
6570
6601
|
},
|
|
6571
6602
|
[openSheet]
|
|
6572
6603
|
);
|
|
6573
|
-
const toggleSheet =
|
|
6604
|
+
const toggleSheet = React42.useCallback(async () => {
|
|
6574
6605
|
if (!sheetOpen) {
|
|
6575
6606
|
const shouldExitTest = Boolean(testingMrId) || isTesting;
|
|
6576
6607
|
if (shouldExitTest) {
|
|
@@ -6582,7 +6613,7 @@ function StudioOverlay({
|
|
|
6582
6613
|
closeSheet();
|
|
6583
6614
|
}
|
|
6584
6615
|
}, [closeSheet, isTesting, onRestoreBase, sheetOpen, testingMrId]);
|
|
6585
|
-
const handleTestMr =
|
|
6616
|
+
const handleTestMr = React42.useCallback(
|
|
6586
6617
|
async (mr) => {
|
|
6587
6618
|
if (!onTestMr) return;
|
|
6588
6619
|
await onTestMr(mr);
|
|
@@ -6590,10 +6621,10 @@ function StudioOverlay({
|
|
|
6590
6621
|
},
|
|
6591
6622
|
[closeSheet, onTestMr]
|
|
6592
6623
|
);
|
|
6593
|
-
|
|
6624
|
+
React42.useEffect(() => {
|
|
6594
6625
|
sheetOpenRef.current = sheetOpen;
|
|
6595
6626
|
}, [sheetOpen]);
|
|
6596
|
-
|
|
6627
|
+
React42.useEffect(() => {
|
|
6597
6628
|
const poller = startStudioControlPolling((action) => {
|
|
6598
6629
|
if (action === "show" && !sheetOpenRef.current) openSheet();
|
|
6599
6630
|
if (action === "hide" && sheetOpenRef.current) closeSheet();
|
|
@@ -6601,7 +6632,7 @@ function StudioOverlay({
|
|
|
6601
6632
|
}, studioControlOptions);
|
|
6602
6633
|
return () => poller.stop();
|
|
6603
6634
|
}, [closeSheet, openSheet, studioControlOptions, toggleSheet]);
|
|
6604
|
-
|
|
6635
|
+
React42.useEffect(() => {
|
|
6605
6636
|
void publishComergeStudioUIState(sheetOpen, studioControlOptions);
|
|
6606
6637
|
}, [sheetOpen, studioControlOptions]);
|
|
6607
6638
|
return /* @__PURE__ */ jsxs34(Fragment6, { children: [
|
|
@@ -6660,8 +6691,8 @@ function StudioOverlay({
|
|
|
6660
6691
|
)
|
|
6661
6692
|
}
|
|
6662
6693
|
) }),
|
|
6663
|
-
|
|
6664
|
-
|
|
6694
|
+
showBubble && /* @__PURE__ */ jsx57(
|
|
6695
|
+
Bubble,
|
|
6665
6696
|
{
|
|
6666
6697
|
visible: !sheetOpen && !drawing,
|
|
6667
6698
|
ariaLabel: sheetOpen ? "Hide studio" : "Show studio",
|
|
@@ -6709,24 +6740,25 @@ function StudioOverlay({
|
|
|
6709
6740
|
import { jsx as jsx58, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
6710
6741
|
function ComergeStudio({
|
|
6711
6742
|
appId,
|
|
6712
|
-
|
|
6743
|
+
clientKey: clientKey2,
|
|
6713
6744
|
appKey = "MicroMain",
|
|
6714
6745
|
onNavigateHome,
|
|
6715
6746
|
style,
|
|
6716
|
-
|
|
6717
|
-
studioControlOptions
|
|
6747
|
+
showBubble = true,
|
|
6748
|
+
studioControlOptions,
|
|
6749
|
+
embeddedBaseBundles
|
|
6718
6750
|
}) {
|
|
6719
|
-
const [activeAppId, setActiveAppId] =
|
|
6720
|
-
const [runtimeAppId, setRuntimeAppId] =
|
|
6721
|
-
const [pendingRuntimeTargetAppId, setPendingRuntimeTargetAppId] =
|
|
6722
|
-
const platform =
|
|
6723
|
-
|
|
6751
|
+
const [activeAppId, setActiveAppId] = React43.useState(appId);
|
|
6752
|
+
const [runtimeAppId, setRuntimeAppId] = React43.useState(appId);
|
|
6753
|
+
const [pendingRuntimeTargetAppId, setPendingRuntimeTargetAppId] = React43.useState(null);
|
|
6754
|
+
const platform = React43.useMemo(() => RNPlatform.OS === "ios" ? "ios" : "android", []);
|
|
6755
|
+
React43.useEffect(() => {
|
|
6724
6756
|
setActiveAppId(appId);
|
|
6725
6757
|
setRuntimeAppId(appId);
|
|
6726
6758
|
setPendingRuntimeTargetAppId(null);
|
|
6727
6759
|
}, [appId]);
|
|
6728
|
-
const captureTargetRef =
|
|
6729
|
-
return /* @__PURE__ */ jsx58(StudioBootstrap, {
|
|
6760
|
+
const captureTargetRef = React43.useRef(null);
|
|
6761
|
+
return /* @__PURE__ */ jsx58(StudioBootstrap, { clientKey: clientKey2, fallback: /* @__PURE__ */ jsx58(View45, { style: { flex: 1 } }), children: ({ userId }) => /* @__PURE__ */ jsx58(BottomSheetModalProvider, { children: /* @__PURE__ */ jsx58(LiquidGlassResetProvider, { resetTriggers: [appId, activeAppId, runtimeAppId], children: /* @__PURE__ */ jsx58(
|
|
6730
6762
|
ComergeStudioInner,
|
|
6731
6763
|
{
|
|
6732
6764
|
userId,
|
|
@@ -6741,8 +6773,9 @@ function ComergeStudio({
|
|
|
6741
6773
|
onNavigateHome,
|
|
6742
6774
|
captureTargetRef,
|
|
6743
6775
|
style,
|
|
6744
|
-
|
|
6745
|
-
studioControlOptions
|
|
6776
|
+
showBubble,
|
|
6777
|
+
studioControlOptions,
|
|
6778
|
+
embeddedBaseBundles
|
|
6746
6779
|
}
|
|
6747
6780
|
) }) }) });
|
|
6748
6781
|
}
|
|
@@ -6759,17 +6792,18 @@ function ComergeStudioInner({
|
|
|
6759
6792
|
onNavigateHome,
|
|
6760
6793
|
captureTargetRef,
|
|
6761
6794
|
style,
|
|
6762
|
-
|
|
6763
|
-
studioControlOptions
|
|
6795
|
+
showBubble,
|
|
6796
|
+
studioControlOptions,
|
|
6797
|
+
embeddedBaseBundles
|
|
6764
6798
|
}) {
|
|
6765
6799
|
const { app, loading: appLoading } = useApp(activeAppId);
|
|
6766
6800
|
const { app: runtimeAppFromHook } = useApp(runtimeAppId, { enabled: runtimeAppId !== activeAppId });
|
|
6767
6801
|
const runtimeApp = runtimeAppId === activeAppId ? app : runtimeAppFromHook;
|
|
6768
|
-
const sawEditingOnPendingTargetRef =
|
|
6769
|
-
|
|
6802
|
+
const sawEditingOnPendingTargetRef = React43.useRef(false);
|
|
6803
|
+
React43.useEffect(() => {
|
|
6770
6804
|
sawEditingOnPendingTargetRef.current = false;
|
|
6771
6805
|
}, [pendingRuntimeTargetAppId]);
|
|
6772
|
-
|
|
6806
|
+
React43.useEffect(() => {
|
|
6773
6807
|
if (!pendingRuntimeTargetAppId) return;
|
|
6774
6808
|
if (activeAppId !== pendingRuntimeTargetAppId) return;
|
|
6775
6809
|
if ((app == null ? void 0 : app.status) === "editing") {
|
|
@@ -6784,15 +6818,16 @@ function ComergeStudioInner({
|
|
|
6784
6818
|
const bundle = useBundleManager({
|
|
6785
6819
|
base: { appId: runtimeAppId, commitId: (runtimeApp == null ? void 0 : runtimeApp.headCommitId) ?? void 0 },
|
|
6786
6820
|
platform,
|
|
6787
|
-
canRequestLatest: (runtimeApp == null ? void 0 : runtimeApp.status) === "ready"
|
|
6821
|
+
canRequestLatest: (runtimeApp == null ? void 0 : runtimeApp.status) === "ready",
|
|
6822
|
+
embeddedBaseBundles
|
|
6788
6823
|
});
|
|
6789
|
-
const sawEditingOnActiveAppRef =
|
|
6790
|
-
const [showPostEditPreparing, setShowPostEditPreparing] =
|
|
6791
|
-
|
|
6824
|
+
const sawEditingOnActiveAppRef = React43.useRef(false);
|
|
6825
|
+
const [showPostEditPreparing, setShowPostEditPreparing] = React43.useState(false);
|
|
6826
|
+
React43.useEffect(() => {
|
|
6792
6827
|
sawEditingOnActiveAppRef.current = false;
|
|
6793
6828
|
setShowPostEditPreparing(false);
|
|
6794
6829
|
}, [activeAppId]);
|
|
6795
|
-
|
|
6830
|
+
React43.useEffect(() => {
|
|
6796
6831
|
if (!(app == null ? void 0 : app.id)) return;
|
|
6797
6832
|
if (app.status === "editing") {
|
|
6798
6833
|
sawEditingOnActiveAppRef.current = true;
|
|
@@ -6804,7 +6839,7 @@ function ComergeStudioInner({
|
|
|
6804
6839
|
sawEditingOnActiveAppRef.current = false;
|
|
6805
6840
|
}
|
|
6806
6841
|
}, [app == null ? void 0 : app.id, app == null ? void 0 : app.status]);
|
|
6807
|
-
|
|
6842
|
+
React43.useEffect(() => {
|
|
6808
6843
|
if (!showPostEditPreparing) return;
|
|
6809
6844
|
const stillProcessingBaseBundle = bundle.loading && bundle.loadingMode === "base" && !bundle.isTesting;
|
|
6810
6845
|
if (!stillProcessingBaseBundle) {
|
|
@@ -6814,10 +6849,10 @@ function ComergeStudioInner({
|
|
|
6814
6849
|
const threadId = (app == null ? void 0 : app.threadId) ?? "";
|
|
6815
6850
|
const thread = useThreadMessages(threadId);
|
|
6816
6851
|
const mergeRequests = useMergeRequests({ appId: activeAppId });
|
|
6817
|
-
const hasOpenOutgoingMr =
|
|
6852
|
+
const hasOpenOutgoingMr = React43.useMemo(() => {
|
|
6818
6853
|
return mergeRequests.lists.outgoing.some((mr) => mr.status === "open");
|
|
6819
6854
|
}, [mergeRequests.lists.outgoing]);
|
|
6820
|
-
const incomingReviewMrs =
|
|
6855
|
+
const incomingReviewMrs = React43.useMemo(() => {
|
|
6821
6856
|
if (!userId) return mergeRequests.lists.incoming;
|
|
6822
6857
|
return mergeRequests.lists.incoming.filter((mr) => mr.createdBy !== userId);
|
|
6823
6858
|
}, [mergeRequests.lists.incoming, userId]);
|
|
@@ -6839,9 +6874,9 @@ function ComergeStudioInner({
|
|
|
6839
6874
|
uploadAttachments: uploader.uploadBase64Images
|
|
6840
6875
|
});
|
|
6841
6876
|
const chatSendDisabled = hasNoOutcomeAfterLastHuman(thread.raw);
|
|
6842
|
-
const [processingMrId, setProcessingMrId] =
|
|
6843
|
-
const [testingMrId, setTestingMrId] =
|
|
6844
|
-
const chatShowTypingIndicator =
|
|
6877
|
+
const [processingMrId, setProcessingMrId] = React43.useState(null);
|
|
6878
|
+
const [testingMrId, setTestingMrId] = React43.useState(null);
|
|
6879
|
+
const chatShowTypingIndicator = React43.useMemo(() => {
|
|
6845
6880
|
var _a;
|
|
6846
6881
|
if (!thread.raw || thread.raw.length === 0) return false;
|
|
6847
6882
|
const last = thread.raw[thread.raw.length - 1];
|
|
@@ -6855,7 +6890,8 @@ function ComergeStudioInner({
|
|
|
6855
6890
|
appKey,
|
|
6856
6891
|
bundlePath: bundle.bundlePath,
|
|
6857
6892
|
forcePreparing: showPostEditPreparing,
|
|
6858
|
-
renderToken: bundle.renderToken
|
|
6893
|
+
renderToken: bundle.renderToken,
|
|
6894
|
+
allowInitialPreparing: !embeddedBaseBundles
|
|
6859
6895
|
}
|
|
6860
6896
|
),
|
|
6861
6897
|
/* @__PURE__ */ jsx58(
|
|
@@ -6911,7 +6947,7 @@ function ComergeStudioInner({
|
|
|
6911
6947
|
chatShowTypingIndicator,
|
|
6912
6948
|
onSendChat: (text, attachments) => actions.sendEdit({ prompt: text, attachments }),
|
|
6913
6949
|
onNavigateHome,
|
|
6914
|
-
|
|
6950
|
+
showBubble,
|
|
6915
6951
|
studioControlOptions
|
|
6916
6952
|
}
|
|
6917
6953
|
)
|