fix: publish to World confirm button stuck disabled in Bevy editor - #1493
Conversation
The confirm button required project.status === 'succeeded', which is only set by the fire-and-forget thumbnail-save flow. Under the Bevy renderer the screenshot is best-effort and may never resolve, leaving the status undefined forever and the button permanently grayed out. Only block while a thumbnail save is actually in flight. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Test this pull request on windows-latestDownload the correct version for your architecture: |
Test this pull request on macos-latestDownload the correct version for your architecture:Click here if you don't know which version to downloadFor running this unsigned version of the app, you will need to run the xattr command on it:
|
decentraland-bot
left a comment
There was a problem hiding this comment.
Review: fix: publish to World confirm button stuck disabled in Bevy editor
Summary
Single-file, 6-line fix that changes the projectIsReady gate in SelectWorld from requiring an explicit 'succeeded' status to only blocking during an active 'loading' state. The root cause is well identified: the Bevy renderer's screenshot is best-effort and may never dispatch the saveAndGetThumbnail thunk, leaving project.status as undefined forever — which the old === 'succeeded' check treated as "not ready".
Deployment Flow Analysis
The requester asked to verify this fixes all flows for worlds, multi-scene worlds, and genesis city. Here's the breakdown:
✅ Worlds (single scene)
SelectWorld → handleNext() → onPublish({ worldConfiguration, scene: {base: "0,0", parcels: [...]} })
The projectIsReady gate controls the "Review" button in SelectWorld. With the fix, undefined status (Bevy case) now evaluates to true, unblocking the button. Babylon behavior is unchanged ('succeeded' still evaluates to true).
✅ Multi-scene worlds
SelectWorld → handleNext() → onSelectLocation() → SelectLocation → handleNext() → onPublish() or onShowConfirmation()
Same fix applies — projectIsReady only gates the first step (SelectWorld). The subsequent SelectLocation step has its own independent button gate (disabled={!placement || noParcelsFit}) that does not reference project.status. The ConfirmOverwrite step also has no projectIsReady check. So multi-scene flow is unblocked.
✅ Genesis City (PublishToLand) — not affected
PublishToLand does not use projectIsReady or check project.status at all. Its publish button is gated only on disabled={!placement} (parcel selection). This path was never broken by the thumbnail status issue.
Correctness Verification
All possible project.status values (status?: Status where Status = 'idle' | 'loading' | 'succeeded' | 'failed'):
| Status | Old (=== 'succeeded') |
New (!== 'loading') |
Correct? |
|---|---|---|---|
undefined |
false ❌ stuck |
true ✅ |
✅ Bevy fix |
'idle' |
false |
true |
✅ No reason to block |
'loading' |
false |
false |
✅ Blocks during save |
'succeeded' |
true |
true |
✅ Babylon unchanged |
'failed' |
false |
true |
✅ Failed thumbnail shouldn't block deploy |
All transitions are correct. The 'loading' → false case properly prevents racing the thumbnail file write as noted in the comment.
Architecture Note
[P2] project.status is set by the getProject thunk lifecycle (pending → loading, fulfilled → succeeded, rejected → failed), not by saveAndGetThumbnail directly. In theory, an unrelated getProject dispatch while the publish modal is open could briefly set status to 'loading' and momentarily disable the button. This is pre-existing behavior and the fix doesn't make it worse — it's actually correct to pause during any active project operation. A dedicated thumbnailSaveStatus field would be cleaner long-term but is out of scope for this fix.
Security Review
No security issues found. The change is a pure UI gate condition in a React component within an Electron desktop app. No network calls, auth/authz, input handling, secrets, or sensitive data are modified.
Git Conventions (ADR-6)
- Branch:
fix/bevy-publish-world-confirm-disabled✅ - Title:
fix: publish to World confirm button stuck disabled in Bevy editor✅
CI Status
All checks passing ✅ (lint, unit tests, E2E, typechecking, Windows build, macOS build)
Verdict
APPROVE — The fix is correct, minimal, and well-documented. It unblocks Bevy world publishing while preserving Babylon behavior. Genesis City was never affected. No P0 or P1 issues found.
Reviewed by Jarvis 🤖 · Requested by Gabriel Díaz (<@U03MGHMAJL8>) via Slack
Problem
When editing a scene with the Bevy editor, publishing to a World is impossible: after selecting a world name from the dropdown, the confirm button stays grayed out forever. The same scene publishes fine from the Babylon editor.
Root cause
When Publish is clicked, the editor fire-and-forgets a "save scene thumbnail" flow: it requests a screenshot from the renderer over the scene RPC, and only if a screenshot comes back does it dispatch
workspace/saveAndGetThumbnail— the thunk whose lifecycle setsproject.statustoloading→succeeded/failed.The World step's confirm button required
project.status === 'succeeded':succeeded→ button enables./screenshotconsole command, and the host explicitly treats a rejection as "no thumbnail, non-fatal"). When it fails, the save thunk is never dispatched,project.statusstaysundefinedforever, and the button never enables — with no error surfaced anywhere.The
status === 'succeeded'gate is a leftover: it originally guarded a thumbnail preview image inside the publish modal (loader until the screenshot arrived, #279). That preview was removed in the multi-scene redesign (#1089), but the gate stayed attached to the button — silently turning a decorative thumbnail failure into a publish blocker. It even carried a// TODO: handle failed state....Fix
Only block the button while a thumbnail save is actually in flight (
status === 'loading'), so the deploy doesn't race the thumbnail file write. Bothundefined(thumbnail never attempted — the normal Bevy case) andfailednow allow publishing, since the deploy works fine without a fresh thumbnail.Babylon behavior is unchanged: the button just briefly disables during the save, then enables.
Notes
/screenshot— that's a separate, cosmetic issue; publishing is no longer held hostage by it.🤖 Generated with Claude Code