@comergehq/studio 0.1.11 → 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 +22 -2
- package/dist/index.d.ts +22 -2
- package/dist/index.js +352 -290
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +361 -296
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -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 +23 -3
- 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 +41 -12
- package/src/components/floating-draggable-button/index.ts +0 -4
package/dist/index.js
CHANGED
|
@@ -36,7 +36,7 @@ __export(index_exports, {
|
|
|
36
36
|
module.exports = __toCommonJS(index_exports);
|
|
37
37
|
|
|
38
38
|
// src/studio/ComergeStudio.tsx
|
|
39
|
-
var
|
|
39
|
+
var React43 = __toESM(require("react"));
|
|
40
40
|
var import_react_native55 = require("react-native");
|
|
41
41
|
var import_bottom_sheet6 = require("@gorhom/bottom-sheet");
|
|
42
42
|
|
|
@@ -218,11 +218,11 @@ var React = __toESM(require("react"));
|
|
|
218
218
|
var import_axios = __toESM(require("axios"));
|
|
219
219
|
|
|
220
220
|
// src/core/services/http/baseUrl.ts
|
|
221
|
-
var BASE_URL = "https://comerge.ai";
|
|
221
|
+
var BASE_URL = "https://api.comerge.ai";
|
|
222
222
|
|
|
223
223
|
// src/core/services/http/public.ts
|
|
224
224
|
var CLIENT_KEY_HEADER = "x-comerge-api-key";
|
|
225
|
-
var
|
|
225
|
+
var clientKey = null;
|
|
226
226
|
var publicApi = import_axios.default.create({
|
|
227
227
|
baseURL: BASE_URL,
|
|
228
228
|
timeout: 3e4,
|
|
@@ -231,19 +231,19 @@ var publicApi = import_axios.default.create({
|
|
|
231
231
|
"Content-Type": "application/json"
|
|
232
232
|
}
|
|
233
233
|
});
|
|
234
|
-
function
|
|
234
|
+
function setClientKey(clientKeyInput) {
|
|
235
235
|
var _a;
|
|
236
|
-
const trimmed = ((_a =
|
|
236
|
+
const trimmed = ((_a = clientKeyInput == null ? void 0 : clientKeyInput.trim) == null ? void 0 : _a.call(clientKeyInput)) ?? "";
|
|
237
237
|
if (!trimmed) {
|
|
238
|
-
throw new Error("comerge-studio:
|
|
238
|
+
throw new Error("comerge-studio: clientKey is required");
|
|
239
239
|
}
|
|
240
|
-
|
|
240
|
+
clientKey = trimmed;
|
|
241
241
|
publicApi.defaults.headers.common[CLIENT_KEY_HEADER] = trimmed;
|
|
242
242
|
}
|
|
243
243
|
publicApi.interceptors.request.use((config) => {
|
|
244
|
-
if (!
|
|
244
|
+
if (!clientKey) return config;
|
|
245
245
|
config.headers = config.headers ?? {};
|
|
246
|
-
config.headers[CLIENT_KEY_HEADER] =
|
|
246
|
+
config.headers[CLIENT_KEY_HEADER] = clientKey;
|
|
247
247
|
return config;
|
|
248
248
|
});
|
|
249
249
|
|
|
@@ -308,42 +308,9 @@ async function ensureAnonymousSession() {
|
|
|
308
308
|
return { user: data.user, isNew: true };
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
-
// src/data/base-repository.ts
|
|
312
|
-
var BaseRepository = class {
|
|
313
|
-
unwrapOrThrow(res) {
|
|
314
|
-
if (res.success && res.responseObject) return res.responseObject;
|
|
315
|
-
const msg = res.message || "Request failed";
|
|
316
|
-
throw new Error(msg);
|
|
317
|
-
}
|
|
318
|
-
};
|
|
319
|
-
|
|
320
|
-
// src/data/base-remote.ts
|
|
321
|
-
var BaseRemote = class {
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
// src/data/public/studio-config/remote.ts
|
|
325
|
-
var StudioConfigRemoteDataSourceImpl = class extends BaseRemote {
|
|
326
|
-
async get() {
|
|
327
|
-
const { data } = await publicApi.get("/v1/public/studio-config");
|
|
328
|
-
return data;
|
|
329
|
-
}
|
|
330
|
-
};
|
|
331
|
-
var studioConfigRemoteDataSource = new StudioConfigRemoteDataSourceImpl();
|
|
332
|
-
|
|
333
|
-
// src/data/public/studio-config/repository.ts
|
|
334
|
-
var StudioConfigRepositoryImpl = class extends BaseRepository {
|
|
335
|
-
constructor(remote) {
|
|
336
|
-
super();
|
|
337
|
-
this.remote = remote;
|
|
338
|
-
}
|
|
339
|
-
async get() {
|
|
340
|
-
const res = await this.remote.get();
|
|
341
|
-
return this.unwrapOrThrow(res);
|
|
342
|
-
}
|
|
343
|
-
};
|
|
344
|
-
var studioConfigRepository = new StudioConfigRepositoryImpl(studioConfigRemoteDataSource);
|
|
345
|
-
|
|
346
311
|
// src/studio/bootstrap/useStudioBootstrap.ts
|
|
312
|
+
var SUPABASE_URL = "https://xtfxwbckjpfmqubnsusu.supabase.co";
|
|
313
|
+
var SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inh0Znh3YmNranBmbXF1Ym5zdXN1Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjA2MDEyMzAsImV4cCI6MjA3NjE3NzIzMH0.dzWGAWrK4CvrmHVHzf8w7JlUZohdap0ZPnLZnABMV8s";
|
|
347
314
|
function useStudioBootstrap(options) {
|
|
348
315
|
const [state, setState] = React.useState({
|
|
349
316
|
ready: false,
|
|
@@ -354,11 +321,10 @@ function useStudioBootstrap(options) {
|
|
|
354
321
|
let cancelled = false;
|
|
355
322
|
(async () => {
|
|
356
323
|
try {
|
|
357
|
-
|
|
324
|
+
setClientKey(options.clientKey);
|
|
358
325
|
const requireAuth = isSupabaseClientInjected();
|
|
359
326
|
if (!requireAuth) {
|
|
360
|
-
|
|
361
|
-
setSupabaseConfig(cfg);
|
|
327
|
+
setSupabaseConfig({ url: SUPABASE_URL, anonKey: SUPABASE_ANON_KEY });
|
|
362
328
|
}
|
|
363
329
|
const { user } = requireAuth ? await ensureAuthenticatedSession() : await ensureAnonymousSession();
|
|
364
330
|
if (cancelled) return;
|
|
@@ -372,14 +338,14 @@ function useStudioBootstrap(options) {
|
|
|
372
338
|
return () => {
|
|
373
339
|
cancelled = true;
|
|
374
340
|
};
|
|
375
|
-
}, [options.
|
|
341
|
+
}, [options.clientKey]);
|
|
376
342
|
return state;
|
|
377
343
|
}
|
|
378
344
|
|
|
379
345
|
// src/studio/bootstrap/StudioBootstrap.tsx
|
|
380
346
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
381
|
-
function StudioBootstrap({ children, fallback, renderError,
|
|
382
|
-
const { ready, error, userId } = useStudioBootstrap({
|
|
347
|
+
function StudioBootstrap({ children, fallback, renderError, clientKey: clientKey2 }) {
|
|
348
|
+
const { ready, error, userId } = useStudioBootstrap({ clientKey: clientKey2 });
|
|
383
349
|
if (error) {
|
|
384
350
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.View, { style: { flex: 1, justifyContent: "center", alignItems: "center", padding: 24 }, children: renderError ? renderError(error) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { variant: "bodyMuted", children: error.message }) });
|
|
385
351
|
}
|
|
@@ -527,6 +493,10 @@ var createApiClient = (baseURL) => {
|
|
|
527
493
|
};
|
|
528
494
|
var api = createApiClient(BASE_URL);
|
|
529
495
|
|
|
496
|
+
// src/data/base-remote.ts
|
|
497
|
+
var BaseRemote = class {
|
|
498
|
+
};
|
|
499
|
+
|
|
530
500
|
// src/data/apps/remote.ts
|
|
531
501
|
var AppsRemoteDataSourceImpl = class extends BaseRemote {
|
|
532
502
|
async list(projectId) {
|
|
@@ -582,6 +552,15 @@ var AppsRemoteDataSourceImpl = class extends BaseRemote {
|
|
|
582
552
|
};
|
|
583
553
|
var appsRemoteDataSource = new AppsRemoteDataSourceImpl();
|
|
584
554
|
|
|
555
|
+
// src/data/base-repository.ts
|
|
556
|
+
var BaseRepository = class {
|
|
557
|
+
unwrapOrThrow(res) {
|
|
558
|
+
if (res.success && res.responseObject) return res.responseObject;
|
|
559
|
+
const msg = res.message || "Request failed";
|
|
560
|
+
throw new Error(msg);
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
|
|
585
564
|
// src/data/apps/repository.ts
|
|
586
565
|
function mapDbAppRow(row) {
|
|
587
566
|
return {
|
|
@@ -934,6 +913,7 @@ function useThreadMessages(threadId) {
|
|
|
934
913
|
// src/studio/hooks/useBundleManager.ts
|
|
935
914
|
var React5 = __toESM(require("react"));
|
|
936
915
|
var FileSystem = __toESM(require("expo-file-system/legacy"));
|
|
916
|
+
var import_expo_asset = require("expo-asset");
|
|
937
917
|
|
|
938
918
|
// src/data/apps/bundles/remote.ts
|
|
939
919
|
var BundlesRemoteDataSourceImpl = class extends BaseRemote {
|
|
@@ -1092,6 +1072,24 @@ async function deleteFileIfExists(fileUri) {
|
|
|
1092
1072
|
} catch {
|
|
1093
1073
|
}
|
|
1094
1074
|
}
|
|
1075
|
+
async function hydrateBaseFromEmbeddedAsset(appId, platform, embedded) {
|
|
1076
|
+
if (!(embedded == null ? void 0 : embedded.module)) return null;
|
|
1077
|
+
const key = baseBundleKey(appId, platform);
|
|
1078
|
+
const targetUri = toBundleFileUri(key);
|
|
1079
|
+
const existing = await getExistingNonEmptyFileUri(targetUri);
|
|
1080
|
+
if (existing) return { bundlePath: existing, meta: embedded.meta ?? null };
|
|
1081
|
+
const asset = import_expo_asset.Asset.fromModule(embedded.module);
|
|
1082
|
+
await asset.downloadAsync();
|
|
1083
|
+
const sourceUri = asset.localUri ?? asset.uri;
|
|
1084
|
+
if (!sourceUri) return null;
|
|
1085
|
+
const info = await FileSystem.getInfoAsync(sourceUri);
|
|
1086
|
+
if (!info.exists) return null;
|
|
1087
|
+
await deleteFileIfExists(targetUri);
|
|
1088
|
+
await FileSystem.copyAsync({ from: sourceUri, to: targetUri });
|
|
1089
|
+
const finalUri = await getExistingNonEmptyFileUri(targetUri);
|
|
1090
|
+
if (!finalUri) return null;
|
|
1091
|
+
return { bundlePath: finalUri, meta: embedded.meta ?? null };
|
|
1092
|
+
}
|
|
1095
1093
|
async function safeReplaceFileFromUrl(url, targetUri, tmpKey) {
|
|
1096
1094
|
const tmpUri = toBundleFileUri(`tmp:${tmpKey}:${Date.now()}`);
|
|
1097
1095
|
try {
|
|
@@ -1164,7 +1162,8 @@ async function resolveBundlePath(src, platform, mode) {
|
|
|
1164
1162
|
function useBundleManager({
|
|
1165
1163
|
base,
|
|
1166
1164
|
platform,
|
|
1167
|
-
canRequestLatest = true
|
|
1165
|
+
canRequestLatest = true,
|
|
1166
|
+
embeddedBaseBundles
|
|
1168
1167
|
}) {
|
|
1169
1168
|
const [bundlePath, setBundlePath] = React5.useState(null);
|
|
1170
1169
|
const [renderToken, setRenderToken] = React5.useState(0);
|
|
@@ -1175,6 +1174,8 @@ function useBundleManager({
|
|
|
1175
1174
|
const [isTesting, setIsTesting] = React5.useState(false);
|
|
1176
1175
|
const baseRef = React5.useRef(base);
|
|
1177
1176
|
baseRef.current = base;
|
|
1177
|
+
const embeddedBaseBundlesRef = React5.useRef(embeddedBaseBundles);
|
|
1178
|
+
embeddedBaseBundlesRef.current = embeddedBaseBundles;
|
|
1178
1179
|
const baseOpIdRef = React5.useRef(0);
|
|
1179
1180
|
const testOpIdRef = React5.useRef(0);
|
|
1180
1181
|
const activeLoadModeRef = React5.useRef(null);
|
|
@@ -1197,16 +1198,29 @@ function useBundleManager({
|
|
|
1197
1198
|
const hasCompletedFirstNetworkBaseLoadRef = React5.useRef(false);
|
|
1198
1199
|
const hydrateBaseFromDisk = React5.useCallback(
|
|
1199
1200
|
async (appId, reason) => {
|
|
1201
|
+
var _a;
|
|
1200
1202
|
try {
|
|
1201
1203
|
const dir = bundlesCacheDir();
|
|
1202
1204
|
await ensureDir(dir);
|
|
1203
1205
|
const key = baseBundleKey(appId, platform);
|
|
1204
1206
|
const uri = toBundleFileUri(key);
|
|
1205
|
-
|
|
1207
|
+
let existing = await getExistingNonEmptyFileUri(uri);
|
|
1208
|
+
let embeddedMeta = null;
|
|
1209
|
+
if (!existing) {
|
|
1210
|
+
const embedded = (_a = embeddedBaseBundlesRef.current) == null ? void 0 : _a[platform];
|
|
1211
|
+
const hydrated = await hydrateBaseFromEmbeddedAsset(appId, platform, embedded);
|
|
1212
|
+
if (hydrated == null ? void 0 : hydrated.bundlePath) {
|
|
1213
|
+
existing = hydrated.bundlePath;
|
|
1214
|
+
embeddedMeta = hydrated.meta ?? null;
|
|
1215
|
+
if (embeddedMeta) {
|
|
1216
|
+
await writeJsonFile(toBundleMetaFileUri(key), embeddedMeta);
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1206
1220
|
if (existing) {
|
|
1207
1221
|
lastBaseBundlePathRef.current = existing;
|
|
1208
1222
|
setBundlePath(existing);
|
|
1209
|
-
const meta = await readJsonFile(toBundleMetaFileUri(key));
|
|
1223
|
+
const meta = embeddedMeta ?? await readJsonFile(toBundleMetaFileUri(key));
|
|
1210
1224
|
if (meta == null ? void 0 : meta.fingerprint) {
|
|
1211
1225
|
lastBaseFingerprintRef.current = meta.fingerprint;
|
|
1212
1226
|
}
|
|
@@ -1793,11 +1807,28 @@ function hasNoOutcomeAfterLastHuman(messages) {
|
|
|
1793
1807
|
}
|
|
1794
1808
|
|
|
1795
1809
|
// src/studio/ui/RuntimeRenderer.tsx
|
|
1810
|
+
var React9 = __toESM(require("react"));
|
|
1796
1811
|
var import_react_native6 = require("react-native");
|
|
1797
1812
|
var import_runtime = require("@comergehq/runtime");
|
|
1798
1813
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1799
|
-
function RuntimeRenderer({
|
|
1814
|
+
function RuntimeRenderer({
|
|
1815
|
+
appKey,
|
|
1816
|
+
bundlePath,
|
|
1817
|
+
forcePreparing,
|
|
1818
|
+
renderToken,
|
|
1819
|
+
style,
|
|
1820
|
+
allowInitialPreparing = true
|
|
1821
|
+
}) {
|
|
1822
|
+
const [hasRenderedOnce, setHasRenderedOnce] = React9.useState(false);
|
|
1823
|
+
React9.useEffect(() => {
|
|
1824
|
+
if (bundlePath) {
|
|
1825
|
+
setHasRenderedOnce(true);
|
|
1826
|
+
}
|
|
1827
|
+
}, [bundlePath]);
|
|
1800
1828
|
if (!bundlePath || forcePreparing) {
|
|
1829
|
+
if (!hasRenderedOnce && !forcePreparing && !allowInitialPreparing) {
|
|
1830
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native6.View, { style: [{ flex: 1 }, style] });
|
|
1831
|
+
}
|
|
1801
1832
|
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" }) });
|
|
1802
1833
|
}
|
|
1803
1834
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native6.View, { style: [{ flex: 1 }, style], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
@@ -1812,11 +1843,11 @@ function RuntimeRenderer({ appKey, bundlePath, forcePreparing, renderToken, styl
|
|
|
1812
1843
|
}
|
|
1813
1844
|
|
|
1814
1845
|
// src/studio/ui/StudioOverlay.tsx
|
|
1815
|
-
var
|
|
1846
|
+
var React42 = __toESM(require("react"));
|
|
1816
1847
|
var import_react_native54 = require("react-native");
|
|
1817
1848
|
|
|
1818
1849
|
// src/components/studio-sheet/StudioBottomSheet.tsx
|
|
1819
|
-
var
|
|
1850
|
+
var React12 = __toESM(require("react"));
|
|
1820
1851
|
var import_react_native9 = require("react-native");
|
|
1821
1852
|
var import_bottom_sheet = __toESM(require("@gorhom/bottom-sheet"));
|
|
1822
1853
|
var import_react_native_safe_area_context = require("react-native-safe-area-context");
|
|
@@ -1826,20 +1857,20 @@ var import_react_native8 = require("react-native");
|
|
|
1826
1857
|
var import_liquid_glass2 = require("@callstack/liquid-glass");
|
|
1827
1858
|
|
|
1828
1859
|
// src/components/utils/ResettableLiquidGlassView.tsx
|
|
1829
|
-
var
|
|
1860
|
+
var React11 = __toESM(require("react"));
|
|
1830
1861
|
var import_liquid_glass = require("@callstack/liquid-glass");
|
|
1831
1862
|
|
|
1832
1863
|
// src/components/utils/liquidGlassReset.tsx
|
|
1833
|
-
var
|
|
1864
|
+
var React10 = __toESM(require("react"));
|
|
1834
1865
|
var import_react_native7 = require("react-native");
|
|
1835
1866
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1836
|
-
var LiquidGlassResetContext =
|
|
1867
|
+
var LiquidGlassResetContext = React10.createContext(0);
|
|
1837
1868
|
function LiquidGlassResetProvider({
|
|
1838
1869
|
children,
|
|
1839
1870
|
resetTriggers = []
|
|
1840
1871
|
}) {
|
|
1841
|
-
const [token, setToken] =
|
|
1842
|
-
|
|
1872
|
+
const [token, setToken] = React10.useState(0);
|
|
1873
|
+
React10.useEffect(() => {
|
|
1843
1874
|
if (import_react_native7.Platform.OS !== "ios") return;
|
|
1844
1875
|
const onChange = (state) => {
|
|
1845
1876
|
if (state === "active") setToken((t) => t + 1);
|
|
@@ -1847,21 +1878,21 @@ function LiquidGlassResetProvider({
|
|
|
1847
1878
|
const sub = import_react_native7.AppState.addEventListener("change", onChange);
|
|
1848
1879
|
return () => sub.remove();
|
|
1849
1880
|
}, []);
|
|
1850
|
-
|
|
1881
|
+
React10.useEffect(() => {
|
|
1851
1882
|
setToken((t) => t + 1);
|
|
1852
1883
|
}, resetTriggers);
|
|
1853
1884
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LiquidGlassResetContext.Provider, { value: token, children });
|
|
1854
1885
|
}
|
|
1855
1886
|
function useLiquidGlassResetToken() {
|
|
1856
|
-
return
|
|
1887
|
+
return React10.useContext(LiquidGlassResetContext);
|
|
1857
1888
|
}
|
|
1858
1889
|
|
|
1859
1890
|
// src/components/utils/ResettableLiquidGlassView.tsx
|
|
1860
1891
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1861
1892
|
function ResettableLiquidGlassView({ children, ...props }) {
|
|
1862
1893
|
const token = useLiquidGlassResetToken();
|
|
1863
|
-
const [layoutBootKey, setLayoutBootKey] =
|
|
1864
|
-
const sawNonZeroLayoutRef =
|
|
1894
|
+
const [layoutBootKey, setLayoutBootKey] = React11.useState(0);
|
|
1895
|
+
const sawNonZeroLayoutRef = React11.useRef(false);
|
|
1865
1896
|
const onLayout = (e) => {
|
|
1866
1897
|
var _a;
|
|
1867
1898
|
(_a = props.onLayout) == null ? void 0 : _a.call(props, e);
|
|
@@ -1935,11 +1966,11 @@ function StudioBottomSheet({
|
|
|
1935
1966
|
}) {
|
|
1936
1967
|
const theme = useTheme();
|
|
1937
1968
|
const insets = (0, import_react_native_safe_area_context.useSafeAreaInsets)();
|
|
1938
|
-
const internalSheetRef =
|
|
1969
|
+
const internalSheetRef = React12.useRef(null);
|
|
1939
1970
|
const resolvedSheetRef = sheetRef ?? internalSheetRef;
|
|
1940
|
-
const currentIndexRef =
|
|
1941
|
-
const lastAppStateRef =
|
|
1942
|
-
|
|
1971
|
+
const currentIndexRef = React12.useRef(open ? snapPoints.length - 1 : -1);
|
|
1972
|
+
const lastAppStateRef = React12.useRef(import_react_native9.AppState.currentState);
|
|
1973
|
+
React12.useEffect(() => {
|
|
1943
1974
|
const sub = import_react_native9.AppState.addEventListener("change", (state) => {
|
|
1944
1975
|
const prev = lastAppStateRef.current;
|
|
1945
1976
|
lastAppStateRef.current = state;
|
|
@@ -1959,7 +1990,7 @@ function StudioBottomSheet({
|
|
|
1959
1990
|
});
|
|
1960
1991
|
return () => sub.remove();
|
|
1961
1992
|
}, [open, resolvedSheetRef]);
|
|
1962
|
-
|
|
1993
|
+
React12.useEffect(() => {
|
|
1963
1994
|
const sheet = resolvedSheetRef.current;
|
|
1964
1995
|
if (!sheet) return;
|
|
1965
1996
|
if (open) {
|
|
@@ -1968,7 +1999,7 @@ function StudioBottomSheet({
|
|
|
1968
1999
|
sheet.close();
|
|
1969
2000
|
}
|
|
1970
2001
|
}, [open, resolvedSheetRef, snapPoints.length]);
|
|
1971
|
-
const handleChange =
|
|
2002
|
+
const handleChange = React12.useCallback(
|
|
1972
2003
|
(index) => {
|
|
1973
2004
|
currentIndexRef.current = index;
|
|
1974
2005
|
onOpenChange == null ? void 0 : onOpenChange(index >= 0);
|
|
@@ -1997,12 +2028,12 @@ function StudioBottomSheet({
|
|
|
1997
2028
|
}
|
|
1998
2029
|
|
|
1999
2030
|
// src/components/studio-sheet/StudioSheetPager.tsx
|
|
2000
|
-
var
|
|
2031
|
+
var React13 = __toESM(require("react"));
|
|
2001
2032
|
var import_react_native10 = require("react-native");
|
|
2002
2033
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
2003
2034
|
function StudioSheetPager({ activePage, width, preview, chat, style }) {
|
|
2004
|
-
const anim =
|
|
2005
|
-
|
|
2035
|
+
const anim = React13.useRef(new import_react_native10.Animated.Value(activePage === "chat" ? 1 : 0)).current;
|
|
2036
|
+
React13.useEffect(() => {
|
|
2006
2037
|
import_react_native10.Animated.spring(anim, {
|
|
2007
2038
|
toValue: activePage === "chat" ? 1 : 0,
|
|
2008
2039
|
useNativeDriver: true,
|
|
@@ -2050,14 +2081,14 @@ function StudioSheetPager({ activePage, width, preview, chat, style }) {
|
|
|
2050
2081
|
] });
|
|
2051
2082
|
}
|
|
2052
2083
|
|
|
2053
|
-
// src/components/
|
|
2084
|
+
// src/components/bubble/Bubble.tsx
|
|
2054
2085
|
var import_react = require("react");
|
|
2055
2086
|
var import_react_native11 = require("react-native");
|
|
2056
2087
|
var Haptics = __toESM(require("expo-haptics"));
|
|
2057
2088
|
var import_react_native_reanimated = __toESM(require("react-native-reanimated"));
|
|
2058
2089
|
var import_liquid_glass3 = require("@callstack/liquid-glass");
|
|
2059
2090
|
|
|
2060
|
-
// src/components/
|
|
2091
|
+
// src/components/bubble/constants.ts
|
|
2061
2092
|
var DEFAULT_SIZE = 48;
|
|
2062
2093
|
var DEFAULT_EDGE_PADDING = 10;
|
|
2063
2094
|
var DEFAULT_OFFSET = {
|
|
@@ -2068,7 +2099,7 @@ var ENTER_SCALE_FROM = 0.3;
|
|
|
2068
2099
|
var ENTER_ROTATION_FROM_DEG = -180;
|
|
2069
2100
|
var PULSE_DURATION_MS = 900;
|
|
2070
2101
|
|
|
2071
|
-
// src/components/
|
|
2102
|
+
// src/components/bubble/Bubble.tsx
|
|
2072
2103
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
2073
2104
|
var HIDDEN_OFFSET_X = 20;
|
|
2074
2105
|
var SPRING_POSITION = { damping: 12, stiffness: 100, mass: 0.8 };
|
|
@@ -2090,7 +2121,7 @@ function getHiddenTranslateY(height) {
|
|
|
2090
2121
|
function getFinalTranslateY(height, size, bottomOffset) {
|
|
2091
2122
|
return height - size - bottomOffset;
|
|
2092
2123
|
}
|
|
2093
|
-
function
|
|
2124
|
+
function Bubble({
|
|
2094
2125
|
onPress,
|
|
2095
2126
|
size = DEFAULT_SIZE,
|
|
2096
2127
|
disabled = false,
|
|
@@ -2315,7 +2346,7 @@ var styles = import_react_native11.StyleSheet.create({
|
|
|
2315
2346
|
});
|
|
2316
2347
|
|
|
2317
2348
|
// src/components/overlays/EdgeGlowFrame.tsx
|
|
2318
|
-
var
|
|
2349
|
+
var React14 = __toESM(require("react"));
|
|
2319
2350
|
var import_react_native12 = require("react-native");
|
|
2320
2351
|
var import_expo_linear_gradient = require("expo-linear-gradient");
|
|
2321
2352
|
|
|
@@ -2358,8 +2389,8 @@ function EdgeGlowFrame({
|
|
|
2358
2389
|
}) {
|
|
2359
2390
|
const theme = useTheme();
|
|
2360
2391
|
const alpha = Math.max(0, Math.min(1, intensity));
|
|
2361
|
-
const anim =
|
|
2362
|
-
|
|
2392
|
+
const anim = React14.useRef(new import_react_native12.Animated.Value(visible ? 1 : 0)).current;
|
|
2393
|
+
React14.useEffect(() => {
|
|
2363
2394
|
import_react_native12.Animated.timing(anim, {
|
|
2364
2395
|
toValue: visible ? 1 : 0,
|
|
2365
2396
|
duration: 300,
|
|
@@ -2410,12 +2441,12 @@ function EdgeGlowFrame({
|
|
|
2410
2441
|
}
|
|
2411
2442
|
|
|
2412
2443
|
// src/components/draw/DrawModeOverlay.tsx
|
|
2413
|
-
var
|
|
2444
|
+
var React17 = __toESM(require("react"));
|
|
2414
2445
|
var import_react_native16 = require("react-native");
|
|
2415
2446
|
var import_react_native_view_shot = require("react-native-view-shot");
|
|
2416
2447
|
|
|
2417
2448
|
// src/components/draw/DrawSurface.tsx
|
|
2418
|
-
var
|
|
2449
|
+
var React15 = __toESM(require("react"));
|
|
2419
2450
|
var import_react_native13 = require("react-native");
|
|
2420
2451
|
var import_react_native_svg = __toESM(require("react-native-svg"));
|
|
2421
2452
|
|
|
@@ -2447,25 +2478,25 @@ function DrawSurface({
|
|
|
2447
2478
|
style,
|
|
2448
2479
|
minDistance = 1
|
|
2449
2480
|
}) {
|
|
2450
|
-
const [renderTick, setRenderTick] =
|
|
2451
|
-
const currentPointsRef =
|
|
2452
|
-
const rafRef =
|
|
2453
|
-
const triggerRender =
|
|
2481
|
+
const [renderTick, setRenderTick] = React15.useState(0);
|
|
2482
|
+
const currentPointsRef = React15.useRef([]);
|
|
2483
|
+
const rafRef = React15.useRef(null);
|
|
2484
|
+
const triggerRender = React15.useCallback(() => {
|
|
2454
2485
|
if (rafRef.current !== null) return;
|
|
2455
2486
|
rafRef.current = requestAnimationFrame(() => {
|
|
2456
2487
|
rafRef.current = null;
|
|
2457
2488
|
setRenderTick((n) => n + 1);
|
|
2458
2489
|
});
|
|
2459
2490
|
}, []);
|
|
2460
|
-
|
|
2491
|
+
React15.useEffect(() => () => {
|
|
2461
2492
|
if (rafRef.current !== null) cancelAnimationFrame(rafRef.current);
|
|
2462
2493
|
}, []);
|
|
2463
|
-
const onStart =
|
|
2494
|
+
const onStart = React15.useCallback((e) => {
|
|
2464
2495
|
const { locationX, locationY } = e.nativeEvent;
|
|
2465
2496
|
currentPointsRef.current = [{ x: locationX, y: locationY }];
|
|
2466
2497
|
triggerRender();
|
|
2467
2498
|
}, [triggerRender]);
|
|
2468
|
-
const onMove =
|
|
2499
|
+
const onMove = React15.useCallback((e, _g) => {
|
|
2469
2500
|
const { locationX, locationY } = e.nativeEvent;
|
|
2470
2501
|
const pts = currentPointsRef.current;
|
|
2471
2502
|
if (pts.length > 0) {
|
|
@@ -2478,7 +2509,7 @@ function DrawSurface({
|
|
|
2478
2509
|
currentPointsRef.current = [...pts, { x: locationX, y: locationY }];
|
|
2479
2510
|
triggerRender();
|
|
2480
2511
|
}, [minDistance, triggerRender]);
|
|
2481
|
-
const onEnd =
|
|
2512
|
+
const onEnd = React15.useCallback(() => {
|
|
2482
2513
|
const points = currentPointsRef.current;
|
|
2483
2514
|
if (points.length > 0) {
|
|
2484
2515
|
onAddStroke({ points, color, width: strokeWidth });
|
|
@@ -2486,7 +2517,7 @@ function DrawSurface({
|
|
|
2486
2517
|
currentPointsRef.current = [];
|
|
2487
2518
|
triggerRender();
|
|
2488
2519
|
}, [color, onAddStroke, strokeWidth, triggerRender]);
|
|
2489
|
-
const panResponder =
|
|
2520
|
+
const panResponder = React15.useMemo(
|
|
2490
2521
|
() => import_react_native13.PanResponder.create({
|
|
2491
2522
|
onStartShouldSetPanResponder: () => true,
|
|
2492
2523
|
onMoveShouldSetPanResponder: () => true,
|
|
@@ -2536,7 +2567,7 @@ var styles2 = import_react_native13.StyleSheet.create({
|
|
|
2536
2567
|
});
|
|
2537
2568
|
|
|
2538
2569
|
// src/components/draw/DrawToolbar.tsx
|
|
2539
|
-
var
|
|
2570
|
+
var React16 = __toESM(require("react"));
|
|
2540
2571
|
var import_react_native15 = require("react-native");
|
|
2541
2572
|
var import_react_native_safe_area_context2 = require("react-native-safe-area-context");
|
|
2542
2573
|
var import_lucide_react_native = require("lucide-react-native");
|
|
@@ -2626,11 +2657,11 @@ function DrawToolbar({
|
|
|
2626
2657
|
}) {
|
|
2627
2658
|
const insets = (0, import_react_native_safe_area_context2.useSafeAreaInsets)();
|
|
2628
2659
|
const { width: screenWidth, height: screenHeight } = (0, import_react_native15.useWindowDimensions)();
|
|
2629
|
-
const [expanded, setExpanded] =
|
|
2630
|
-
const pos =
|
|
2631
|
-
const start =
|
|
2632
|
-
const currentPos =
|
|
2633
|
-
|
|
2660
|
+
const [expanded, setExpanded] = React16.useState(false);
|
|
2661
|
+
const pos = React16.useRef(new import_react_native15.Animated.ValueXY({ x: screenWidth / 2 - 110, y: -140 })).current;
|
|
2662
|
+
const start = React16.useRef({ x: 0, y: 0 });
|
|
2663
|
+
const currentPos = React16.useRef({ x: 0, y: 0 });
|
|
2664
|
+
React16.useEffect(() => {
|
|
2634
2665
|
if (hidden) return;
|
|
2635
2666
|
import_react_native15.Animated.spring(pos.y, {
|
|
2636
2667
|
toValue: insets.top + 60,
|
|
@@ -2640,7 +2671,7 @@ function DrawToolbar({
|
|
|
2640
2671
|
mass: 0.8
|
|
2641
2672
|
}).start();
|
|
2642
2673
|
}, [hidden, insets.top, pos.y]);
|
|
2643
|
-
|
|
2674
|
+
React16.useEffect(() => {
|
|
2644
2675
|
const id = pos.addListener((v) => {
|
|
2645
2676
|
currentPos.current = { x: v.x ?? 0, y: v.y ?? 0 };
|
|
2646
2677
|
});
|
|
@@ -2648,7 +2679,7 @@ function DrawToolbar({
|
|
|
2648
2679
|
pos.removeListener(id);
|
|
2649
2680
|
};
|
|
2650
2681
|
}, [pos]);
|
|
2651
|
-
const clamp2 =
|
|
2682
|
+
const clamp2 = React16.useCallback(
|
|
2652
2683
|
(x, y) => {
|
|
2653
2684
|
const minX = 10;
|
|
2654
2685
|
const maxX = Math.max(10, screenWidth - 230);
|
|
@@ -2658,7 +2689,7 @@ function DrawToolbar({
|
|
|
2658
2689
|
},
|
|
2659
2690
|
[insets.top, screenHeight, screenWidth]
|
|
2660
2691
|
);
|
|
2661
|
-
const panResponder =
|
|
2692
|
+
const panResponder = React16.useMemo(
|
|
2662
2693
|
() => import_react_native15.PanResponder.create({
|
|
2663
2694
|
onStartShouldSetPanResponder: () => false,
|
|
2664
2695
|
onMoveShouldSetPanResponder: (_e, g) => Math.abs(g.dx) > 5 || Math.abs(g.dy) > 5,
|
|
@@ -2686,7 +2717,7 @@ function DrawToolbar({
|
|
|
2686
2717
|
children
|
|
2687
2718
|
}) {
|
|
2688
2719
|
const isDisabled = Boolean(disabled) || Boolean(capturingDisabled);
|
|
2689
|
-
const [pressed, setPressed] =
|
|
2720
|
+
const [pressed, setPressed] = React16.useState(false);
|
|
2690
2721
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2691
2722
|
import_react_native15.View,
|
|
2692
2723
|
{
|
|
@@ -2824,7 +2855,7 @@ function DrawModeOverlay({
|
|
|
2824
2855
|
renderDragHandle
|
|
2825
2856
|
}) {
|
|
2826
2857
|
const theme = useTheme();
|
|
2827
|
-
const defaultPalette =
|
|
2858
|
+
const defaultPalette = React17.useMemo(
|
|
2828
2859
|
() => [
|
|
2829
2860
|
"#EF4444",
|
|
2830
2861
|
// Red
|
|
@@ -2842,11 +2873,11 @@ function DrawModeOverlay({
|
|
|
2842
2873
|
[]
|
|
2843
2874
|
);
|
|
2844
2875
|
const colors = palette && palette.length > 0 ? palette : defaultPalette;
|
|
2845
|
-
const [selectedColor, setSelectedColor] =
|
|
2846
|
-
const [strokes, setStrokes] =
|
|
2847
|
-
const [capturing, setCapturing] =
|
|
2848
|
-
const [hideUi, setHideUi] =
|
|
2849
|
-
|
|
2876
|
+
const [selectedColor, setSelectedColor] = React17.useState(colors[0] ?? "#EF4444");
|
|
2877
|
+
const [strokes, setStrokes] = React17.useState([]);
|
|
2878
|
+
const [capturing, setCapturing] = React17.useState(false);
|
|
2879
|
+
const [hideUi, setHideUi] = React17.useState(false);
|
|
2880
|
+
React17.useEffect(() => {
|
|
2850
2881
|
if (!visible) return;
|
|
2851
2882
|
setStrokes([]);
|
|
2852
2883
|
setSelectedColor(colors[0] ?? "#EF4444");
|
|
@@ -2854,14 +2885,14 @@ function DrawModeOverlay({
|
|
|
2854
2885
|
setHideUi(false);
|
|
2855
2886
|
}, [colors, visible]);
|
|
2856
2887
|
const canUndo = strokes.length > 0;
|
|
2857
|
-
const handleUndo =
|
|
2888
|
+
const handleUndo = React17.useCallback(() => {
|
|
2858
2889
|
setStrokes((prev) => prev.slice(0, -1));
|
|
2859
2890
|
}, []);
|
|
2860
|
-
const handleCancel =
|
|
2891
|
+
const handleCancel = React17.useCallback(() => {
|
|
2861
2892
|
setStrokes([]);
|
|
2862
2893
|
onCancel();
|
|
2863
2894
|
}, [onCancel]);
|
|
2864
|
-
const handleDone =
|
|
2895
|
+
const handleDone = React17.useCallback(async () => {
|
|
2865
2896
|
if (!captureTargetRef.current || capturing) return;
|
|
2866
2897
|
try {
|
|
2867
2898
|
setCapturing(true);
|
|
@@ -2921,7 +2952,7 @@ var styles3 = import_react_native16.StyleSheet.create({
|
|
|
2921
2952
|
});
|
|
2922
2953
|
|
|
2923
2954
|
// src/components/comments/AppCommentsSheet.tsx
|
|
2924
|
-
var
|
|
2955
|
+
var React24 = __toESM(require("react"));
|
|
2925
2956
|
var import_react_native22 = require("react-native");
|
|
2926
2957
|
var import_bottom_sheet3 = require("@gorhom/bottom-sheet");
|
|
2927
2958
|
var import_react_native_safe_area_context3 = require("react-native-safe-area-context");
|
|
@@ -2929,17 +2960,17 @@ var import_liquid_glass5 = require("@callstack/liquid-glass");
|
|
|
2929
2960
|
var import_lucide_react_native4 = require("lucide-react-native");
|
|
2930
2961
|
|
|
2931
2962
|
// src/components/chat/ChatComposer.tsx
|
|
2932
|
-
var
|
|
2963
|
+
var React19 = __toESM(require("react"));
|
|
2933
2964
|
var import_react_native18 = require("react-native");
|
|
2934
2965
|
var import_liquid_glass4 = require("@callstack/liquid-glass");
|
|
2935
2966
|
var import_lucide_react_native3 = require("lucide-react-native");
|
|
2936
2967
|
|
|
2937
2968
|
// src/components/chat/MultilineTextInput.tsx
|
|
2938
|
-
var
|
|
2969
|
+
var React18 = __toESM(require("react"));
|
|
2939
2970
|
var import_react_native17 = require("react-native");
|
|
2940
2971
|
var import_bottom_sheet2 = require("@gorhom/bottom-sheet");
|
|
2941
2972
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
2942
|
-
var MultilineTextInput =
|
|
2973
|
+
var MultilineTextInput = React18.forwardRef(function MultilineTextInput2({ useBottomSheetTextInput = false, placeholder, placeholderTextColor, style, ...props }, ref) {
|
|
2943
2974
|
const theme = useTheme();
|
|
2944
2975
|
const baseStyle = {
|
|
2945
2976
|
minHeight: 44,
|
|
@@ -3011,7 +3042,7 @@ function AspectRatioThumbnail({
|
|
|
3011
3042
|
onRemove,
|
|
3012
3043
|
renderRemoveIcon
|
|
3013
3044
|
}) {
|
|
3014
|
-
const [aspectRatio, setAspectRatio] =
|
|
3045
|
+
const [aspectRatio, setAspectRatio] = React19.useState(1);
|
|
3015
3046
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_react_native18.View, { style: { height: THUMBNAIL_HEIGHT, aspectRatio, position: "relative" }, children: [
|
|
3016
3047
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native18.View, { style: { flex: 1, borderRadius: 8, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3017
3048
|
import_react_native18.Image,
|
|
@@ -3068,19 +3099,19 @@ function ChatComposer({
|
|
|
3068
3099
|
style
|
|
3069
3100
|
}) {
|
|
3070
3101
|
const theme = useTheme();
|
|
3071
|
-
const [internal, setInternal] =
|
|
3102
|
+
const [internal, setInternal] = React19.useState("");
|
|
3072
3103
|
const text = value ?? internal;
|
|
3073
3104
|
const setText = onChangeValue ?? setInternal;
|
|
3074
3105
|
const hasAttachments = attachments.length > 0;
|
|
3075
3106
|
const hasText = text.trim().length > 0;
|
|
3076
3107
|
const composerMinHeight = hasAttachments ? THUMBNAIL_HEIGHT + 44 + 24 : 44;
|
|
3077
3108
|
const isButtonDisabled = sending || disabled || sendDisabled;
|
|
3078
|
-
const maxInputHeight =
|
|
3079
|
-
const shakeAnim =
|
|
3080
|
-
const [sendPressed, setSendPressed] =
|
|
3081
|
-
const inputRef =
|
|
3082
|
-
const prevAutoFocusRef =
|
|
3083
|
-
|
|
3109
|
+
const maxInputHeight = React19.useMemo(() => import_react_native18.Dimensions.get("window").height * 0.5, []);
|
|
3110
|
+
const shakeAnim = React19.useRef(new import_react_native18.Animated.Value(0)).current;
|
|
3111
|
+
const [sendPressed, setSendPressed] = React19.useState(false);
|
|
3112
|
+
const inputRef = React19.useRef(null);
|
|
3113
|
+
const prevAutoFocusRef = React19.useRef(false);
|
|
3114
|
+
React19.useEffect(() => {
|
|
3084
3115
|
const shouldFocus = autoFocus && !prevAutoFocusRef.current && !disabled && !sending;
|
|
3085
3116
|
prevAutoFocusRef.current = autoFocus;
|
|
3086
3117
|
if (!shouldFocus) return;
|
|
@@ -3090,7 +3121,7 @@ function ChatComposer({
|
|
|
3090
3121
|
}, 75);
|
|
3091
3122
|
return () => clearTimeout(t);
|
|
3092
3123
|
}, [autoFocus, disabled, sending]);
|
|
3093
|
-
const triggerShake =
|
|
3124
|
+
const triggerShake = React19.useCallback(() => {
|
|
3094
3125
|
shakeAnim.setValue(0);
|
|
3095
3126
|
import_react_native18.Animated.sequence([
|
|
3096
3127
|
import_react_native18.Animated.timing(shakeAnim, { toValue: 10, duration: 50, useNativeDriver: true }),
|
|
@@ -3100,7 +3131,7 @@ function ChatComposer({
|
|
|
3100
3131
|
import_react_native18.Animated.timing(shakeAnim, { toValue: 0, duration: 50, useNativeDriver: true })
|
|
3101
3132
|
]).start();
|
|
3102
3133
|
}, [shakeAnim]);
|
|
3103
|
-
const handleSend =
|
|
3134
|
+
const handleSend = React19.useCallback(async () => {
|
|
3104
3135
|
if (isButtonDisabled) return;
|
|
3105
3136
|
if (!hasText) {
|
|
3106
3137
|
triggerShake();
|
|
@@ -3233,7 +3264,7 @@ function ChatComposer({
|
|
|
3233
3264
|
}
|
|
3234
3265
|
|
|
3235
3266
|
// src/components/comments/CommentRow.tsx
|
|
3236
|
-
var
|
|
3267
|
+
var React20 = __toESM(require("react"));
|
|
3237
3268
|
var import_react_native20 = require("react-native");
|
|
3238
3269
|
|
|
3239
3270
|
// src/components/primitives/Avatar.tsx
|
|
@@ -3305,9 +3336,9 @@ function formatTimeAgo(iso) {
|
|
|
3305
3336
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
3306
3337
|
function CommentRow({ comment, showDivider }) {
|
|
3307
3338
|
const theme = useTheme();
|
|
3308
|
-
const [authorName, setAuthorName] =
|
|
3309
|
-
const [authorAvatar, setAuthorAvatar] =
|
|
3310
|
-
|
|
3339
|
+
const [authorName, setAuthorName] = React20.useState(null);
|
|
3340
|
+
const [authorAvatar, setAuthorAvatar] = React20.useState(null);
|
|
3341
|
+
React20.useEffect(() => {
|
|
3311
3342
|
let cancelled = false;
|
|
3312
3343
|
(async () => {
|
|
3313
3344
|
try {
|
|
@@ -3347,7 +3378,7 @@ function CommentRow({ comment, showDivider }) {
|
|
|
3347
3378
|
}
|
|
3348
3379
|
|
|
3349
3380
|
// src/components/comments/useAppComments.ts
|
|
3350
|
-
var
|
|
3381
|
+
var React21 = __toESM(require("react"));
|
|
3351
3382
|
|
|
3352
3383
|
// src/data/comments/remote.ts
|
|
3353
3384
|
var AppCommentsRemoteDataSourceImpl = class extends BaseRemote {
|
|
@@ -3419,18 +3450,18 @@ var appCommentsRepository = new AppCommentsRepositoryImpl(appCommentsRemoteDataS
|
|
|
3419
3450
|
|
|
3420
3451
|
// src/components/comments/useAppComments.ts
|
|
3421
3452
|
function useAppComments(appId) {
|
|
3422
|
-
const [comments, setComments] =
|
|
3423
|
-
const [loading, setLoading] =
|
|
3424
|
-
const [sending, setSending] =
|
|
3425
|
-
const [error, setError] =
|
|
3426
|
-
const sortByCreatedAtAsc =
|
|
3453
|
+
const [comments, setComments] = React21.useState([]);
|
|
3454
|
+
const [loading, setLoading] = React21.useState(false);
|
|
3455
|
+
const [sending, setSending] = React21.useState(false);
|
|
3456
|
+
const [error, setError] = React21.useState(null);
|
|
3457
|
+
const sortByCreatedAtAsc = React21.useCallback((items) => {
|
|
3427
3458
|
return [...items].sort((a, b) => {
|
|
3428
3459
|
const at = a.createdAt ? new Date(a.createdAt).getTime() : 0;
|
|
3429
3460
|
const bt = b.createdAt ? new Date(b.createdAt).getTime() : 0;
|
|
3430
3461
|
return at - bt;
|
|
3431
3462
|
});
|
|
3432
3463
|
}, []);
|
|
3433
|
-
const refresh =
|
|
3464
|
+
const refresh = React21.useCallback(async () => {
|
|
3434
3465
|
if (!appId) {
|
|
3435
3466
|
setComments([]);
|
|
3436
3467
|
return;
|
|
@@ -3447,10 +3478,10 @@ function useAppComments(appId) {
|
|
|
3447
3478
|
setLoading(false);
|
|
3448
3479
|
}
|
|
3449
3480
|
}, [appId, sortByCreatedAtAsc]);
|
|
3450
|
-
|
|
3481
|
+
React21.useEffect(() => {
|
|
3451
3482
|
void refresh();
|
|
3452
3483
|
}, [refresh]);
|
|
3453
|
-
const create =
|
|
3484
|
+
const create = React21.useCallback(
|
|
3454
3485
|
async (text) => {
|
|
3455
3486
|
if (!appId) return;
|
|
3456
3487
|
const trimmed = text.trim();
|
|
@@ -3473,11 +3504,11 @@ function useAppComments(appId) {
|
|
|
3473
3504
|
}
|
|
3474
3505
|
|
|
3475
3506
|
// src/components/comments/useAppDetails.ts
|
|
3476
|
-
var
|
|
3507
|
+
var React22 = __toESM(require("react"));
|
|
3477
3508
|
function useAppDetails(appId) {
|
|
3478
|
-
const [app, setApp] =
|
|
3479
|
-
const [loading, setLoading] =
|
|
3480
|
-
|
|
3509
|
+
const [app, setApp] = React22.useState(null);
|
|
3510
|
+
const [loading, setLoading] = React22.useState(false);
|
|
3511
|
+
React22.useEffect(() => {
|
|
3481
3512
|
if (!appId) {
|
|
3482
3513
|
setApp(null);
|
|
3483
3514
|
return;
|
|
@@ -3502,11 +3533,11 @@ function useAppDetails(appId) {
|
|
|
3502
3533
|
}
|
|
3503
3534
|
|
|
3504
3535
|
// src/components/comments/useIosKeyboardSnapFix.ts
|
|
3505
|
-
var
|
|
3536
|
+
var React23 = __toESM(require("react"));
|
|
3506
3537
|
var import_react_native21 = require("react-native");
|
|
3507
3538
|
function useIosKeyboardSnapFix(sheetRef, options) {
|
|
3508
|
-
const [keyboardVisible, setKeyboardVisible] =
|
|
3509
|
-
|
|
3539
|
+
const [keyboardVisible, setKeyboardVisible] = React23.useState(false);
|
|
3540
|
+
React23.useEffect(() => {
|
|
3510
3541
|
if (import_react_native21.Platform.OS !== "ios") return;
|
|
3511
3542
|
const show = import_react_native21.Keyboard.addListener("keyboardWillShow", () => setKeyboardVisible(true));
|
|
3512
3543
|
const hide = import_react_native21.Keyboard.addListener("keyboardWillHide", () => {
|
|
@@ -3534,16 +3565,16 @@ var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
|
3534
3565
|
function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
3535
3566
|
const theme = useTheme();
|
|
3536
3567
|
const insets = (0, import_react_native_safe_area_context3.useSafeAreaInsets)();
|
|
3537
|
-
const sheetRef =
|
|
3538
|
-
const snapPoints =
|
|
3539
|
-
const currentIndexRef =
|
|
3568
|
+
const sheetRef = React24.useRef(null);
|
|
3569
|
+
const snapPoints = React24.useMemo(() => ["50%", "90%"], []);
|
|
3570
|
+
const currentIndexRef = React24.useRef(1);
|
|
3540
3571
|
const { comments, loading, sending, error, create, refresh } = useAppComments(appId);
|
|
3541
3572
|
const { app, loading: loadingApp } = useAppDetails(appId);
|
|
3542
3573
|
const { keyboardVisible } = useIosKeyboardSnapFix(sheetRef, {
|
|
3543
3574
|
getCurrentIndex: () => currentIndexRef.current,
|
|
3544
3575
|
targetIndex: 1
|
|
3545
3576
|
});
|
|
3546
|
-
|
|
3577
|
+
React24.useEffect(() => {
|
|
3547
3578
|
var _a, _b;
|
|
3548
3579
|
if (appId) {
|
|
3549
3580
|
(_a = sheetRef.current) == null ? void 0 : _a.present();
|
|
@@ -3552,22 +3583,22 @@ function AppCommentsSheet({ appId, onClose, onCountChange, onPlayApp }) {
|
|
|
3552
3583
|
(_b = sheetRef.current) == null ? void 0 : _b.dismiss();
|
|
3553
3584
|
}
|
|
3554
3585
|
}, [appId, refresh]);
|
|
3555
|
-
|
|
3586
|
+
React24.useEffect(() => {
|
|
3556
3587
|
if (!appId) return;
|
|
3557
3588
|
onCountChange == null ? void 0 : onCountChange(comments.length);
|
|
3558
3589
|
}, [appId, comments.length, onCountChange]);
|
|
3559
|
-
const renderBackdrop =
|
|
3590
|
+
const renderBackdrop = React24.useCallback(
|
|
3560
3591
|
(props) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_bottom_sheet3.BottomSheetBackdrop, { ...props, disappearsOnIndex: -1, appearsOnIndex: 0, opacity: 0.5 }),
|
|
3561
3592
|
[]
|
|
3562
3593
|
);
|
|
3563
|
-
const handleChange =
|
|
3594
|
+
const handleChange = React24.useCallback(
|
|
3564
3595
|
(index) => {
|
|
3565
3596
|
currentIndexRef.current = index;
|
|
3566
3597
|
if (index === -1) onClose();
|
|
3567
3598
|
},
|
|
3568
3599
|
[onClose]
|
|
3569
3600
|
);
|
|
3570
|
-
const handlePlay =
|
|
3601
|
+
const handlePlay = React24.useCallback(async () => {
|
|
3571
3602
|
var _a;
|
|
3572
3603
|
if (!appId) return;
|
|
3573
3604
|
(_a = sheetRef.current) == null ? void 0 : _a.dismiss();
|
|
@@ -3777,7 +3808,7 @@ function StudioSheetHeader({ left, center, right, style }) {
|
|
|
3777
3808
|
}
|
|
3778
3809
|
|
|
3779
3810
|
// src/components/studio-sheet/StudioSheetHeaderIconButton.tsx
|
|
3780
|
-
var
|
|
3811
|
+
var React25 = __toESM(require("react"));
|
|
3781
3812
|
var import_react_native25 = require("react-native");
|
|
3782
3813
|
var import_liquid_glass6 = require("@callstack/liquid-glass");
|
|
3783
3814
|
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
@@ -3792,7 +3823,7 @@ function StudioSheetHeaderIconButton({
|
|
|
3792
3823
|
}) {
|
|
3793
3824
|
const theme = useTheme();
|
|
3794
3825
|
const size = 44;
|
|
3795
|
-
const [pressed, setPressed] =
|
|
3826
|
+
const [pressed, setPressed] = React25.useState(false);
|
|
3796
3827
|
const solidBg = intent === "danger" ? theme.colors.danger : intent === "primary" ? theme.colors.primary : theme.colors.neutral;
|
|
3797
3828
|
const glassFallbackBg = theme.scheme === "dark" ? "#18181B" : "#F6F6F6";
|
|
3798
3829
|
const glassInnerBg = intent === "danger" ? theme.colors.danger : theme.colors.primary;
|
|
@@ -3982,14 +4013,14 @@ function PreviewHeroCard({
|
|
|
3982
4013
|
}
|
|
3983
4014
|
|
|
3984
4015
|
// src/components/preview/PreviewPlaceholder.tsx
|
|
3985
|
-
var
|
|
4016
|
+
var React26 = __toESM(require("react"));
|
|
3986
4017
|
var import_react_native29 = require("react-native");
|
|
3987
4018
|
var import_expo_linear_gradient2 = require("expo-linear-gradient");
|
|
3988
4019
|
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
3989
4020
|
function PreviewPlaceholder({ visible, style }) {
|
|
3990
4021
|
if (!visible) return null;
|
|
3991
|
-
const opacityAnim =
|
|
3992
|
-
|
|
4022
|
+
const opacityAnim = React26.useRef(new import_react_native29.Animated.Value(0)).current;
|
|
4023
|
+
React26.useEffect(() => {
|
|
3993
4024
|
if (!visible) return;
|
|
3994
4025
|
const animation = import_react_native29.Animated.loop(
|
|
3995
4026
|
import_react_native29.Animated.sequence([
|
|
@@ -4573,12 +4604,12 @@ function PreviewCustomizeSection({
|
|
|
4573
4604
|
}
|
|
4574
4605
|
|
|
4575
4606
|
// src/studio/ui/preview-panel/PreviewCollaborateSection.tsx
|
|
4576
|
-
var
|
|
4607
|
+
var React32 = __toESM(require("react"));
|
|
4577
4608
|
var import_react_native42 = require("react-native");
|
|
4578
4609
|
var import_lucide_react_native9 = require("lucide-react-native");
|
|
4579
4610
|
|
|
4580
4611
|
// src/components/merge-requests/MergeRequestStatusCard.tsx
|
|
4581
|
-
var
|
|
4612
|
+
var React28 = __toESM(require("react"));
|
|
4582
4613
|
var import_react_native38 = require("react-native");
|
|
4583
4614
|
var import_lucide_react_native7 = require("lucide-react-native");
|
|
4584
4615
|
|
|
@@ -4660,11 +4691,11 @@ function toIsoString(input) {
|
|
|
4660
4691
|
}
|
|
4661
4692
|
|
|
4662
4693
|
// src/components/merge-requests/useControlledExpansion.ts
|
|
4663
|
-
var
|
|
4694
|
+
var React27 = __toESM(require("react"));
|
|
4664
4695
|
function useControlledExpansion(props) {
|
|
4665
|
-
const [uncontrolled, setUncontrolled] =
|
|
4696
|
+
const [uncontrolled, setUncontrolled] = React27.useState(false);
|
|
4666
4697
|
const expanded = props.expanded ?? uncontrolled;
|
|
4667
|
-
const setExpanded =
|
|
4698
|
+
const setExpanded = React27.useCallback(
|
|
4668
4699
|
(next) => {
|
|
4669
4700
|
var _a;
|
|
4670
4701
|
(_a = props.onExpandedChange) == null ? void 0 : _a.call(props, next);
|
|
@@ -4689,8 +4720,8 @@ function MergeRequestStatusCard({
|
|
|
4689
4720
|
const isDark = theme.scheme === "dark";
|
|
4690
4721
|
const textColor = isDark ? "#FFFFFF" : "#000000";
|
|
4691
4722
|
const subTextColor = isDark ? "#A1A1AA" : "#71717A";
|
|
4692
|
-
const status =
|
|
4693
|
-
const { StatusIcon, iconColor, bgColor, statusText } =
|
|
4723
|
+
const status = React28.useMemo(() => getMergeRequestStatusDisplay(String(mergeRequest.status)), [mergeRequest.status]);
|
|
4724
|
+
const { StatusIcon, iconColor, bgColor, statusText } = React28.useMemo(() => {
|
|
4694
4725
|
switch (mergeRequest.status) {
|
|
4695
4726
|
case "approved":
|
|
4696
4727
|
case "merged":
|
|
@@ -4721,8 +4752,8 @@ function MergeRequestStatusCard({
|
|
|
4721
4752
|
const createdIso = toIsoString(mergeRequest.createdAt ?? null);
|
|
4722
4753
|
const headerTimeAgo = updatedIso ? formatTimeAgo(updatedIso) : "";
|
|
4723
4754
|
const createdTimeAgo = createdIso ? formatTimeAgo(createdIso) : "";
|
|
4724
|
-
const rotate =
|
|
4725
|
-
|
|
4755
|
+
const rotate = React28.useRef(new import_react_native38.Animated.Value(expanded ? 1 : 0)).current;
|
|
4756
|
+
React28.useEffect(() => {
|
|
4726
4757
|
import_react_native38.Animated.timing(rotate, {
|
|
4727
4758
|
toValue: expanded ? 1 : 0,
|
|
4728
4759
|
duration: 200,
|
|
@@ -4813,16 +4844,16 @@ function MergeRequestStatusCard({
|
|
|
4813
4844
|
}
|
|
4814
4845
|
|
|
4815
4846
|
// src/components/merge-requests/ReviewMergeRequestCarousel.tsx
|
|
4816
|
-
var
|
|
4847
|
+
var React31 = __toESM(require("react"));
|
|
4817
4848
|
var import_react_native41 = require("react-native");
|
|
4818
4849
|
|
|
4819
4850
|
// src/components/merge-requests/ReviewMergeRequestCard.tsx
|
|
4820
|
-
var
|
|
4851
|
+
var React30 = __toESM(require("react"));
|
|
4821
4852
|
var import_react_native40 = require("react-native");
|
|
4822
4853
|
var import_lucide_react_native8 = require("lucide-react-native");
|
|
4823
4854
|
|
|
4824
4855
|
// src/components/merge-requests/ReviewMergeRequestActionButton.tsx
|
|
4825
|
-
var
|
|
4856
|
+
var React29 = __toESM(require("react"));
|
|
4826
4857
|
var import_react_native39 = require("react-native");
|
|
4827
4858
|
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
4828
4859
|
function ReviewMergeRequestActionButton({
|
|
@@ -4833,7 +4864,7 @@ function ReviewMergeRequestActionButton({
|
|
|
4833
4864
|
children,
|
|
4834
4865
|
iconOnly
|
|
4835
4866
|
}) {
|
|
4836
|
-
const [pressed, setPressed] =
|
|
4867
|
+
const [pressed, setPressed] = React29.useState(false);
|
|
4837
4868
|
const height = iconOnly ? 36 : 40;
|
|
4838
4869
|
const width = iconOnly ? 36 : void 0;
|
|
4839
4870
|
const paddingHorizontal = iconOnly ? 0 : 16;
|
|
@@ -4895,10 +4926,10 @@ function ReviewMergeRequestCard({
|
|
|
4895
4926
|
onTest
|
|
4896
4927
|
}) {
|
|
4897
4928
|
const theme = useTheme();
|
|
4898
|
-
const status =
|
|
4929
|
+
const status = React30.useMemo(() => getMergeRequestStatusDisplay(mr.status), [mr.status]);
|
|
4899
4930
|
const canAct = mr.status === "open";
|
|
4900
|
-
const rotate =
|
|
4901
|
-
|
|
4931
|
+
const rotate = React30.useRef(new import_react_native40.Animated.Value(isExpanded ? 1 : 0)).current;
|
|
4932
|
+
React30.useEffect(() => {
|
|
4902
4933
|
import_react_native40.Animated.timing(rotate, { toValue: isExpanded ? 1 : 0, duration: 200, useNativeDriver: true }).start();
|
|
4903
4934
|
}, [isExpanded, rotate]);
|
|
4904
4935
|
const position = total > 1 ? `${index + 1}/${total}` : "Merge request";
|
|
@@ -5030,11 +5061,11 @@ function ReviewMergeRequestCarousel({
|
|
|
5030
5061
|
}) {
|
|
5031
5062
|
const theme = useTheme();
|
|
5032
5063
|
const { width } = (0, import_react_native41.useWindowDimensions)();
|
|
5033
|
-
const [expanded, setExpanded] =
|
|
5034
|
-
const carouselScrollX =
|
|
5064
|
+
const [expanded, setExpanded] = React31.useState({});
|
|
5065
|
+
const carouselScrollX = React31.useRef(new import_react_native41.Animated.Value(0)).current;
|
|
5035
5066
|
const peekAmount = 24;
|
|
5036
5067
|
const gap = 16;
|
|
5037
|
-
const cardWidth =
|
|
5068
|
+
const cardWidth = React31.useMemo(() => Math.max(1, width - theme.spacing.lg * 2 - peekAmount), [peekAmount, theme.spacing.lg, width]);
|
|
5038
5069
|
const snapInterval = cardWidth + gap;
|
|
5039
5070
|
const dotColor = theme.scheme === "dark" ? "#FFFFFF" : "#000000";
|
|
5040
5071
|
if (mergeRequests.length === 0) return null;
|
|
@@ -5133,7 +5164,7 @@ function PreviewCollaborateSection({
|
|
|
5133
5164
|
onTestMr
|
|
5134
5165
|
}) {
|
|
5135
5166
|
const theme = useTheme();
|
|
5136
|
-
const [submittingMr, setSubmittingMr] =
|
|
5167
|
+
const [submittingMr, setSubmittingMr] = React32.useState(false);
|
|
5137
5168
|
const hasSection = canSubmitMergeRequest || incomingMergeRequests.length > 0 || outgoingMergeRequests.length > 0;
|
|
5138
5169
|
if (!hasSection) return null;
|
|
5139
5170
|
const showActionsSubtitle = canSubmitMergeRequest && onSubmitMergeRequest || onTestMr && incomingMergeRequests.length > 0;
|
|
@@ -5241,7 +5272,7 @@ function PreviewCollaborateSection({
|
|
|
5241
5272
|
}
|
|
5242
5273
|
|
|
5243
5274
|
// src/studio/ui/preview-panel/usePreviewPanelData.ts
|
|
5244
|
-
var
|
|
5275
|
+
var React34 = __toESM(require("react"));
|
|
5245
5276
|
|
|
5246
5277
|
// src/data/apps/images/remote.ts
|
|
5247
5278
|
var AppImagesRemoteDataSourceImpl = class extends BaseRemote {
|
|
@@ -5292,7 +5323,7 @@ var AppImagesRepositoryImpl = class extends BaseRepository {
|
|
|
5292
5323
|
var appImagesRepository = new AppImagesRepositoryImpl(appImagesRemoteDataSource);
|
|
5293
5324
|
|
|
5294
5325
|
// src/studio/hooks/useAppStats.ts
|
|
5295
|
-
var
|
|
5326
|
+
var React33 = __toESM(require("react"));
|
|
5296
5327
|
var Haptics2 = __toESM(require("expo-haptics"));
|
|
5297
5328
|
|
|
5298
5329
|
// src/data/likes/remote.ts
|
|
@@ -5361,34 +5392,34 @@ function useAppStats({
|
|
|
5361
5392
|
initialIsLiked = false,
|
|
5362
5393
|
onOpenComments
|
|
5363
5394
|
}) {
|
|
5364
|
-
const [likeCount, setLikeCount] =
|
|
5365
|
-
const [commentCount, setCommentCount] =
|
|
5366
|
-
const [forkCount, setForkCount] =
|
|
5367
|
-
const [isLiked, setIsLiked] =
|
|
5368
|
-
const didMutateRef =
|
|
5369
|
-
const lastAppIdRef =
|
|
5370
|
-
|
|
5395
|
+
const [likeCount, setLikeCount] = React33.useState(initialLikes);
|
|
5396
|
+
const [commentCount, setCommentCount] = React33.useState(initialComments);
|
|
5397
|
+
const [forkCount, setForkCount] = React33.useState(initialForks);
|
|
5398
|
+
const [isLiked, setIsLiked] = React33.useState(initialIsLiked);
|
|
5399
|
+
const didMutateRef = React33.useRef(false);
|
|
5400
|
+
const lastAppIdRef = React33.useRef("");
|
|
5401
|
+
React33.useEffect(() => {
|
|
5371
5402
|
if (lastAppIdRef.current === appId) return;
|
|
5372
5403
|
lastAppIdRef.current = appId;
|
|
5373
5404
|
didMutateRef.current = false;
|
|
5374
5405
|
}, [appId]);
|
|
5375
|
-
|
|
5406
|
+
React33.useEffect(() => {
|
|
5376
5407
|
if (didMutateRef.current) return;
|
|
5377
5408
|
setLikeCount(initialLikes);
|
|
5378
5409
|
}, [appId, initialLikes]);
|
|
5379
|
-
|
|
5410
|
+
React33.useEffect(() => {
|
|
5380
5411
|
if (didMutateRef.current) return;
|
|
5381
5412
|
setCommentCount(initialComments);
|
|
5382
5413
|
}, [appId, initialComments]);
|
|
5383
|
-
|
|
5414
|
+
React33.useEffect(() => {
|
|
5384
5415
|
if (didMutateRef.current) return;
|
|
5385
5416
|
setForkCount(initialForks);
|
|
5386
5417
|
}, [appId, initialForks]);
|
|
5387
|
-
|
|
5418
|
+
React33.useEffect(() => {
|
|
5388
5419
|
if (didMutateRef.current) return;
|
|
5389
5420
|
setIsLiked(initialIsLiked);
|
|
5390
5421
|
}, [appId, initialIsLiked]);
|
|
5391
|
-
const handleLike =
|
|
5422
|
+
const handleLike = React33.useCallback(async () => {
|
|
5392
5423
|
var _a, _b;
|
|
5393
5424
|
if (!appId) return;
|
|
5394
5425
|
didMutateRef.current = true;
|
|
@@ -5412,7 +5443,7 @@ function useAppStats({
|
|
|
5412
5443
|
setLikeCount((prev) => Math.max(0, prev + (newIsLiked ? -1 : 1)));
|
|
5413
5444
|
}
|
|
5414
5445
|
}, [appId, isLiked, likeCount]);
|
|
5415
|
-
const handleOpenComments =
|
|
5446
|
+
const handleOpenComments = React33.useCallback(() => {
|
|
5416
5447
|
if (!appId) return;
|
|
5417
5448
|
try {
|
|
5418
5449
|
void Haptics2.impactAsync(Haptics2.ImpactFeedbackStyle.Light);
|
|
@@ -5427,11 +5458,11 @@ function useAppStats({
|
|
|
5427
5458
|
var LIKE_DEBUG_PREFIX = "[COMERGE_LIKE_DEBUG]";
|
|
5428
5459
|
function usePreviewPanelData(params) {
|
|
5429
5460
|
const { app, isOwner, outgoingMergeRequests, onOpenComments, commentCountOverride } = params;
|
|
5430
|
-
const [imageUrl, setImageUrl] =
|
|
5431
|
-
const [imageLoaded, setImageLoaded] =
|
|
5432
|
-
const [insights, setInsights] =
|
|
5433
|
-
const [creator, setCreator] =
|
|
5434
|
-
|
|
5461
|
+
const [imageUrl, setImageUrl] = React34.useState(null);
|
|
5462
|
+
const [imageLoaded, setImageLoaded] = React34.useState(false);
|
|
5463
|
+
const [insights, setInsights] = React34.useState({ likes: 0, comments: 0, forks: 0, downloads: 0 });
|
|
5464
|
+
const [creator, setCreator] = React34.useState(null);
|
|
5465
|
+
React34.useEffect(() => {
|
|
5435
5466
|
if (!(app == null ? void 0 : app.id)) return;
|
|
5436
5467
|
let cancelled = false;
|
|
5437
5468
|
(async () => {
|
|
@@ -5446,7 +5477,7 @@ function usePreviewPanelData(params) {
|
|
|
5446
5477
|
cancelled = true;
|
|
5447
5478
|
};
|
|
5448
5479
|
}, [app == null ? void 0 : app.id]);
|
|
5449
|
-
|
|
5480
|
+
React34.useEffect(() => {
|
|
5450
5481
|
if (!(app == null ? void 0 : app.createdBy)) return;
|
|
5451
5482
|
let cancelled = false;
|
|
5452
5483
|
(async () => {
|
|
@@ -5462,10 +5493,10 @@ function usePreviewPanelData(params) {
|
|
|
5462
5493
|
cancelled = true;
|
|
5463
5494
|
};
|
|
5464
5495
|
}, [app == null ? void 0 : app.createdBy]);
|
|
5465
|
-
|
|
5496
|
+
React34.useEffect(() => {
|
|
5466
5497
|
setImageLoaded(false);
|
|
5467
5498
|
}, [app == null ? void 0 : app.id]);
|
|
5468
|
-
|
|
5499
|
+
React34.useEffect(() => {
|
|
5469
5500
|
if (!(app == null ? void 0 : app.id)) return;
|
|
5470
5501
|
let cancelled = false;
|
|
5471
5502
|
(async () => {
|
|
@@ -5490,7 +5521,7 @@ function usePreviewPanelData(params) {
|
|
|
5490
5521
|
cancelled = true;
|
|
5491
5522
|
};
|
|
5492
5523
|
}, [app == null ? void 0 : app.id]);
|
|
5493
|
-
|
|
5524
|
+
React34.useEffect(() => {
|
|
5494
5525
|
if (!(app == null ? void 0 : app.id)) return;
|
|
5495
5526
|
log.debug(
|
|
5496
5527
|
`${LIKE_DEBUG_PREFIX} usePreviewPanelData.appChanged appId=${app.id} app.isLiked=${String(app.isLiked)}`
|
|
@@ -5504,7 +5535,7 @@ function usePreviewPanelData(params) {
|
|
|
5504
5535
|
initialIsLiked: Boolean(app == null ? void 0 : app.isLiked),
|
|
5505
5536
|
onOpenComments
|
|
5506
5537
|
});
|
|
5507
|
-
const canSubmitMergeRequest =
|
|
5538
|
+
const canSubmitMergeRequest = React34.useMemo(() => {
|
|
5508
5539
|
if (!isOwner) return false;
|
|
5509
5540
|
if (!app) return false;
|
|
5510
5541
|
if (!app.forkedFromAppId) return false;
|
|
@@ -5617,16 +5648,16 @@ function PreviewPanel({
|
|
|
5617
5648
|
}
|
|
5618
5649
|
|
|
5619
5650
|
// src/studio/ui/ChatPanel.tsx
|
|
5620
|
-
var
|
|
5651
|
+
var React39 = __toESM(require("react"));
|
|
5621
5652
|
var import_react_native51 = require("react-native");
|
|
5622
5653
|
|
|
5623
5654
|
// src/components/chat/ChatPage.tsx
|
|
5624
|
-
var
|
|
5655
|
+
var React37 = __toESM(require("react"));
|
|
5625
5656
|
var import_react_native47 = require("react-native");
|
|
5626
5657
|
var import_react_native_safe_area_context4 = require("react-native-safe-area-context");
|
|
5627
5658
|
|
|
5628
5659
|
// src/components/chat/ChatMessageList.tsx
|
|
5629
|
-
var
|
|
5660
|
+
var React36 = __toESM(require("react"));
|
|
5630
5661
|
var import_react_native46 = require("react-native");
|
|
5631
5662
|
var import_bottom_sheet5 = require("@gorhom/bottom-sheet");
|
|
5632
5663
|
|
|
@@ -5672,17 +5703,17 @@ function ChatMessageBubble({ message, renderContent, style }) {
|
|
|
5672
5703
|
}
|
|
5673
5704
|
|
|
5674
5705
|
// src/components/chat/TypingIndicator.tsx
|
|
5675
|
-
var
|
|
5706
|
+
var React35 = __toESM(require("react"));
|
|
5676
5707
|
var import_react_native45 = require("react-native");
|
|
5677
5708
|
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
5678
5709
|
function TypingIndicator({ style }) {
|
|
5679
5710
|
const theme = useTheme();
|
|
5680
5711
|
const dotColor = theme.colors.textSubtle;
|
|
5681
|
-
const anims =
|
|
5712
|
+
const anims = React35.useMemo(
|
|
5682
5713
|
() => [new import_react_native45.Animated.Value(0.3), new import_react_native45.Animated.Value(0.3), new import_react_native45.Animated.Value(0.3)],
|
|
5683
5714
|
[]
|
|
5684
5715
|
);
|
|
5685
|
-
|
|
5716
|
+
React35.useEffect(() => {
|
|
5686
5717
|
const loops = [];
|
|
5687
5718
|
anims.forEach((a, idx) => {
|
|
5688
5719
|
const seq = import_react_native45.Animated.sequence([
|
|
@@ -5716,7 +5747,7 @@ function TypingIndicator({ style }) {
|
|
|
5716
5747
|
|
|
5717
5748
|
// src/components/chat/ChatMessageList.tsx
|
|
5718
5749
|
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
5719
|
-
var ChatMessageList =
|
|
5750
|
+
var ChatMessageList = React36.forwardRef(
|
|
5720
5751
|
({
|
|
5721
5752
|
messages,
|
|
5722
5753
|
showTypingIndicator = false,
|
|
@@ -5727,20 +5758,20 @@ var ChatMessageList = React35.forwardRef(
|
|
|
5727
5758
|
nearBottomThreshold = 200
|
|
5728
5759
|
}, ref) => {
|
|
5729
5760
|
const theme = useTheme();
|
|
5730
|
-
const listRef =
|
|
5731
|
-
const nearBottomRef =
|
|
5732
|
-
const initialScrollDoneRef =
|
|
5733
|
-
const lastMessageIdRef =
|
|
5734
|
-
const data =
|
|
5761
|
+
const listRef = React36.useRef(null);
|
|
5762
|
+
const nearBottomRef = React36.useRef(true);
|
|
5763
|
+
const initialScrollDoneRef = React36.useRef(false);
|
|
5764
|
+
const lastMessageIdRef = React36.useRef(null);
|
|
5765
|
+
const data = React36.useMemo(() => {
|
|
5735
5766
|
return [...messages].reverse();
|
|
5736
5767
|
}, [messages]);
|
|
5737
|
-
const scrollToBottom =
|
|
5768
|
+
const scrollToBottom = React36.useCallback((options) => {
|
|
5738
5769
|
var _a;
|
|
5739
5770
|
const animated = (options == null ? void 0 : options.animated) ?? true;
|
|
5740
5771
|
(_a = listRef.current) == null ? void 0 : _a.scrollToOffset({ offset: 0, animated });
|
|
5741
5772
|
}, []);
|
|
5742
|
-
|
|
5743
|
-
const handleScroll =
|
|
5773
|
+
React36.useImperativeHandle(ref, () => ({ scrollToBottom }), [scrollToBottom]);
|
|
5774
|
+
const handleScroll = React36.useCallback(
|
|
5744
5775
|
(e) => {
|
|
5745
5776
|
const { contentOffset, contentSize, layoutMeasurement } = e.nativeEvent;
|
|
5746
5777
|
const distanceFromBottom = Math.max(contentOffset.y - Math.max(bottomInset, 0), 0);
|
|
@@ -5752,7 +5783,7 @@ var ChatMessageList = React35.forwardRef(
|
|
|
5752
5783
|
},
|
|
5753
5784
|
[bottomInset, nearBottomThreshold, onNearBottomChange]
|
|
5754
5785
|
);
|
|
5755
|
-
|
|
5786
|
+
React36.useEffect(() => {
|
|
5756
5787
|
if (!initialScrollDoneRef.current) return;
|
|
5757
5788
|
const lastId = messages.length > 0 ? messages[messages.length - 1].id : null;
|
|
5758
5789
|
const prevLastId = lastMessageIdRef.current;
|
|
@@ -5762,7 +5793,7 @@ var ChatMessageList = React35.forwardRef(
|
|
|
5762
5793
|
const id = requestAnimationFrame(() => scrollToBottom({ animated: true }));
|
|
5763
5794
|
return () => cancelAnimationFrame(id);
|
|
5764
5795
|
}, [messages, scrollToBottom]);
|
|
5765
|
-
|
|
5796
|
+
React36.useEffect(() => {
|
|
5766
5797
|
if (showTypingIndicator && nearBottomRef.current) {
|
|
5767
5798
|
const id = requestAnimationFrame(() => scrollToBottom({ animated: true }));
|
|
5768
5799
|
return () => cancelAnimationFrame(id);
|
|
@@ -5824,9 +5855,9 @@ function ChatPage({
|
|
|
5824
5855
|
}) {
|
|
5825
5856
|
const theme = useTheme();
|
|
5826
5857
|
const insets = (0, import_react_native_safe_area_context4.useSafeAreaInsets)();
|
|
5827
|
-
const [composerHeight, setComposerHeight] =
|
|
5828
|
-
const [keyboardVisible, setKeyboardVisible] =
|
|
5829
|
-
|
|
5858
|
+
const [composerHeight, setComposerHeight] = React37.useState(0);
|
|
5859
|
+
const [keyboardVisible, setKeyboardVisible] = React37.useState(false);
|
|
5860
|
+
React37.useEffect(() => {
|
|
5830
5861
|
if (import_react_native47.Platform.OS !== "ios") return;
|
|
5831
5862
|
const show = import_react_native47.Keyboard.addListener("keyboardWillShow", () => setKeyboardVisible(true));
|
|
5832
5863
|
const hide = import_react_native47.Keyboard.addListener("keyboardWillHide", () => setKeyboardVisible(false));
|
|
@@ -5838,12 +5869,12 @@ function ChatPage({
|
|
|
5838
5869
|
const footerBottomPadding = import_react_native47.Platform.OS === "ios" ? keyboardVisible ? 0 : insets.bottom : insets.bottom + 10;
|
|
5839
5870
|
const overlayBottom = composerHeight + footerBottomPadding + theme.spacing.lg;
|
|
5840
5871
|
const bottomInset = composerHeight + footerBottomPadding + theme.spacing.xl;
|
|
5841
|
-
const resolvedOverlay =
|
|
5872
|
+
const resolvedOverlay = React37.useMemo(() => {
|
|
5842
5873
|
var _a;
|
|
5843
5874
|
if (!overlay) return null;
|
|
5844
|
-
if (!
|
|
5875
|
+
if (!React37.isValidElement(overlay)) return overlay;
|
|
5845
5876
|
const prevStyle = (_a = overlay.props) == null ? void 0 : _a.style;
|
|
5846
|
-
return
|
|
5877
|
+
return React37.cloneElement(overlay, {
|
|
5847
5878
|
style: [prevStyle, { bottom: overlayBottom }]
|
|
5848
5879
|
});
|
|
5849
5880
|
}, [overlay, overlayBottom]);
|
|
@@ -5898,15 +5929,15 @@ function ChatPage({
|
|
|
5898
5929
|
}
|
|
5899
5930
|
|
|
5900
5931
|
// src/components/chat/ScrollToBottomButton.tsx
|
|
5901
|
-
var
|
|
5932
|
+
var React38 = __toESM(require("react"));
|
|
5902
5933
|
var import_react_native48 = require("react-native");
|
|
5903
5934
|
var import_react_native_reanimated2 = __toESM(require("react-native-reanimated"));
|
|
5904
5935
|
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
5905
5936
|
function ScrollToBottomButton({ visible, onPress, children, style }) {
|
|
5906
5937
|
const theme = useTheme();
|
|
5907
5938
|
const progress = (0, import_react_native_reanimated2.useSharedValue)(visible ? 1 : 0);
|
|
5908
|
-
const [pressed, setPressed] =
|
|
5909
|
-
|
|
5939
|
+
const [pressed, setPressed] = React38.useState(false);
|
|
5940
|
+
React38.useEffect(() => {
|
|
5910
5941
|
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) });
|
|
5911
5942
|
}, [progress, visible]);
|
|
5912
5943
|
const animStyle = (0, import_react_native_reanimated2.useAnimatedStyle)(() => ({
|
|
@@ -6061,9 +6092,9 @@ function ChatPanel({
|
|
|
6061
6092
|
onStartDraw,
|
|
6062
6093
|
onSend
|
|
6063
6094
|
}) {
|
|
6064
|
-
const listRef =
|
|
6065
|
-
const [nearBottom, setNearBottom] =
|
|
6066
|
-
const handleSend =
|
|
6095
|
+
const listRef = React39.useRef(null);
|
|
6096
|
+
const [nearBottom, setNearBottom] = React39.useState(true);
|
|
6097
|
+
const handleSend = React39.useCallback(
|
|
6067
6098
|
async (text, composerAttachments) => {
|
|
6068
6099
|
const all = composerAttachments ?? attachments;
|
|
6069
6100
|
await onSend(text, all.length > 0 ? all : void 0);
|
|
@@ -6077,7 +6108,7 @@ function ChatPanel({
|
|
|
6077
6108
|
},
|
|
6078
6109
|
[attachments, nearBottom, onClearAttachments, onSend]
|
|
6079
6110
|
);
|
|
6080
|
-
const handleScrollToBottom =
|
|
6111
|
+
const handleScrollToBottom = React39.useCallback(() => {
|
|
6081
6112
|
var _a;
|
|
6082
6113
|
(_a = listRef.current) == null ? void 0 : _a.scrollToBottom({ animated: true });
|
|
6083
6114
|
}, []);
|
|
@@ -6151,7 +6182,7 @@ function ChatPanel({
|
|
|
6151
6182
|
}
|
|
6152
6183
|
|
|
6153
6184
|
// src/components/dialogs/ConfirmMergeRequestDialog.tsx
|
|
6154
|
-
var
|
|
6185
|
+
var React40 = __toESM(require("react"));
|
|
6155
6186
|
var import_react_native53 = require("react-native");
|
|
6156
6187
|
|
|
6157
6188
|
// src/components/primitives/Modal.tsx
|
|
@@ -6199,14 +6230,14 @@ function ConfirmMergeRequestDialog({
|
|
|
6199
6230
|
onTestFirst
|
|
6200
6231
|
}) {
|
|
6201
6232
|
const theme = useTheme();
|
|
6202
|
-
const close =
|
|
6233
|
+
const close = React40.useCallback(() => onOpenChange(false), [onOpenChange]);
|
|
6203
6234
|
const canConfirm = Boolean(mergeRequest) && !approveDisabled;
|
|
6204
|
-
const handleConfirm =
|
|
6235
|
+
const handleConfirm = React40.useCallback(() => {
|
|
6205
6236
|
if (!mergeRequest) return;
|
|
6206
6237
|
onOpenChange(false);
|
|
6207
6238
|
void onConfirm();
|
|
6208
6239
|
}, [mergeRequest, onConfirm, onOpenChange]);
|
|
6209
|
-
const handleTestFirst =
|
|
6240
|
+
const handleTestFirst = React40.useCallback(() => {
|
|
6210
6241
|
if (!mergeRequest) return;
|
|
6211
6242
|
onOpenChange(false);
|
|
6212
6243
|
void onTestFirst(mergeRequest);
|
|
@@ -6355,7 +6386,7 @@ function ConfirmMergeFlow({
|
|
|
6355
6386
|
}
|
|
6356
6387
|
|
|
6357
6388
|
// src/studio/hooks/useOptimisticChatMessages.ts
|
|
6358
|
-
var
|
|
6389
|
+
var React41 = __toESM(require("react"));
|
|
6359
6390
|
function makeOptimisticId() {
|
|
6360
6391
|
return `optimistic:${Date.now().toString(36)}:${Math.random().toString(36).slice(2, 10)}`;
|
|
6361
6392
|
}
|
|
@@ -6393,11 +6424,11 @@ function useOptimisticChatMessages({
|
|
|
6393
6424
|
chatMessages,
|
|
6394
6425
|
onSendChat
|
|
6395
6426
|
}) {
|
|
6396
|
-
const [optimisticChat, setOptimisticChat] =
|
|
6397
|
-
|
|
6427
|
+
const [optimisticChat, setOptimisticChat] = React41.useState([]);
|
|
6428
|
+
React41.useEffect(() => {
|
|
6398
6429
|
setOptimisticChat([]);
|
|
6399
6430
|
}, [threadId]);
|
|
6400
|
-
const messages =
|
|
6431
|
+
const messages = React41.useMemo(() => {
|
|
6401
6432
|
if (!optimisticChat || optimisticChat.length === 0) return chatMessages;
|
|
6402
6433
|
const unresolved = optimisticChat.filter((o) => !isOptimisticResolvedByServer(chatMessages, o));
|
|
6403
6434
|
if (unresolved.length === 0) return chatMessages;
|
|
@@ -6413,7 +6444,7 @@ function useOptimisticChatMessages({
|
|
|
6413
6444
|
merged.sort((a, b) => String(a.createdAt).localeCompare(String(b.createdAt)));
|
|
6414
6445
|
return merged;
|
|
6415
6446
|
}, [chatMessages, optimisticChat]);
|
|
6416
|
-
|
|
6447
|
+
React41.useEffect(() => {
|
|
6417
6448
|
if (optimisticChat.length === 0) return;
|
|
6418
6449
|
setOptimisticChat((prev) => {
|
|
6419
6450
|
if (prev.length === 0) return prev;
|
|
@@ -6421,7 +6452,7 @@ function useOptimisticChatMessages({
|
|
|
6421
6452
|
return next.length === prev.length ? prev : next;
|
|
6422
6453
|
});
|
|
6423
6454
|
}, [chatMessages, optimisticChat.length]);
|
|
6424
|
-
const onSend =
|
|
6455
|
+
const onSend = React41.useCallback(
|
|
6425
6456
|
async (text, attachments) => {
|
|
6426
6457
|
if (shouldForkOnEdit) {
|
|
6427
6458
|
await onSendChat(text, attachments);
|
|
@@ -6441,6 +6472,7 @@ function useOptimisticChatMessages({
|
|
|
6441
6472
|
}
|
|
6442
6473
|
|
|
6443
6474
|
// src/studio/ui/StudioOverlay.tsx
|
|
6475
|
+
var import_studio_control = require("@comergehq/studio-control");
|
|
6444
6476
|
var import_jsx_runtime57 = require("react/jsx-runtime");
|
|
6445
6477
|
function StudioOverlay({
|
|
6446
6478
|
captureTargetRef,
|
|
@@ -6468,16 +6500,19 @@ function StudioOverlay({
|
|
|
6468
6500
|
chatSending,
|
|
6469
6501
|
chatShowTypingIndicator,
|
|
6470
6502
|
onSendChat,
|
|
6471
|
-
onNavigateHome
|
|
6503
|
+
onNavigateHome,
|
|
6504
|
+
showBubble,
|
|
6505
|
+
studioControlOptions
|
|
6472
6506
|
}) {
|
|
6473
6507
|
const theme = useTheme();
|
|
6474
6508
|
const { width } = (0, import_react_native54.useWindowDimensions)();
|
|
6475
|
-
const [sheetOpen, setSheetOpen] =
|
|
6476
|
-
const
|
|
6477
|
-
const [
|
|
6478
|
-
const [
|
|
6479
|
-
const [
|
|
6480
|
-
const [
|
|
6509
|
+
const [sheetOpen, setSheetOpen] = React42.useState(false);
|
|
6510
|
+
const sheetOpenRef = React42.useRef(sheetOpen);
|
|
6511
|
+
const [activePage, setActivePage] = React42.useState("preview");
|
|
6512
|
+
const [drawing, setDrawing] = React42.useState(false);
|
|
6513
|
+
const [chatAttachments, setChatAttachments] = React42.useState([]);
|
|
6514
|
+
const [commentsAppId, setCommentsAppId] = React42.useState(null);
|
|
6515
|
+
const [commentsCount, setCommentsCount] = React42.useState(null);
|
|
6481
6516
|
const threadId = (app == null ? void 0 : app.threadId) ?? null;
|
|
6482
6517
|
const optimistic = useOptimisticChatMessages({
|
|
6483
6518
|
threadId,
|
|
@@ -6485,24 +6520,24 @@ function StudioOverlay({
|
|
|
6485
6520
|
chatMessages,
|
|
6486
6521
|
onSendChat
|
|
6487
6522
|
});
|
|
6488
|
-
const [confirmMrId, setConfirmMrId] =
|
|
6489
|
-
const confirmMr =
|
|
6523
|
+
const [confirmMrId, setConfirmMrId] = React42.useState(null);
|
|
6524
|
+
const confirmMr = React42.useMemo(
|
|
6490
6525
|
() => confirmMrId ? incomingMergeRequests.find((m) => m.id === confirmMrId) ?? null : null,
|
|
6491
6526
|
[confirmMrId, incomingMergeRequests]
|
|
6492
6527
|
);
|
|
6493
|
-
const handleSheetOpenChange =
|
|
6528
|
+
const handleSheetOpenChange = React42.useCallback((open) => {
|
|
6494
6529
|
setSheetOpen(open);
|
|
6495
6530
|
if (!open) import_react_native54.Keyboard.dismiss();
|
|
6496
6531
|
}, []);
|
|
6497
|
-
const closeSheet =
|
|
6532
|
+
const closeSheet = React42.useCallback(() => {
|
|
6498
6533
|
handleSheetOpenChange(false);
|
|
6499
6534
|
}, [handleSheetOpenChange]);
|
|
6500
|
-
const openSheet =
|
|
6501
|
-
const goToChat =
|
|
6535
|
+
const openSheet = React42.useCallback(() => setSheetOpen(true), []);
|
|
6536
|
+
const goToChat = React42.useCallback(() => {
|
|
6502
6537
|
setActivePage("chat");
|
|
6503
6538
|
openSheet();
|
|
6504
6539
|
}, [openSheet]);
|
|
6505
|
-
const backToPreview =
|
|
6540
|
+
const backToPreview = React42.useCallback(() => {
|
|
6506
6541
|
if (import_react_native54.Platform.OS !== "ios") {
|
|
6507
6542
|
import_react_native54.Keyboard.dismiss();
|
|
6508
6543
|
setActivePage("preview");
|
|
@@ -6520,11 +6555,11 @@ function StudioOverlay({
|
|
|
6520
6555
|
const t = setTimeout(finalize, 350);
|
|
6521
6556
|
import_react_native54.Keyboard.dismiss();
|
|
6522
6557
|
}, []);
|
|
6523
|
-
const startDraw =
|
|
6558
|
+
const startDraw = React42.useCallback(() => {
|
|
6524
6559
|
setDrawing(true);
|
|
6525
6560
|
closeSheet();
|
|
6526
6561
|
}, [closeSheet]);
|
|
6527
|
-
const handleDrawCapture =
|
|
6562
|
+
const handleDrawCapture = React42.useCallback(
|
|
6528
6563
|
(dataUrl) => {
|
|
6529
6564
|
setChatAttachments((prev) => [...prev, dataUrl]);
|
|
6530
6565
|
setDrawing(false);
|
|
@@ -6533,7 +6568,7 @@ function StudioOverlay({
|
|
|
6533
6568
|
},
|
|
6534
6569
|
[openSheet]
|
|
6535
6570
|
);
|
|
6536
|
-
const toggleSheet =
|
|
6571
|
+
const toggleSheet = React42.useCallback(async () => {
|
|
6537
6572
|
if (!sheetOpen) {
|
|
6538
6573
|
const shouldExitTest = Boolean(testingMrId) || isTesting;
|
|
6539
6574
|
if (shouldExitTest) {
|
|
@@ -6545,7 +6580,7 @@ function StudioOverlay({
|
|
|
6545
6580
|
closeSheet();
|
|
6546
6581
|
}
|
|
6547
6582
|
}, [closeSheet, isTesting, onRestoreBase, sheetOpen, testingMrId]);
|
|
6548
|
-
const handleTestMr =
|
|
6583
|
+
const handleTestMr = React42.useCallback(
|
|
6549
6584
|
async (mr) => {
|
|
6550
6585
|
if (!onTestMr) return;
|
|
6551
6586
|
await onTestMr(mr);
|
|
@@ -6553,6 +6588,20 @@ function StudioOverlay({
|
|
|
6553
6588
|
},
|
|
6554
6589
|
[closeSheet, onTestMr]
|
|
6555
6590
|
);
|
|
6591
|
+
React42.useEffect(() => {
|
|
6592
|
+
sheetOpenRef.current = sheetOpen;
|
|
6593
|
+
}, [sheetOpen]);
|
|
6594
|
+
React42.useEffect(() => {
|
|
6595
|
+
const poller = (0, import_studio_control.startStudioControlPolling)((action) => {
|
|
6596
|
+
if (action === "show" && !sheetOpenRef.current) openSheet();
|
|
6597
|
+
if (action === "hide" && sheetOpenRef.current) closeSheet();
|
|
6598
|
+
if (action === "toggle") toggleSheet();
|
|
6599
|
+
}, studioControlOptions);
|
|
6600
|
+
return () => poller.stop();
|
|
6601
|
+
}, [closeSheet, openSheet, studioControlOptions, toggleSheet]);
|
|
6602
|
+
React42.useEffect(() => {
|
|
6603
|
+
void (0, import_studio_control.publishComergeStudioUIState)(sheetOpen, studioControlOptions);
|
|
6604
|
+
}, [sheetOpen, studioControlOptions]);
|
|
6556
6605
|
return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
|
|
6557
6606
|
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(EdgeGlowFrame, { visible: isTesting, role: "accent", thickness: 40, intensity: 1 }),
|
|
6558
6607
|
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(StudioBottomSheet, { open: sheetOpen, onOpenChange: handleSheetOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
@@ -6609,8 +6658,8 @@ function StudioOverlay({
|
|
|
6609
6658
|
)
|
|
6610
6659
|
}
|
|
6611
6660
|
) }),
|
|
6612
|
-
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
6613
|
-
|
|
6661
|
+
showBubble && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
6662
|
+
Bubble,
|
|
6614
6663
|
{
|
|
6615
6664
|
visible: !sheetOpen && !drawing,
|
|
6616
6665
|
ariaLabel: sheetOpen ? "Hide studio" : "Show studio",
|
|
@@ -6658,22 +6707,25 @@ function StudioOverlay({
|
|
|
6658
6707
|
var import_jsx_runtime58 = require("react/jsx-runtime");
|
|
6659
6708
|
function ComergeStudio({
|
|
6660
6709
|
appId,
|
|
6661
|
-
|
|
6710
|
+
clientKey: clientKey2,
|
|
6662
6711
|
appKey = "MicroMain",
|
|
6663
6712
|
onNavigateHome,
|
|
6664
|
-
style
|
|
6713
|
+
style,
|
|
6714
|
+
showBubble = true,
|
|
6715
|
+
studioControlOptions,
|
|
6716
|
+
embeddedBaseBundles
|
|
6665
6717
|
}) {
|
|
6666
|
-
const [activeAppId, setActiveAppId] =
|
|
6667
|
-
const [runtimeAppId, setRuntimeAppId] =
|
|
6668
|
-
const [pendingRuntimeTargetAppId, setPendingRuntimeTargetAppId] =
|
|
6669
|
-
const platform =
|
|
6670
|
-
|
|
6718
|
+
const [activeAppId, setActiveAppId] = React43.useState(appId);
|
|
6719
|
+
const [runtimeAppId, setRuntimeAppId] = React43.useState(appId);
|
|
6720
|
+
const [pendingRuntimeTargetAppId, setPendingRuntimeTargetAppId] = React43.useState(null);
|
|
6721
|
+
const platform = React43.useMemo(() => import_react_native55.Platform.OS === "ios" ? "ios" : "android", []);
|
|
6722
|
+
React43.useEffect(() => {
|
|
6671
6723
|
setActiveAppId(appId);
|
|
6672
6724
|
setRuntimeAppId(appId);
|
|
6673
6725
|
setPendingRuntimeTargetAppId(null);
|
|
6674
6726
|
}, [appId]);
|
|
6675
|
-
const captureTargetRef =
|
|
6676
|
-
return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(StudioBootstrap, {
|
|
6727
|
+
const captureTargetRef = React43.useRef(null);
|
|
6728
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(StudioBootstrap, { clientKey: clientKey2, fallback: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_react_native55.View, { style: { flex: 1 } }), children: ({ userId }) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_bottom_sheet6.BottomSheetModalProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(LiquidGlassResetProvider, { resetTriggers: [appId, activeAppId, runtimeAppId], children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6677
6729
|
ComergeStudioInner,
|
|
6678
6730
|
{
|
|
6679
6731
|
userId,
|
|
@@ -6687,7 +6739,10 @@ function ComergeStudio({
|
|
|
6687
6739
|
platform,
|
|
6688
6740
|
onNavigateHome,
|
|
6689
6741
|
captureTargetRef,
|
|
6690
|
-
style
|
|
6742
|
+
style,
|
|
6743
|
+
showBubble,
|
|
6744
|
+
studioControlOptions,
|
|
6745
|
+
embeddedBaseBundles
|
|
6691
6746
|
}
|
|
6692
6747
|
) }) }) });
|
|
6693
6748
|
}
|
|
@@ -6703,16 +6758,19 @@ function ComergeStudioInner({
|
|
|
6703
6758
|
platform,
|
|
6704
6759
|
onNavigateHome,
|
|
6705
6760
|
captureTargetRef,
|
|
6706
|
-
style
|
|
6761
|
+
style,
|
|
6762
|
+
showBubble,
|
|
6763
|
+
studioControlOptions,
|
|
6764
|
+
embeddedBaseBundles
|
|
6707
6765
|
}) {
|
|
6708
6766
|
const { app, loading: appLoading } = useApp(activeAppId);
|
|
6709
6767
|
const { app: runtimeAppFromHook } = useApp(runtimeAppId, { enabled: runtimeAppId !== activeAppId });
|
|
6710
6768
|
const runtimeApp = runtimeAppId === activeAppId ? app : runtimeAppFromHook;
|
|
6711
|
-
const sawEditingOnPendingTargetRef =
|
|
6712
|
-
|
|
6769
|
+
const sawEditingOnPendingTargetRef = React43.useRef(false);
|
|
6770
|
+
React43.useEffect(() => {
|
|
6713
6771
|
sawEditingOnPendingTargetRef.current = false;
|
|
6714
6772
|
}, [pendingRuntimeTargetAppId]);
|
|
6715
|
-
|
|
6773
|
+
React43.useEffect(() => {
|
|
6716
6774
|
if (!pendingRuntimeTargetAppId) return;
|
|
6717
6775
|
if (activeAppId !== pendingRuntimeTargetAppId) return;
|
|
6718
6776
|
if ((app == null ? void 0 : app.status) === "editing") {
|
|
@@ -6727,15 +6785,16 @@ function ComergeStudioInner({
|
|
|
6727
6785
|
const bundle = useBundleManager({
|
|
6728
6786
|
base: { appId: runtimeAppId, commitId: (runtimeApp == null ? void 0 : runtimeApp.headCommitId) ?? void 0 },
|
|
6729
6787
|
platform,
|
|
6730
|
-
canRequestLatest: (runtimeApp == null ? void 0 : runtimeApp.status) === "ready"
|
|
6788
|
+
canRequestLatest: (runtimeApp == null ? void 0 : runtimeApp.status) === "ready",
|
|
6789
|
+
embeddedBaseBundles
|
|
6731
6790
|
});
|
|
6732
|
-
const sawEditingOnActiveAppRef =
|
|
6733
|
-
const [showPostEditPreparing, setShowPostEditPreparing] =
|
|
6734
|
-
|
|
6791
|
+
const sawEditingOnActiveAppRef = React43.useRef(false);
|
|
6792
|
+
const [showPostEditPreparing, setShowPostEditPreparing] = React43.useState(false);
|
|
6793
|
+
React43.useEffect(() => {
|
|
6735
6794
|
sawEditingOnActiveAppRef.current = false;
|
|
6736
6795
|
setShowPostEditPreparing(false);
|
|
6737
6796
|
}, [activeAppId]);
|
|
6738
|
-
|
|
6797
|
+
React43.useEffect(() => {
|
|
6739
6798
|
if (!(app == null ? void 0 : app.id)) return;
|
|
6740
6799
|
if (app.status === "editing") {
|
|
6741
6800
|
sawEditingOnActiveAppRef.current = true;
|
|
@@ -6747,7 +6806,7 @@ function ComergeStudioInner({
|
|
|
6747
6806
|
sawEditingOnActiveAppRef.current = false;
|
|
6748
6807
|
}
|
|
6749
6808
|
}, [app == null ? void 0 : app.id, app == null ? void 0 : app.status]);
|
|
6750
|
-
|
|
6809
|
+
React43.useEffect(() => {
|
|
6751
6810
|
if (!showPostEditPreparing) return;
|
|
6752
6811
|
const stillProcessingBaseBundle = bundle.loading && bundle.loadingMode === "base" && !bundle.isTesting;
|
|
6753
6812
|
if (!stillProcessingBaseBundle) {
|
|
@@ -6757,10 +6816,10 @@ function ComergeStudioInner({
|
|
|
6757
6816
|
const threadId = (app == null ? void 0 : app.threadId) ?? "";
|
|
6758
6817
|
const thread = useThreadMessages(threadId);
|
|
6759
6818
|
const mergeRequests = useMergeRequests({ appId: activeAppId });
|
|
6760
|
-
const hasOpenOutgoingMr =
|
|
6819
|
+
const hasOpenOutgoingMr = React43.useMemo(() => {
|
|
6761
6820
|
return mergeRequests.lists.outgoing.some((mr) => mr.status === "open");
|
|
6762
6821
|
}, [mergeRequests.lists.outgoing]);
|
|
6763
|
-
const incomingReviewMrs =
|
|
6822
|
+
const incomingReviewMrs = React43.useMemo(() => {
|
|
6764
6823
|
if (!userId) return mergeRequests.lists.incoming;
|
|
6765
6824
|
return mergeRequests.lists.incoming.filter((mr) => mr.createdBy !== userId);
|
|
6766
6825
|
}, [mergeRequests.lists.incoming, userId]);
|
|
@@ -6782,9 +6841,9 @@ function ComergeStudioInner({
|
|
|
6782
6841
|
uploadAttachments: uploader.uploadBase64Images
|
|
6783
6842
|
});
|
|
6784
6843
|
const chatSendDisabled = hasNoOutcomeAfterLastHuman(thread.raw);
|
|
6785
|
-
const [processingMrId, setProcessingMrId] =
|
|
6786
|
-
const [testingMrId, setTestingMrId] =
|
|
6787
|
-
const chatShowTypingIndicator =
|
|
6844
|
+
const [processingMrId, setProcessingMrId] = React43.useState(null);
|
|
6845
|
+
const [testingMrId, setTestingMrId] = React43.useState(null);
|
|
6846
|
+
const chatShowTypingIndicator = React43.useMemo(() => {
|
|
6788
6847
|
var _a;
|
|
6789
6848
|
if (!thread.raw || thread.raw.length === 0) return false;
|
|
6790
6849
|
const last = thread.raw[thread.raw.length - 1];
|
|
@@ -6798,7 +6857,8 @@ function ComergeStudioInner({
|
|
|
6798
6857
|
appKey,
|
|
6799
6858
|
bundlePath: bundle.bundlePath,
|
|
6800
6859
|
forcePreparing: showPostEditPreparing,
|
|
6801
|
-
renderToken: bundle.renderToken
|
|
6860
|
+
renderToken: bundle.renderToken,
|
|
6861
|
+
allowInitialPreparing: !embeddedBaseBundles
|
|
6802
6862
|
}
|
|
6803
6863
|
),
|
|
6804
6864
|
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
@@ -6853,7 +6913,9 @@ function ComergeStudioInner({
|
|
|
6853
6913
|
chatSending: actions.sending,
|
|
6854
6914
|
chatShowTypingIndicator,
|
|
6855
6915
|
onSendChat: (text, attachments) => actions.sendEdit({ prompt: text, attachments }),
|
|
6856
|
-
onNavigateHome
|
|
6916
|
+
onNavigateHome,
|
|
6917
|
+
showBubble,
|
|
6918
|
+
studioControlOptions
|
|
6857
6919
|
}
|
|
6858
6920
|
)
|
|
6859
6921
|
] }) });
|