@comergehq/studio 0.1.19 → 0.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +134 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +135 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/chat/ChatMessageBubble.tsx +5 -2
- package/src/data/apps/remote.ts +9 -0
- package/src/data/apps/repository.ts +7 -0
- package/src/data/apps/types.ts +15 -0
- package/src/studio/ComergeStudio.tsx +22 -0
- package/src/studio/ui/PreviewPanel.tsx +24 -4
- package/src/studio/ui/StudioOverlay.tsx +9 -0
- package/src/studio/ui/preview-panel/PreviewCollaborateSection.tsx +95 -3
- package/src/studio/ui/preview-panel/usePreviewPanelData.ts +8 -0
package/dist/index.js
CHANGED
|
@@ -549,6 +549,12 @@ var AppsRemoteDataSourceImpl = class extends BaseRemote {
|
|
|
549
549
|
);
|
|
550
550
|
return data;
|
|
551
551
|
}
|
|
552
|
+
async syncUpstream(appId) {
|
|
553
|
+
const { data } = await api.post(
|
|
554
|
+
`/v1/apps/${encodeURIComponent(appId)}/sync-upstream`
|
|
555
|
+
);
|
|
556
|
+
return data;
|
|
557
|
+
}
|
|
552
558
|
};
|
|
553
559
|
var appsRemoteDataSource = new AppsRemoteDataSourceImpl();
|
|
554
560
|
|
|
@@ -627,6 +633,10 @@ var AppsRepositoryImpl = class extends BaseRepository {
|
|
|
627
633
|
const res = await this.remote.importFromGithub(payload);
|
|
628
634
|
return this.unwrapOrThrow(res);
|
|
629
635
|
}
|
|
636
|
+
async syncUpstream(appId) {
|
|
637
|
+
const res = await this.remote.syncUpstream(appId);
|
|
638
|
+
return this.unwrapOrThrow(res);
|
|
639
|
+
}
|
|
630
640
|
subscribeCreatedApps(userId, handlers) {
|
|
631
641
|
if (!userId) return () => {
|
|
632
642
|
};
|
|
@@ -5390,6 +5400,9 @@ function ReviewMergeRequestCarousel({
|
|
|
5390
5400
|
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
5391
5401
|
function PreviewCollaborateSection({
|
|
5392
5402
|
canSubmitMergeRequest,
|
|
5403
|
+
canSyncUpstream,
|
|
5404
|
+
syncingUpstream,
|
|
5405
|
+
upstreamSyncStatus,
|
|
5393
5406
|
incomingMergeRequests,
|
|
5394
5407
|
outgoingMergeRequests,
|
|
5395
5408
|
creatorStatsById,
|
|
@@ -5398,15 +5411,18 @@ function PreviewCollaborateSection({
|
|
|
5398
5411
|
testingMrId,
|
|
5399
5412
|
toMergeRequestSummary,
|
|
5400
5413
|
onSubmitMergeRequest,
|
|
5414
|
+
onSyncUpstream,
|
|
5401
5415
|
onRequestApprove,
|
|
5402
5416
|
onReject,
|
|
5403
5417
|
onTestMr
|
|
5404
5418
|
}) {
|
|
5405
5419
|
const theme = useTheme();
|
|
5406
5420
|
const [submittingMr, setSubmittingMr] = React32.useState(false);
|
|
5407
|
-
const
|
|
5421
|
+
const [syncingLocal, setSyncingLocal] = React32.useState(false);
|
|
5422
|
+
const hasSection = canSubmitMergeRequest || canSyncUpstream || incomingMergeRequests.length > 0 || outgoingMergeRequests.length > 0;
|
|
5408
5423
|
if (!hasSection) return null;
|
|
5409
|
-
const
|
|
5424
|
+
const isSyncing = Boolean(syncingUpstream || syncingLocal);
|
|
5425
|
+
const showActionsSubtitle = canSubmitMergeRequest && onSubmitMergeRequest || canSyncUpstream && onSyncUpstream || onTestMr && incomingMergeRequests.length > 0;
|
|
5410
5426
|
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
|
|
5411
5427
|
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(SectionTitle, { marginTop: theme.spacing.xl, children: "Collaborate" }),
|
|
5412
5428
|
showActionsSubtitle ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
@@ -5475,6 +5491,64 @@ function PreviewCollaborateSection({
|
|
|
5475
5491
|
right: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react_native9.Send, { size: 16, color: "#03DAC6" })
|
|
5476
5492
|
}
|
|
5477
5493
|
) : null,
|
|
5494
|
+
canSyncUpstream && onSyncUpstream ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
5495
|
+
PressableCardRow,
|
|
5496
|
+
{
|
|
5497
|
+
accessibilityLabel: "Sync from original",
|
|
5498
|
+
disabled: isSyncing,
|
|
5499
|
+
onPress: () => {
|
|
5500
|
+
import_react_native42.Alert.alert(
|
|
5501
|
+
"Sync from Original",
|
|
5502
|
+
"This will pull the latest upstream changes into your remix.",
|
|
5503
|
+
[
|
|
5504
|
+
{ text: "Cancel", style: "cancel" },
|
|
5505
|
+
{
|
|
5506
|
+
text: "Sync",
|
|
5507
|
+
style: "destructive",
|
|
5508
|
+
onPress: () => {
|
|
5509
|
+
setSyncingLocal(true);
|
|
5510
|
+
Promise.resolve(onSyncUpstream()).then((result) => {
|
|
5511
|
+
if ((result == null ? void 0 : result.status) === "up-to-date") {
|
|
5512
|
+
import_react_native42.Alert.alert("Up to date", "Your remix already includes the latest upstream changes.");
|
|
5513
|
+
} else {
|
|
5514
|
+
import_react_native42.Alert.alert("Sync started", "Upstream changes are being merged into your remix.");
|
|
5515
|
+
}
|
|
5516
|
+
}).catch(() => {
|
|
5517
|
+
import_react_native42.Alert.alert("Sync failed", "We could not start the sync. Please try again.");
|
|
5518
|
+
}).finally(() => setSyncingLocal(false));
|
|
5519
|
+
}
|
|
5520
|
+
}
|
|
5521
|
+
]
|
|
5522
|
+
);
|
|
5523
|
+
},
|
|
5524
|
+
style: {
|
|
5525
|
+
padding: theme.spacing.lg,
|
|
5526
|
+
borderRadius: theme.radii.lg,
|
|
5527
|
+
backgroundColor: withAlpha(theme.colors.surfaceRaised, 0.5),
|
|
5528
|
+
borderWidth: 1,
|
|
5529
|
+
borderColor: withAlpha(theme.colors.primary, 0.25),
|
|
5530
|
+
marginBottom: theme.spacing.sm
|
|
5531
|
+
},
|
|
5532
|
+
left: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
5533
|
+
import_react_native42.View,
|
|
5534
|
+
{
|
|
5535
|
+
style: {
|
|
5536
|
+
width: 40,
|
|
5537
|
+
height: 40,
|
|
5538
|
+
borderRadius: 999,
|
|
5539
|
+
alignItems: "center",
|
|
5540
|
+
justifyContent: "center",
|
|
5541
|
+
backgroundColor: withAlpha(theme.colors.primary, 0.12),
|
|
5542
|
+
marginRight: theme.spacing.lg
|
|
5543
|
+
},
|
|
5544
|
+
children: isSyncing ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native42.ActivityIndicator, { color: theme.colors.primary, size: "small" }) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react_native9.RefreshCw, { size: 18, color: theme.colors.primary })
|
|
5545
|
+
}
|
|
5546
|
+
),
|
|
5547
|
+
title: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Text, { style: { color: theme.colors.text, fontSize: 16, lineHeight: 20, fontWeight: theme.typography.fontWeight.semibold }, children: "Sync from Original" }),
|
|
5548
|
+
subtitle: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Text, { style: { color: theme.colors.textMuted, fontSize: 12, lineHeight: 16, marginTop: 2 }, children: isSyncing ? "Syncing upstream changes..." : upstreamSyncStatus === "up-to-date" ? "You are already up to date with the original app" : "Pull the latest upstream changes into this remix" }),
|
|
5549
|
+
right: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react_native9.RefreshCw, { size: 16, color: theme.colors.primary })
|
|
5550
|
+
}
|
|
5551
|
+
) : null,
|
|
5478
5552
|
onTestMr && incomingMergeRequests.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
5479
5553
|
ReviewMergeRequestCarousel,
|
|
5480
5554
|
{
|
|
@@ -5782,6 +5856,12 @@ function usePreviewPanelData(params) {
|
|
|
5782
5856
|
if (app.headCommitId && app.forkedFromCommitId && app.headCommitId !== app.forkedFromCommitId) return true;
|
|
5783
5857
|
return false;
|
|
5784
5858
|
}, [app, isOwner, outgoingMergeRequests]);
|
|
5859
|
+
const canSyncUpstream = React34.useMemo(() => {
|
|
5860
|
+
if (!isOwner) return false;
|
|
5861
|
+
if (!app) return false;
|
|
5862
|
+
if (!app.forkedFromAppId) return false;
|
|
5863
|
+
return app.status === "ready";
|
|
5864
|
+
}, [app, isOwner]);
|
|
5785
5865
|
const showProcessing = app ? app.status !== "ready" : false;
|
|
5786
5866
|
return {
|
|
5787
5867
|
imageUrl,
|
|
@@ -5791,7 +5871,8 @@ function usePreviewPanelData(params) {
|
|
|
5791
5871
|
insights,
|
|
5792
5872
|
stats,
|
|
5793
5873
|
showProcessing,
|
|
5794
|
-
canSubmitMergeRequest
|
|
5874
|
+
canSubmitMergeRequest,
|
|
5875
|
+
canSyncUpstream
|
|
5795
5876
|
};
|
|
5796
5877
|
}
|
|
5797
5878
|
|
|
@@ -5814,6 +5895,9 @@ function PreviewPanel({
|
|
|
5814
5895
|
onGoToChat,
|
|
5815
5896
|
onStartDraw,
|
|
5816
5897
|
onSubmitMergeRequest,
|
|
5898
|
+
onSyncUpstream,
|
|
5899
|
+
syncingUpstream,
|
|
5900
|
+
upstreamSyncStatus,
|
|
5817
5901
|
onRequestApprove,
|
|
5818
5902
|
onReject,
|
|
5819
5903
|
onTestMr,
|
|
@@ -5823,11 +5907,11 @@ function PreviewPanel({
|
|
|
5823
5907
|
const handleShare = React35.useCallback(async () => {
|
|
5824
5908
|
if (!app || !app.isPublic) return;
|
|
5825
5909
|
const shareUrl = `https://remix.one/app/${app.id}`;
|
|
5826
|
-
const message = app.name ? `${app.name} on
|
|
5827
|
-
${shareUrl}` : `Check out this app on
|
|
5910
|
+
const message = app.name ? `${app.name} on Remix
|
|
5911
|
+
${shareUrl}` : `Check out this app on Remix
|
|
5828
5912
|
${shareUrl}`;
|
|
5829
5913
|
try {
|
|
5830
|
-
const title = app.name ?? "
|
|
5914
|
+
const title = app.name ?? "Remix app";
|
|
5831
5915
|
const payload = import_react_native43.Platform.OS === "ios" ? {
|
|
5832
5916
|
title,
|
|
5833
5917
|
message
|
|
@@ -5841,7 +5925,17 @@ ${shareUrl}`;
|
|
|
5841
5925
|
log.warn("PreviewPanel share failed", error);
|
|
5842
5926
|
}
|
|
5843
5927
|
}, [app]);
|
|
5844
|
-
const {
|
|
5928
|
+
const {
|
|
5929
|
+
imageUrl,
|
|
5930
|
+
imageLoaded,
|
|
5931
|
+
setImageLoaded,
|
|
5932
|
+
creator,
|
|
5933
|
+
insights,
|
|
5934
|
+
stats,
|
|
5935
|
+
showProcessing,
|
|
5936
|
+
canSubmitMergeRequest,
|
|
5937
|
+
canSyncUpstream
|
|
5938
|
+
} = usePreviewPanelData({
|
|
5845
5939
|
app,
|
|
5846
5940
|
isOwner,
|
|
5847
5941
|
outgoingMergeRequests,
|
|
@@ -5901,6 +5995,9 @@ ${shareUrl}`;
|
|
|
5901
5995
|
PreviewCollaborateSection,
|
|
5902
5996
|
{
|
|
5903
5997
|
canSubmitMergeRequest,
|
|
5998
|
+
canSyncUpstream,
|
|
5999
|
+
syncingUpstream,
|
|
6000
|
+
upstreamSyncStatus,
|
|
5904
6001
|
incomingMergeRequests,
|
|
5905
6002
|
outgoingMergeRequests,
|
|
5906
6003
|
creatorStatsById,
|
|
@@ -5909,6 +6006,7 @@ ${shareUrl}`;
|
|
|
5909
6006
|
testingMrId,
|
|
5910
6007
|
toMergeRequestSummary,
|
|
5911
6008
|
onSubmitMergeRequest,
|
|
6009
|
+
onSyncUpstream,
|
|
5912
6010
|
onRequestApprove,
|
|
5913
6011
|
onReject,
|
|
5914
6012
|
onTestMr
|
|
@@ -5943,6 +6041,8 @@ function ChatMessageBubble({ message, renderContent, style }) {
|
|
|
5943
6041
|
const isMergeApproved = metaEvent === "merge_request.approved";
|
|
5944
6042
|
const isMergeRejected = metaEvent === "merge_request.rejected";
|
|
5945
6043
|
const isMergeCompleted = metaEvent === "merge.completed";
|
|
6044
|
+
const isSyncStarted = metaEvent === "sync.started";
|
|
6045
|
+
const isSyncCompleted = metaEvent === "sync.completed";
|
|
5946
6046
|
const isHuman = message.author === "human" || isMergeApproved || isMergeRejected;
|
|
5947
6047
|
const align = { alignSelf: isHuman ? "flex-end" : "flex-start" };
|
|
5948
6048
|
const bubbleVariant = isHuman ? "surface" : "surfaceRaised";
|
|
@@ -5964,8 +6064,8 @@ function ChatMessageBubble({ message, renderContent, style }) {
|
|
|
5964
6064
|
cornerStyle
|
|
5965
6065
|
],
|
|
5966
6066
|
children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_react_native44.View, { style: { flexDirection: "row", alignItems: "center" }, children: [
|
|
5967
|
-
isMergeCompleted ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react_native10.CheckCheck, { size: 16, color: theme.colors.success, style: { marginRight: theme.spacing.sm } }) : null,
|
|
5968
|
-
isMergeApproved ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react_native10.GitMerge, { size: 16, color: theme.colors.text, style: { marginRight: theme.spacing.sm } }) : null,
|
|
6067
|
+
isMergeCompleted || isSyncCompleted ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react_native10.CheckCheck, { size: 16, color: theme.colors.success, style: { marginRight: theme.spacing.sm } }) : null,
|
|
6068
|
+
isMergeApproved || isSyncStarted ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react_native10.GitMerge, { size: 16, color: theme.colors.text, style: { marginRight: theme.spacing.sm } }) : null,
|
|
5969
6069
|
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_react_native44.View, { style: { flexShrink: 1, minWidth: 0 }, children: renderContent ? renderContent(message) : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(MarkdownText, { markdown: message.content, variant: "chat", bodyColor }) })
|
|
5970
6070
|
] })
|
|
5971
6071
|
}
|
|
@@ -6928,6 +7028,9 @@ function StudioOverlay({
|
|
|
6928
7028
|
testingMrId,
|
|
6929
7029
|
toMergeRequestSummary,
|
|
6930
7030
|
onSubmitMergeRequest,
|
|
7031
|
+
onSyncUpstream,
|
|
7032
|
+
syncingUpstream,
|
|
7033
|
+
upstreamSyncStatus,
|
|
6931
7034
|
onApprove,
|
|
6932
7035
|
onReject,
|
|
6933
7036
|
onTestMr,
|
|
@@ -7072,6 +7175,9 @@ function StudioOverlay({
|
|
|
7072
7175
|
onGoToChat: goToChat,
|
|
7073
7176
|
onStartDraw: isOwner ? startDraw : void 0,
|
|
7074
7177
|
onSubmitMergeRequest,
|
|
7178
|
+
onSyncUpstream,
|
|
7179
|
+
syncingUpstream,
|
|
7180
|
+
upstreamSyncStatus,
|
|
7075
7181
|
onRequestApprove: (mr) => setConfirmMrId(mr.id),
|
|
7076
7182
|
onReject,
|
|
7077
7183
|
onTestMr: handleTestMr,
|
|
@@ -7500,6 +7606,8 @@ function ComergeStudioInner({
|
|
|
7500
7606
|
const chatSendDisabled = false;
|
|
7501
7607
|
const [processingMrId, setProcessingMrId] = React47.useState(null);
|
|
7502
7608
|
const [testingMrId, setTestingMrId] = React47.useState(null);
|
|
7609
|
+
const [syncingUpstream, setSyncingUpstream] = React47.useState(false);
|
|
7610
|
+
const [upstreamSyncStatus, setUpstreamSyncStatus] = React47.useState(null);
|
|
7503
7611
|
const chatShowTypingIndicator = React47.useMemo(() => {
|
|
7504
7612
|
var _a;
|
|
7505
7613
|
if (!thread.raw || thread.raw.length === 0) return false;
|
|
@@ -7510,7 +7618,21 @@ function ComergeStudioInner({
|
|
|
7510
7618
|
React47.useEffect(() => {
|
|
7511
7619
|
updateLastEditQueueInfo(null);
|
|
7512
7620
|
setSuppressQueueUntilResponse(false);
|
|
7621
|
+
setUpstreamSyncStatus(null);
|
|
7513
7622
|
}, [activeAppId, updateLastEditQueueInfo]);
|
|
7623
|
+
const handleSyncUpstream = React47.useCallback(async () => {
|
|
7624
|
+
if (!(app == null ? void 0 : app.id)) {
|
|
7625
|
+
throw new Error("Missing app");
|
|
7626
|
+
}
|
|
7627
|
+
setSyncingUpstream(true);
|
|
7628
|
+
try {
|
|
7629
|
+
const result = await appsRepository.syncUpstream(activeAppId);
|
|
7630
|
+
setUpstreamSyncStatus(result.status);
|
|
7631
|
+
return result;
|
|
7632
|
+
} finally {
|
|
7633
|
+
setSyncingUpstream(false);
|
|
7634
|
+
}
|
|
7635
|
+
}, [activeAppId, app == null ? void 0 : app.id]);
|
|
7514
7636
|
React47.useEffect(() => {
|
|
7515
7637
|
if (!(lastEditQueueInfo == null ? void 0 : lastEditQueueInfo.queueItemId)) return;
|
|
7516
7638
|
const stillPresent = editQueue.items.some((item) => item.id === lastEditQueueInfo.queueItemId);
|
|
@@ -7566,6 +7688,9 @@ function ComergeStudioInner({
|
|
|
7566
7688
|
onSubmitMergeRequest: (app == null ? void 0 : app.forkedFromAppId) && actions.isOwner && !hasOpenOutgoingMr ? async () => {
|
|
7567
7689
|
await mergeRequests.actions.openMergeRequest(activeAppId);
|
|
7568
7690
|
} : void 0,
|
|
7691
|
+
onSyncUpstream: actions.isOwner && (app == null ? void 0 : app.forkedFromAppId) ? handleSyncUpstream : void 0,
|
|
7692
|
+
syncingUpstream,
|
|
7693
|
+
upstreamSyncStatus,
|
|
7569
7694
|
onApprove: async (mr) => {
|
|
7570
7695
|
if (processingMrId) return;
|
|
7571
7696
|
setProcessingMrId(mr.id);
|