From c12ef7f343a4e0dbb1cff264975f02502ddcfae3 Mon Sep 17 00:00:00 2001 From: ciregenz Date: Sat, 20 Jun 2026 03:08:36 -0700 Subject: [PATCH] [eric] publish: 10s slow-hint on slow builds + two-step confirm before unpublish --- .../src/app/components/share/PublishModal.tsx | 49 ++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/components/share/PublishModal.tsx b/frontend/src/app/components/share/PublishModal.tsx index bd03703d..d887c716 100644 --- a/frontend/src/app/components/share/PublishModal.tsx +++ b/frontend/src/app/components/share/PublishModal.tsx @@ -34,6 +34,28 @@ interface Props { type Phase = 'scanning' | 'review' | 'publishing' | 'done' | 'error'; +// A build can take up to ~3 minutes on a cold node_modules. Stay silent for the +// fast common case, then fade in an honest hint after 10s so a slow build doesn't +// read as a hang (matches the SlowHint pattern in ChatInputOverlays). +const SlowHint: React.FC<{ active: boolean; color: string }> = ({ active, color }) => { + const [show, setShow] = useState(false); + useEffect(() => { + if (!active) { + setShow(false); + return; + } + const t = setTimeout(() => setShow(true), 10000); + return () => clearTimeout(t); + }, [active]); + return ( + + + This can take up to a minute. Hang tight. + + + ); +}; + const PublishModal: React.FC = ({ outputId, outputName, open, onClose }) => { const c = useClaudeTokens(); const dispatch = useAppDispatch(); @@ -46,6 +68,7 @@ const PublishModal: React.FC = ({ outputId, outputName, open, onClose }) const [liveUrl, setLiveUrl] = useState(null); const [busy, setBusy] = useState(false); const [toast, setToast] = useState(''); + const [confirmUnpublish, setConfirmUnpublish] = useState(false); const runScan = useCallback(() => { setPhase('scanning'); @@ -63,6 +86,7 @@ const PublishModal: React.FC = ({ outputId, outputName, open, onClose }) useEffect(() => { if (!open) return; setShowDetails(false); + setConfirmUnpublish(false); if (publishedUrl) { setLiveUrl(publishedUrl); setPhase('done'); @@ -107,6 +131,7 @@ const PublishModal: React.FC = ({ outputId, outputName, open, onClose }) setToast('App unpublished'); onClose(); } catch (e: any) { + setConfirmUnpublish(false); setToast(e?.message || "We couldn't unpublish."); } finally { setBusy(false); @@ -134,6 +159,7 @@ const PublishModal: React.FC = ({ outputId, outputName, open, onClose }) <> Checking your app before it goes live... + , ); } @@ -142,6 +168,7 @@ const PublishModal: React.FC = ({ outputId, outputName, open, onClose }) <> Building and publishing your app... + , ); } @@ -154,6 +181,16 @@ const PublishModal: React.FC = ({ outputId, outputName, open, onClose }) ); } if (phase === 'done') { + if (confirmUnpublish) { + return center( + <> + Take this app offline? + + The public link will stop working for anyone you've shared it with. + + , + ); + } return ( @@ -220,9 +257,19 @@ const PublishModal: React.FC = ({ outputId, outputName, open, onClose }) ); } if (phase === 'done') { + if (confirmUnpublish) { + return ( + <> + + + + ); + } return ( <> - + );