diff --git a/editor/src/components/canvas/controls/new-canvas-controls.tsx b/editor/src/components/canvas/controls/new-canvas-controls.tsx index 9dacd48d7ad5..1d705eff25fc 100644 --- a/editor/src/components/canvas/controls/new-canvas-controls.tsx +++ b/editor/src/components/canvas/controls/new-canvas-controls.tsx @@ -66,9 +66,10 @@ import { import { useSelectionArea } from './selection-area-hooks' import { RemixSceneLabelControl } from './select-mode/remix-scene-label' import { NO_OP } from '../../../core/shared/utils' +import { useIsMyProject } from '../../editor/store/collaborative-editing' +import { useStatus } from '../../../../liveblocks.config' import { MultiplayerWrapper } from '../../../utils/multiplayer-wrapper' import { MultiplayerPresence } from '../multiplayer-presence' -import { useStatus } from '../../../../liveblocks.config' export const CanvasControlsContainerID = 'new-canvas-controls-container' @@ -501,6 +502,8 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => { }) } + const isMyProject = useIsMyProject() + const resizeStatus = getResizeStatus() return ( @@ -531,42 +534,56 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => { {when( resizeStatus !== 'disabled', <> - {inspectorFocusedControls.map((c) => ( - - ))} - {inspectorHoveredControls.map((c) => ( - - ))} - {when( - isSelectMode(editorMode), - , - )} - {when(isSelectMode(editorMode) && !anyStrategyActive, )} - {when(isSelectMode(editorMode), )} {renderHighlightControls()} - {renderTextEditableControls()} {unless(dragInteractionActive, )} - {when(isSelectMode(editorMode), )} + {when( - isSelectOrInsertMode(editorMode) && - !EP.multiplePathsAllWithTheSameUID(localSelectedViews), + isMyProject, <> - {strategyControls.map((c) => ( + {inspectorFocusedControls.map((c) => ( + + ))} + {inspectorHoveredControls.map((c) => ( ))} + {when( + isSelectMode(editorMode), + , + )} + {when(isSelectMode(editorMode) && !anyStrategyActive, )} + {when(isSelectMode(editorMode), )} + {renderTextEditableControls()} + {when(isSelectMode(editorMode), )} + {when( + isSelectOrInsertMode(editorMode) && + !EP.multiplePathsAllWithTheSameUID(localSelectedViews), + <> + {strategyControls.map((c) => ( + + ))} + , + )} + {when(isSelectMode(editorMode), )} + , )} - {when(isSelectMode(editorMode), )} - {when( roomStatus === 'connected', diff --git a/editor/src/components/canvas/design-panel-root.tsx b/editor/src/components/canvas/design-panel-root.tsx index c50b27f8da25..124a88253e5e 100644 --- a/editor/src/components/canvas/design-panel-root.tsx +++ b/editor/src/components/canvas/design-panel-root.tsx @@ -20,7 +20,7 @@ import { import { ConsoleAndErrorsPane } from '../code-editor/console-and-errors-pane' import { CanvasStrategyInspector } from './canvas-strategies/canvas-strategy-inspector' import { getQueryParam } from '../../common/env-vars' -import { unless, when } from '../../utils/react-conditionals' +import { when } from '../../utils/react-conditionals' import { InsertMenuPane } from '../navigator/insert-menu-pane' import { VariablesMenuPane } from '../navigator/variables-menu-pane' import { useDispatch } from '../editor/store/dispatch-context' @@ -31,9 +31,7 @@ import { SettingsPane } from '../navigator/left-pane/settings-pane' import { MenuTab } from '../../uuiui/menu-tab' import { FlexRow } from 'utopia-api' import type { StoredPanel } from './stored-layout' -import { MultiplayerPresence } from './multiplayer-presence' import { useRoom, useStatus } from '../../../liveblocks.config' -import { MultiplayerWrapper } from '../../utils/multiplayer-wrapper' import { isFeatureEnabled } from '../../utils/feature-switches' import { CommentsPane } from '../inspector/comments-pane' import { EditorModes, isCommentMode } from '../editor/editor-modes' diff --git a/editor/src/components/editor/global-shortcuts.tsx b/editor/src/components/editor/global-shortcuts.tsx index 90d532d60996..8ac03db4f830 100644 --- a/editor/src/components/editor/global-shortcuts.tsx +++ b/editor/src/components/editor/global-shortcuts.tsx @@ -686,6 +686,9 @@ export function handleKeyDown( ) }, [INSERT_DIV_SHORTCUT]: () => { + if (!allowedToEdit) { + return [] + } if (!isSelectMode(editor.mode) && !isInsertMode(editor.mode)) { return [] } diff --git a/editor/src/components/editor/store/collaborative-editing.ts b/editor/src/components/editor/store/collaborative-editing.ts index 2882d09a650b..ba2200e3ac08 100644 --- a/editor/src/components/editor/store/collaborative-editing.ts +++ b/editor/src/components/editor/store/collaborative-editing.ts @@ -790,3 +790,11 @@ export function useAllowedToEditProject(): boolean { 'useAllowedToEditProject', ) } + +export function useIsMyProject(): boolean { + return useEditorState( + Substores.projectServerState, + (store) => store.projectServerState.isMyProject === 'yes', + 'useIsMyProject', + ) +} diff --git a/editor/src/components/inspector/controls/color-control.tsx b/editor/src/components/inspector/controls/color-control.tsx index c0dc93c8623f..ea65f96cb403 100644 --- a/editor/src/components/inspector/controls/color-control.tsx +++ b/editor/src/components/inspector/controls/color-control.tsx @@ -8,6 +8,7 @@ import type { ControlStyles } from '../common/control-styles' import type { ControlStatus } from '../common/control-status' import { useColorTheme, UtopiaTheme } from '../../../uuiui' import Utils from '../../../utils/utils' +import { useIsMyProject } from '../../editor/store/collaborative-editing' export interface ColorControlProps { value: CSSColor @@ -81,6 +82,8 @@ export const ColorControl = React.memo((props: ColorControlProps) => { const closePopup = React.useCallback(() => setPopupOpen(false), [setPopupOpen]) + const isMyProject = useIsMyProject() + const picker = !popupOpen ? null : ( { value={props.value} onSubmitValue={props.onSubmitValue} onTransientSubmitValue={props.onTransientSubmitValue} + disabled={!isMyProject} /> ) diff --git a/editor/src/components/inspector/controls/color-picker-swatches.tsx b/editor/src/components/inspector/controls/color-picker-swatches.tsx index 455147947192..7057ec8118d2 100644 --- a/editor/src/components/inspector/controls/color-picker-swatches.tsx +++ b/editor/src/components/inspector/controls/color-picker-swatches.tsx @@ -15,6 +15,7 @@ import { useDispatch } from '../../editor/store/dispatch-context' import type { ColorSwatch } from '../../editor/store/editor-state' import { Substores, useEditorState } from '../../editor/store/store-hook' import { cssColorToChromaColorOrDefault } from '../common/css-utils' +import { useIsMyProject } from '../../editor/store/collaborative-editing' const { checkerboardBackground } = UtopiaStyles.backgrounds @@ -53,9 +54,14 @@ export const ColorPickerSwatches = React.memo((props: ColorPickerSwatchesProps) } }, [colorSwatches]) + const isMyProject = useIsMyProject() + const toggleEditing = React.useCallback(() => { + if (!isMyProject) { + return + } setEditing(!editing) - }, [editing]) + }, [editing, isMyProject]) const onAddColor = React.useCallback(() => { if (currentColor == null) { @@ -106,6 +112,7 @@ export const ColorPickerSwatches = React.memo((props: ColorPickerSwatchesProps) style={{ padding: '0 6px', }} + disabled={!isMyProject} onMouseDown={toggleEditing} > {when(editing, )} diff --git a/editor/src/components/inspector/controls/color-picker.tsx b/editor/src/components/inspector/controls/color-picker.tsx index d01eb28057d6..837564412a84 100644 --- a/editor/src/components/inspector/controls/color-picker.tsx +++ b/editor/src/components/inspector/controls/color-picker.tsx @@ -31,6 +31,7 @@ const checkerboardBackground = UtopiaStyles.backgrounds.checkerboardBackground export interface ColorPickerProps extends ColorPickerInnerProps { closePopup: () => void portalTarget?: HTMLElement + disabled: boolean } export const colorPickerWidth = 290 @@ -96,6 +97,7 @@ export interface ColorPickerInnerProps { offsetY: number id: string testId: string + disabled: boolean } function toPassedInColorType( @@ -340,6 +342,9 @@ export class ColorPickerInner extends React.Component< onMouseDownSV = (e: React.MouseEvent) => { e.stopPropagation() + if (this.props.disabled) { + return + } this.setState({ isScrubbing: true, }) @@ -399,6 +404,9 @@ export class ColorPickerInner extends React.Component< onHueSliderMouseDown = (e: React.MouseEvent) => { e.stopPropagation() + if (this.props.disabled) { + return + } if (this.HueControlRef.current != null) { this.HueOriginLeft = this.HueControlRef.current.getBoundingClientRect().left @@ -437,6 +445,10 @@ export class ColorPickerInner extends React.Component< onAlphaSliderMouseDown = (e: React.MouseEvent) => { e.stopPropagation() + if (this.props.disabled) { + return + } + if (this.AlphaControlRef.current != null) { this.setState({ isScrubbing: true, diff --git a/editor/src/components/inspector/controls/option-control.tsx b/editor/src/components/inspector/controls/option-control.tsx index df1b3518c818..a5c3ad26cee2 100644 --- a/editor/src/components/inspector/controls/option-control.tsx +++ b/editor/src/components/inspector/controls/option-control.tsx @@ -6,6 +6,7 @@ import type { DEPRECATEDControlProps, DEPRECATEDGenericControlOptions } from './ import { colorTheme } from '../../../uuiui' import type { IcnProps } from '../../../uuiui' import { UtopiaTheme, Tooltip, Icn } from '../../../uuiui' +import { useIsMyProject } from '../../editor/store/collaborative-editing' export interface DEPRECATEDOptionControlOptions extends DEPRECATEDGenericControlOptions { icon?: IcnProps @@ -60,7 +61,7 @@ export const OptionControl: React.FunctionComponent< } } - const rc = controlOptions.roundCorners + const isMyProject = useIsMyProject() const background = (() => { if (props.controlStatus === 'overridden' && props.value) { @@ -133,7 +134,7 @@ export const OptionControl: React.FunctionComponent< }} type='checkbox' checked={isChecked} - disabled={!props.controlStyles.interactive} + disabled={!props.controlStyles.interactive || !isMyProject} onChange={onSubmitValue} />
((props: InspectorProps) => { 'Inspector anyKnownElements', ) + const isMyProject = useIsMyProject() + function renderInspectorContents() { return ( @@ -378,18 +380,20 @@ export const Inspector = React.memo((props: InspectorProps) => { )} - {unless( hideAllSections, <> - + {when( + isMyProject, + , + )} {when(multiselectedContract === 'fragment', )} {unless( multiselectedContract === 'fragment', diff --git a/editor/src/components/inspector/sections/style-section/background-subsection/background-picker.tsx b/editor/src/components/inspector/sections/style-section/background-subsection/background-picker.tsx index f1e14a0a3704..85b1bcd2d32f 100644 --- a/editor/src/components/inspector/sections/style-section/background-subsection/background-picker.tsx +++ b/editor/src/components/inspector/sections/style-section/background-subsection/background-picker.tsx @@ -73,6 +73,7 @@ import { GradientStopsEditor } from './gradient-stop-editor' import { getIndexedUpdateCSSBackgroundLayerLinearGradientAngle } from './linear-gradient-layer' import { PickerImagePreview } from './picker-image-preview' import { setProp_UNSAFE } from '../../../../editor/actions/action-creators' +import { useIsMyProject } from '../../../../editor/store/collaborative-editing' const backgroundLayerOptionsByValue: { [key in CSSBackgroundLayerType]: CSSBackgroundLayerTypeSelectOption @@ -545,6 +546,8 @@ export const BackgroundPicker: React.FunctionComponent< } })() + const isMyProject = useIsMyProject() + return ( ) : ( ) ) : null} diff --git a/editor/src/components/user-bar.tsx b/editor/src/components/user-bar.tsx index 2da2ed0b3102..f8c63e1afa36 100644 --- a/editor/src/components/user-bar.tsx +++ b/editor/src/components/user-bar.tsx @@ -21,6 +21,7 @@ import { showToast, switchEditorMode } from './editor/actions/action-creators' import { EditorModes, isFollowMode } from './editor/editor-modes' import { useDispatch } from './editor/store/dispatch-context' import { Substores, useEditorState } from './editor/store/store-hook' +import { useIsMyProject } from './editor/store/collaborative-editing' const MAX_VISIBLE_OTHER_PLAYERS = 4 @@ -58,11 +59,8 @@ export const SinglePlayerUserBar = React.memo(() => { (store) => getUserPicture(store.userState.loginState), 'SinglePlayerUserBar userPicture', ) - const amIOwner = useEditorState( - Substores.projectServerState, - (store) => store.projectServerState.isMyProject === 'yes', - 'SinglePlayerUserBar amIOwner', - ) + const isMyProject = useIsMyProject() + return (
{ }} > - {amIOwner ? : null} + {isMyProject ? : null}
) }) diff --git a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap index ace17ae7bcdc..121a2b457902 100644 --- a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap +++ b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap @@ -33,6 +33,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(MultiplayerPresence)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(MultiplayerWrapper)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", @@ -40,14 +41,14 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(SelectionAreaRectangle)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", - "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.fragment))///div", "//div//div:data-testid='multiselect-outline'", "//div//div:data-testid='multiselect-element-outline-utopia-storyboard-uid/scene-aaa/app-entity:parent/ccc'", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)()//Symbol(react.memo)()", "/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)())", "/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)())", @@ -645,6 +646,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(MultiplayerPresence)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(MultiplayerWrapper)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", @@ -652,14 +654,14 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(SelectionAreaRectangle)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", - "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.fragment))///div", "//div//div:data-testid='multiselect-outline'", "//div//div:data-testid='multiselect-element-outline-utopia-storyboard-uid/scene-aaa/app-entity:parent/ccc'", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)()//Symbol(react.memo)()", "/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)())", "/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)())", @@ -1198,6 +1200,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(MultiplayerPresence)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(MultiplayerWrapper)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", @@ -1508,6 +1511,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(MultiplayerPresence)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(MultiplayerWrapper)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", @@ -1952,6 +1956,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(MultiplayerPresence)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(MultiplayerWrapper)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", @@ -2251,6 +2256,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(MultiplayerPresence)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(MultiplayerWrapper)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", diff --git a/editor/src/core/performance/performance-regression-tests.spec.tsx b/editor/src/core/performance/performance-regression-tests.spec.tsx index 07edcc7e4de8..4e1a16d9608d 100644 --- a/editor/src/core/performance/performance-regression-tests.spec.tsx +++ b/editor/src/core/performance/performance-regression-tests.spec.tsx @@ -65,7 +65,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`704`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`706`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -127,7 +127,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`749`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`751`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -183,7 +183,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`535`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`536`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -249,7 +249,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`607`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`608`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) }) diff --git a/editor/src/uuiui/inputs/number-input.tsx b/editor/src/uuiui/inputs/number-input.tsx index 20f0adfe78cb..db5e7cf393b0 100644 --- a/editor/src/uuiui/inputs/number-input.tsx +++ b/editor/src/uuiui/inputs/number-input.tsx @@ -50,6 +50,7 @@ import { InspectorInput, } from './base-input' import { usePropControlledStateV2 } from '../../components/inspector/common/inspector-utils' +import { useIsMyProject } from '../../components/editor/store/collaborative-editing' export type LabelDragDirection = 'horizontal' | 'vertical' @@ -188,6 +189,8 @@ export const NumberInput = React.memo( const ref = React.useRef(null) const colorTheme = useColorTheme() + const isMyProject = useIsMyProject() + const controlStyles = React.useMemo((): ControlStyles => { return { ...getControlStyles(controlStatus), @@ -553,6 +556,9 @@ export const NumberInput = React.memo( const onIncrementMouseDown = React.useCallback( (e: React.MouseEvent) => { + if (!isMyProject) { + return + } if (e.button === 0) { e.stopPropagation() setIsFauxcused(true) @@ -564,7 +570,7 @@ export const NumberInput = React.memo( }, repeatThreshold) } }, - [incrementBy, stepSize, repeatIncrement, onIncrementMouseUp], + [incrementBy, stepSize, repeatIncrement, onIncrementMouseUp, isMyProject], ) const onDecrementMouseUp = React.useCallback(() => { @@ -596,6 +602,9 @@ export const NumberInput = React.memo( const onDecrementMouseDown = React.useCallback( (e: React.MouseEvent) => { + if (!isMyProject) { + return + } if (e.button === 0) { e.stopPropagation() setIsFauxcused(true) @@ -608,11 +617,14 @@ export const NumberInput = React.memo( ) } }, - [incrementBy, stepSize, repeatIncrement, onDecrementMouseUp], + [incrementBy, stepSize, repeatIncrement, onDecrementMouseUp, isMyProject], ) const onLabelMouseDown = React.useCallback( (e: React.MouseEvent) => { + if (!isMyProject) { + return + } if (e.button === 0) { e.stopPropagation() setIsFauxcused(true) @@ -625,7 +637,7 @@ export const NumberInput = React.memo( setGlobalCursor?.(CSSCursor.ResizeEW) } }, - [scrubOnMouseMove, scrubOnMouseUp, setGlobalCursor, value], + [scrubOnMouseMove, scrubOnMouseUp, setGlobalCursor, value, isMyProject], ) const placeholder = getControlStylesAwarePlaceholder(controlStyles) @@ -678,6 +690,7 @@ export const NumberInput = React.memo( controlStyles={controlStyles} controlStatus={controlStatus} testId={testId} + disabled={!isMyProject} focused={isFocused} hasLabel={labelInner != null} roundCorners={roundCorners} diff --git a/editor/src/uuiui/inputs/string-input.spec.browser2.tsx b/editor/src/uuiui/inputs/string-input.spec.browser2.tsx index 5be069859643..862b30a9f3ff 100644 --- a/editor/src/uuiui/inputs/string-input.spec.browser2.tsx +++ b/editor/src/uuiui/inputs/string-input.spec.browser2.tsx @@ -3,6 +3,10 @@ import type { RenderResult } from '@testing-library/react' import { render } from '@testing-library/react' import React from 'react' import { StringInput } from './string-input' +import { + TestInspectorContextProvider, + getStoreHook, +} from '../../components/inspector/common/inspector.test-utils' describe('StringInput', () => { function checkPlaceholder(renderResult: RenderResult, expectedPlaceholder: string | null): void { @@ -14,36 +18,62 @@ describe('StringInput', () => { } } it('ensures that no placeholder property shows in the input field by default', () => { - const result = render() + const storeHookForTest = getStoreHook() + const result = render( + + + , + ) checkPlaceholder(result, null) }) it('ensures that the placeholder property shows in the input field', () => { + const storeHookForTest = getStoreHook() const result = render( - , + + + , ) checkPlaceholder(result, 'this is a placeholder') }) it('ensures that the unknown control styles property shows in the input field', () => { + const storeHookForTest = getStoreHook() const result = render( - , + + + , ) checkPlaceholder(result, 'Unknown') }) it('ensures that the mixed control styles property shows in the input field', () => { + const storeHookForTest = getStoreHook() const result = render( - , + + + , ) checkPlaceholder(result, 'Mixed') }) diff --git a/editor/src/uuiui/inputs/string-input.tsx b/editor/src/uuiui/inputs/string-input.tsx index 6091078de75d..670e7f9d68b3 100644 --- a/editor/src/uuiui/inputs/string-input.tsx +++ b/editor/src/uuiui/inputs/string-input.tsx @@ -10,6 +10,7 @@ import { getControlStyles } from '../../components/inspector/common/control-styl import { preventDefault, stopPropagation } from '../../components/inspector/common/inspector-utils' import { useColorTheme } from '../styles/theme' import { InspectorInputEmotionStyle, getControlStylesAwarePlaceholder } from './base-input' +import { useIsMyProject } from '../../components/editor/store/collaborative-editing' interface StringInputOptions { focusOnMount?: boolean @@ -50,8 +51,10 @@ export const StringInput = React.memo( } }, [focusOnMount, ref]) + const isMyProject = useIsMyProject() + const controlStyles: ControlStyles = getControlStyles(controlStatus) - const disabled = !controlStyles.interactive + const disabled = !controlStyles.interactive || !isMyProject const inputPropsKeyDown = inputProps.onKeyDown diff --git a/editor/src/uuiui/widgets/popup-list/popup-list.tsx b/editor/src/uuiui/widgets/popup-list/popup-list.tsx index 42772638e642..d938c2ea8771 100644 --- a/editor/src/uuiui/widgets/popup-list/popup-list.tsx +++ b/editor/src/uuiui/widgets/popup-list/popup-list.tsx @@ -27,6 +27,7 @@ import type { ControlStyles, SelectOption } from '../../../uuiui-deps' import { CommonUtils, getControlStyles } from '../../../uuiui-deps' import { SmallerIcons } from '../../../uuiui/icons' import { Tooltip } from '../../tooltip' +import { useIsMyProject } from '../../../components/editor/store/collaborative-editing' type ContainerMode = 'default' | 'showBorderOnHover' | 'noBorder' @@ -587,10 +588,13 @@ export const PopupList = React.memo( style, containerMode = 'default', controlStyles = getControlStyles('simple'), - disabled = !controlStyles.interactive, + disabled: initialDisabled, }, ref, ) => { + const isMyProject = useIsMyProject() + const disabled = initialDisabled || !controlStyles.interactive || !isMyProject + const selectOnSubmitValue = React.useCallback( (newValue: ValueType) => { if (isOptionType(newValue)) {