Skip to content

Commit 3d41688

Browse files
authored
fix: Multi Scene Worlds (#3350)
1 parent f086c78 commit 3d41688

33 files changed

+390
-50
lines changed

src/components/Modals/CreatorHubUpgradeModal/CreatorHubUpgradeModal.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Button, ModalActions, ModalContent } from 'decentraland-ui'
44
import Modal from 'decentraland-dapps/dist/containers/Modal'
55
import { openModal } from 'decentraland-dapps/dist/modules/modal/actions'
66
import { t } from 'decentraland-dapps/dist/modules/translation/utils'
7+
import { config } from 'config'
78
import { Props, CreatorHubUpgradeModalMetadata } from './CreatorHubUpgradeModal.types'
89
import coverImg from 'images/creator-hub-cover.png'
910
import codeImg from 'images/creator-hub-step1.png'
@@ -15,7 +16,7 @@ import styles from './CreatorHubUpgradeModal.module.css'
1516

1617
type Variant = CreatorHubUpgradeModalMetadata['variant']
1718

18-
const CREATOR_HUB_DOWNLOAD_URL = 'https://decentraland.org/download/creator-hub/'
19+
const CREATOR_HUB_DOWNLOAD_URL = config.get('CREATOR_HUB_DOWNLOAD_URL')
1920

2021
const VARIANT_CONFIG: Record<string, { images: [string, string]; translationPrefix: string }> = {
2122
permissions: { images: [accessImg, collaborationImg], translationPrefix: 'creator_hub_upgrade_modal.permissions_variant' },

src/components/Modals/DeployModal/DeployToWorld/DeployToWorld.container.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,7 @@ const mapState = (state: RootState): MapStateProps => {
3737
}
3838

3939
const mapDispatch = (dispatch: MapDispatch): MapDispatchProps => ({
40-
onPublish: (projectId: string, name: string) => {
41-
return dispatch(deployToWorldRequest(projectId, name))
42-
},
40+
onPublish: (projectId: string, name: string) => dispatch(deployToWorldRequest(projectId, name)),
4341
onRecord: () => dispatch(recordMediaRequest()),
4442
onFetchContributableNames: () => dispatch(fetchContributableNamesRequest())
4543
})

src/components/Modals/DeployModal/DeployToWorld/DeployToWorld.module.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
text-align: center;
6262
font-size: 14px;
6363
line-height: 20px;
64+
white-space: pre-line;
6465
}
6566

6667
.modalBodyStateActions {

src/components/Modals/DeployModal/DeployToWorld/DeployToWorld.tsx

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { getAnalytics } from 'decentraland-dapps/dist/modules/analytics/utils'
88
import { config } from 'config'
99
import { isDevelopment } from 'lib/environment'
1010
import { locations } from 'routing/locations'
11-
import { Deployment } from 'modules/deployment/types'
11+
import { Deployment, DeploymentError } from 'modules/deployment/types'
1212
import CopyToClipboard from 'components/CopyToClipboard/CopyToClipboard'
1313
import Icon from 'components/Icon'
1414
import { InfoIcon } from 'components/InfoIcon'
@@ -23,6 +23,7 @@ import { ENS } from 'modules/ens/types'
2323
import Profile from 'components/Profile'
2424
import { marketplace } from 'lib/api/marketplace'
2525

26+
const CREATOR_HUB_DOWNLOAD_URL = config.get('CREATOR_HUB_DOWNLOAD_URL')
2627
const EXPLORER_URL = config.get('EXPLORER_URL', '')
2728
const WORLDS_CONTENT_SERVER_URL = config.get('WORLDS_CONTENT_SERVER', '')
2829
const ENS_DOMAINS_URL = config.get('ENS_DOMAINS_URL', '')
@@ -85,7 +86,11 @@ export default function DeployToWorld({
8586
}, [ensList, externalNames, contributableNames, onRecord, analytics])
8687

8788
useEffect(() => {
88-
if (view === DeployToWorldView.FORM && loading && error) {
89+
if (view === DeployToWorldView.FORM && loading && error === DeploymentError.MULTI_SCENE_BLOCKED) {
90+
setView(DeployToWorldView.MULTI_SCENE_BLOCKED)
91+
setLoading(false)
92+
analytics?.track('Publish to World step', { step: DeployToWorldView.MULTI_SCENE_BLOCKED })
93+
} else if (view === DeployToWorldView.FORM && loading && error) {
8994
setView(DeployToWorldView.ERROR)
9095
setLoading(false)
9196
analytics?.track('Publish to World step', { step: DeployToWorldView.ERROR })
@@ -354,6 +359,29 @@ export default function DeployToWorld({
354359
)
355360
}
356361

362+
const renderMultiSceneBlockedState = () => {
363+
return (
364+
<div className={styles.emptyState}>
365+
<div className={styles.modalHeader}>
366+
<h3>{t('deployment_modal.deploy_world.multi_scene_blocked.title')}</h3>
367+
</div>
368+
<div className={`${styles.modalBodyState} ${styles.modalBodyEmptyState}`}>
369+
<div className={styles.emptyThumbnail} aria-label={project?.description} role="img" />
370+
<span className={styles.description}>{t('deployment_modal.deploy_world.multi_scene_blocked.description')}</span>
371+
</div>
372+
<div className={styles.modalBodyStateActions}>
373+
<Button
374+
primary
375+
className={styles.modalBodyStateActionButton}
376+
onClick={() => window.open(CREATOR_HUB_DOWNLOAD_URL, '_blank', 'noopener,noreferrer')}
377+
>
378+
{t('deployment_modal.deploy_world.multi_scene_blocked.download_creator_hub')}
379+
</Button>
380+
</div>
381+
</div>
382+
)
383+
}
384+
357385
const renderMetrics = () => {
358386
const { rows, cols } = project.layout
359387
return (
@@ -476,6 +504,8 @@ export default function DeployToWorld({
476504
return renderFailureState()
477505
case DeployToWorldView.EMPTY:
478506
return renderEmptyState()
507+
case DeployToWorldView.MULTI_SCENE_BLOCKED:
508+
return renderMultiSceneBlockedState()
479509
default:
480510
return null
481511
}

src/components/Modals/DeployModal/DeployToWorld/DeployToWorld.types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ export enum DeployToWorldView {
5959
PROGRESS = 'PROGRESS',
6060
SUCCESS = 'SUCCESS',
6161
EMPTY = 'EMPTY',
62-
ERROR = 'ERROR'
62+
ERROR = 'ERROR',
63+
MULTI_SCENE_BLOCKED = 'MULTI_SCENE_BLOCKED'
6364
}
6465

6566
export type DeployToWorldModalMetadata = DeployModalMetadata & {

src/components/Modals/WorldPermissionsModal/ModelTabs/WorldPermissionsCollaborators/WorldPermissionsCollaborators.module.css

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,29 @@
2626
color: #716b7c;
2727
justify-content: center;
2828
}
29+
30+
.callout {
31+
display: flex;
32+
align-items: flex-start;
33+
gap: 8px;
34+
padding: 12px 16px;
35+
margin-bottom: 16px;
36+
border-radius: 8px;
37+
background-color: #1a1820;
38+
border: 1px solid #3d3450;
39+
font-size: 14px;
40+
line-height: 1.5;
41+
}
42+
43+
.callout :global(.icon) {
44+
color: #716b7c;
45+
}
46+
47+
.callout p {
48+
color: #a09ba8;
49+
}
50+
51+
.callout a {
52+
color: #ffffff;
53+
text-decoration: underline;
54+
}

src/components/Modals/WorldPermissionsModal/ModelTabs/WorldPermissionsCollaborators/WorldPermissionsCollaborators.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import React from 'react'
33
import { Icon, Popup, Table } from 'decentraland-ui'
44
import { T, t } from 'decentraland-dapps/dist/modules/translation/utils'
55

6+
import { config } from 'config'
67
import { WorldPermissionsCollaboratorsProps } from './WorldPermissionsCollaborators.types'
78
import { WorldPermissionsAddUserForm } from '../Layouts/WorldPermissionsAddUserForm'
89
import { WorldPermissionsHeader } from '../Layouts/WorldPermissionsHeader'
@@ -11,6 +12,8 @@ import LoadingText from 'decentraland-ui/dist/components/Loader/LoadingText'
1112

1213
import styles from './WorldPermissionsCollaborators.module.css'
1314

15+
const CREATOR_HUB_DOWNLOAD_URL = config.get('CREATOR_HUB_DOWNLOAD_URL')
16+
1417
export default React.memo((props: WorldPermissionsCollaboratorsProps) => {
1518
const {
1619
loading,
@@ -24,7 +27,8 @@ export default React.memo((props: WorldPermissionsCollaboratorsProps) => {
2427
onRemoveCollaborator,
2528
error,
2629
worldDeploymentPermissions,
27-
worldStreamingPermissions
30+
worldStreamingPermissions,
31+
permissionsSummary
2832
} = props
2933
return (
3034
<div>
@@ -41,6 +45,23 @@ export default React.memo((props: WorldPermissionsCollaboratorsProps) => {
4145
}
4246
loading={loading}
4347
/>
48+
{!loading && (
49+
<div className={styles.callout}>
50+
<Icon name="info circle" />
51+
<p>
52+
<T
53+
id="world_permissions_modal.tab_collaborators.parcel_permissions_callout"
54+
values={{
55+
link: (content: React.ReactNode) => (
56+
<a href={CREATOR_HUB_DOWNLOAD_URL} target="_blank" rel="noopener noreferrer">
57+
{content}
58+
</a>
59+
)
60+
}}
61+
/>
62+
</p>
63+
</div>
64+
)}
4465

4566
{(!collaboratorUserList || collaboratorUserList.length < 10) && (
4667
<WorldPermissionsAddUserForm
@@ -117,6 +138,7 @@ export default React.memo((props: WorldPermissionsCollaboratorsProps) => {
117138
onRemoveCollaborator={onRemoveCollaborator}
118139
hasWorldDeploymentPermission={worldDeploymentPermissions?.wallets.includes(wallet)}
119140
hasWorldStreamingPermission={worldStreamingPermissions?.wallets.includes(wallet)}
141+
permissionsSummary={permissionsSummary?.[wallet] ?? []}
120142
key={index}
121143
walletAddress={wallet}
122144
/>

src/components/Modals/WorldPermissionsModal/ModelTabs/WorldPermissionsCollaborators/WorldPermissionsCollaborators.types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { ButtonProps, InputOnChangeData } from 'decentraland-ui'
2-
import { AllowListPermissionSetting, WorldPermissionNames } from 'lib/api/worlds'
2+
import { WorldCollaboratorPermission, AllowListPermissionSetting, WorldPermissionNames } from 'lib/api/worlds'
33

44
export type WorldPermissionsCollaboratorsProps = {
55
loading: boolean
66
worldDeploymentPermissions?: AllowListPermissionSetting
77
worldStreamingPermissions?: AllowListPermissionSetting
8+
permissionsSummary?: Record<string, WorldCollaboratorPermission[]>
89
collaboratorUserList?: string[]
910
showAddUserForm: boolean
1011
newAddress: string
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.userCell {
2+
display: flex;
3+
align-items: center;
4+
gap: 16px;
5+
}
6+
7+
.parcelBadge {
8+
margin-right: 100%;
9+
}

src/components/Modals/WorldPermissionsModal/ModelTabs/WorldPermissionsCollaborators/WorldPermissionsCollaboratorsItem/WorldPermissionsCollaboratorsItem.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
import React from 'react'
1+
import React, { useMemo } from 'react'
22
import { Checkbox, Table } from 'decentraland-ui'
3+
import { Chip } from 'decentraland-ui2'
34
import { Button } from 'decentraland-ui/dist/components/Button/Button'
45
import LoadingText from 'decentraland-ui/dist/components/Loader/LoadingText'
6+
import { t } from 'decentraland-dapps/dist/modules/translation/utils'
57
import { WorldPermissionNames } from 'lib/api/worlds'
68
import Icon from 'components/Icon'
79
import { Props } from './WorldPermissionsCollaboratorsItem.types'
810
import { WorldPermissionsAvatarWithInfo } from '../../Layouts/WorldPermissionsAvatarWithInfo'
11+
import styles from './WorldPermissionsCollaboratorsItem.module.css'
912

1013
export const WORLD_PERMISSIONS_COLLABORATORS_ITEM_LOADING_ROW_TEST_ID = 'world-permissions-collaborators-item-test-id'
1114
export const WORLD_PERMISSIONS_COLLABORATORS_ITEM_DEPLOYMENT_CHECKBOX_TEST_ID =
@@ -19,11 +22,17 @@ export const WorldPermissionsCollaboratorsItem = React.memo((props: Props) => {
1922
walletAddress,
2023
hasWorldDeploymentPermission,
2124
hasWorldStreamingPermission,
25+
permissionsSummary,
2226
onUserPermissionListChange,
2327
onRemoveCollaborator,
2428
loading
2529
} = props
2630

31+
const parcelCount: number = useMemo(
32+
() => permissionsSummary?.find(p => p.permission === 'deployment')?.parcel_count ?? 0,
33+
[permissionsSummary]
34+
)
35+
2736
if (loading || !walletAddress || !onUserPermissionListChange) {
2837
return (
2938
<Table.Row data-testid={WORLD_PERMISSIONS_COLLABORATORS_ITEM_LOADING_ROW_TEST_ID}>
@@ -45,8 +54,14 @@ export const WorldPermissionsCollaboratorsItem = React.memo((props: Props) => {
4554

4655
return (
4756
<Table.Row>
48-
<Table.Cell>
57+
<Table.Cell className={styles.userCell}>
4958
<WorldPermissionsAvatarWithInfo walletAddress={walletAddress} />
59+
{parcelCount > 0 && (
60+
<Chip
61+
className={styles.parcelBadge}
62+
label={t('world_permissions_modal.tab_collaborators.parcel_count_badge', { count: parcelCount })}
63+
/>
64+
)}
5065
</Table.Cell>
5166
<Table.Cell>
5267
<Checkbox

0 commit comments

Comments
 (0)