Skip to content

Commit

Permalink
Input/controls constraints for viewers (#4713)
Browse files Browse the repository at this point in the history
* disable inputs for non-editors

* update snaps

* update snaps

* fix guideline test

* snaps

* update tests with store hook

* useIsMyProject

* revert
  • Loading branch information
ruggi authored Jan 10, 2024
1 parent 6b2cb42 commit 4dc398d
Show file tree
Hide file tree
Showing 18 changed files with 192 additions and 76 deletions.
65 changes: 41 additions & 24 deletions editor/src/components/canvas/controls/new-canvas-controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down Expand Up @@ -501,6 +502,8 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => {
})
}

const isMyProject = useIsMyProject()

const resizeStatus = getResizeStatus()

return (
Expand Down Expand Up @@ -531,42 +534,56 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => {
{when(
resizeStatus !== 'disabled',
<>
{inspectorFocusedControls.map((c) => (
<RenderControlMemoized key={c.key} control={c.control} propsForControl={c.props} />
))}
{inspectorHoveredControls.map((c) => (
<RenderControlMemoized key={c.key} control={c.control} propsForControl={c.props} />
))}
{when(
isSelectMode(editorMode),
<RemixSceneLabelControl
maybeHighlightOnHover={maybeHighlightOnHover}
maybeClearHighlightsOnHoverEnd={maybeClearHighlightsOnHoverEnd}
/>,
)}
{when(isSelectMode(editorMode) && !anyStrategyActive, <PinLines />)}
{when(isSelectMode(editorMode), <InsertionControls />)}
{renderHighlightControls()}
{renderTextEditableControls()}
{unless(dragInteractionActive, <LayoutParentControl />)}
{when(isSelectMode(editorMode), <AbsoluteChildrenOutline />)}
<MultiSelectOutlineControl localSelectedElements={localSelectedViews} />
<ZeroSizedElementControls.control showAllPossibleElements={false} />

{when(
isSelectOrInsertMode(editorMode) &&
!EP.multiplePathsAllWithTheSameUID(localSelectedViews),
isMyProject,
<>
{strategyControls.map((c) => (
{inspectorFocusedControls.map((c) => (
<RenderControlMemoized
key={c.key}
control={c.control}
propsForControl={c.props}
/>
))}
{inspectorHoveredControls.map((c) => (
<RenderControlMemoized
key={c.key}
control={c.control.control}
control={c.control}
propsForControl={c.props}
/>
))}
{when(
isSelectMode(editorMode),
<RemixSceneLabelControl
maybeHighlightOnHover={maybeHighlightOnHover}
maybeClearHighlightsOnHoverEnd={maybeClearHighlightsOnHoverEnd}
/>,
)}
{when(isSelectMode(editorMode) && !anyStrategyActive, <PinLines />)}
{when(isSelectMode(editorMode), <InsertionControls />)}
{renderTextEditableControls()}
{when(isSelectMode(editorMode), <AbsoluteChildrenOutline />)}
{when(
isSelectOrInsertMode(editorMode) &&
!EP.multiplePathsAllWithTheSameUID(localSelectedViews),
<>
{strategyControls.map((c) => (
<RenderControlMemoized
key={c.key}
control={c.control.control}
propsForControl={c.props}
/>
))}
</>,
)}
{when(isSelectMode(editorMode), <DistanceGuidelineControl />)}
<GuidelineControls />
</>,
)}
{when(isSelectMode(editorMode), <DistanceGuidelineControl />)}
<GuidelineControls />
{when(
roomStatus === 'connected',
<MultiplayerWrapper errorFallback={null} suspenseFallback={null}>
Expand Down
4 changes: 1 addition & 3 deletions editor/src/components/canvas/design-panel-root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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'
Expand Down
3 changes: 3 additions & 0 deletions editor/src/components/editor/global-shortcuts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,9 @@ export function handleKeyDown(
)
},
[INSERT_DIV_SHORTCUT]: () => {
if (!allowedToEdit) {
return []
}
if (!isSelectMode(editor.mode) && !isInsertMode(editor.mode)) {
return []
}
Expand Down
8 changes: 8 additions & 0 deletions editor/src/components/editor/store/collaborative-editing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -790,3 +790,11 @@ export function useAllowedToEditProject(): boolean {
'useAllowedToEditProject',
)
}

export function useIsMyProject(): boolean {
return useEditorState(
Substores.projectServerState,
(store) => store.projectServerState.isMyProject === 'yes',
'useIsMyProject',
)
}
4 changes: 4 additions & 0 deletions editor/src/components/inspector/controls/color-control.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 : (
<ColorPicker
id={props.id}
Expand All @@ -91,6 +94,7 @@ export const ColorControl = React.memo((props: ColorControlProps) => {
value={props.value}
onSubmitValue={props.onSubmitValue}
onTransientSubmitValue={props.onTransientSubmitValue}
disabled={!isMyProject}
/>
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -106,6 +112,7 @@ export const ColorPickerSwatches = React.memo((props: ColorPickerSwatchesProps)
style={{
padding: '0 6px',
}}
disabled={!isMyProject}
onMouseDown={toggleEditing}
>
{when(editing, <Icons.Checkmark />)}
Expand Down
12 changes: 12 additions & 0 deletions editor/src/components/inspector/controls/color-picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const checkerboardBackground = UtopiaStyles.backgrounds.checkerboardBackground
export interface ColorPickerProps extends ColorPickerInnerProps {
closePopup: () => void
portalTarget?: HTMLElement
disabled: boolean
}

export const colorPickerWidth = 290
Expand Down Expand Up @@ -96,6 +97,7 @@ export interface ColorPickerInnerProps {
offsetY: number
id: string
testId: string
disabled: boolean
}

function toPassedInColorType(
Expand Down Expand Up @@ -340,6 +342,9 @@ export class ColorPickerInner extends React.Component<

onMouseDownSV = (e: React.MouseEvent<HTMLDivElement>) => {
e.stopPropagation()
if (this.props.disabled) {
return
}
this.setState({
isScrubbing: true,
})
Expand Down Expand Up @@ -399,6 +404,9 @@ export class ColorPickerInner extends React.Component<

onHueSliderMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
e.stopPropagation()
if (this.props.disabled) {
return
}

if (this.HueControlRef.current != null) {
this.HueOriginLeft = this.HueControlRef.current.getBoundingClientRect().left
Expand Down Expand Up @@ -437,6 +445,10 @@ export class ColorPickerInner extends React.Component<

onAlphaSliderMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
e.stopPropagation()
if (this.props.disabled) {
return
}

if (this.AlphaControlRef.current != null) {
this.setState({
isScrubbing: true,
Expand Down
5 changes: 3 additions & 2 deletions editor/src/components/inspector/controls/option-control.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -60,7 +61,7 @@ export const OptionControl: React.FunctionComponent<
}
}

const rc = controlOptions.roundCorners
const isMyProject = useIsMyProject()

const background = (() => {
if (props.controlStatus === 'overridden' && props.value) {
Expand Down Expand Up @@ -133,7 +134,7 @@ export const OptionControl: React.FunctionComponent<
}}
type='checkbox'
checked={isChecked}
disabled={!props.controlStyles.interactive}
disabled={!props.controlStyles.interactive || !isMyProject}
onChange={onSubmitValue}
/>
<div
Expand Down
5 changes: 4 additions & 1 deletion editor/src/components/inspector/controls/slider-control.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Slider from 'rc-slider'
import React from 'react'
import { FlexRow, UtopiaTheme } from '../../../uuiui'
import type { DEPRECATEDControlProps, DEPRECATEDGenericControlOptions } from './control'
import { useIsMyProject } from '../../editor/store/collaborative-editing'

export interface DEPRECATEDSliderControlOptions extends DEPRECATEDGenericControlOptions {
minimum: number
Expand Down Expand Up @@ -101,6 +102,8 @@ export const SliderControl: React.FunctionComponent<React.PropsWithChildren<Slid
}
}

const isMyProject = useIsMyProject()

return (
<FlexRow
style={{
Expand All @@ -115,7 +118,7 @@ export const SliderControl: React.FunctionComponent<React.PropsWithChildren<Slid
onContextMenu={props.onContextMenu}
>
<Slider
disabled={!props.controlStyles.interactive}
disabled={!props.controlStyles.interactive || !isMyProject}
value={isSliding ? slidingValue : value}
onBeforeChange={handleBeforeChange}
onChange={handleDragging}
Expand Down
24 changes: 14 additions & 10 deletions editor/src/components/inspector/inspector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ import { FlexCol } from 'utopia-api'
import { SettingsPanel } from './sections/settings-panel/inspector-settingspanel'
import { strictEvery } from '../../core/shared/array-utils'
import { SimplifiedLayoutSubsection } from './sections/layout-section/self-layout-subsection/simplified-layout-subsection'
import { isFeatureEnabled } from '../../utils/feature-switches'
import { ConstraintsSection } from './constraints-section'
import { useIsMyProject } from '../editor/store/collaborative-editing'

export interface ElementPathElement {
name?: string
Expand Down Expand Up @@ -336,6 +336,8 @@ export const Inspector = React.memo<InspectorProps>((props: InspectorProps) => {
'Inspector anyKnownElements',
)

const isMyProject = useIsMyProject()

function renderInspectorContents() {
return (
<React.Fragment>
Expand Down Expand Up @@ -378,18 +380,20 @@ export const Inspector = React.memo<InspectorProps>((props: InspectorProps) => {
)}
<CodeElementSection paths={selectedViews} />
<ConditionalSection paths={selectedViews} />

{unless(
hideAllSections,
<>
<TargetSelectorSection
targets={props.targets}
selectedTargetPath={props.selectedTargetPath}
onSelectTarget={props.onSelectTarget}
onStyleSelectorRename={props.onStyleSelectorRename}
onStyleSelectorDelete={props.onStyleSelectorDelete}
onStyleSelectorInsert={props.onStyleSelectorInsert}
/>
{when(
isMyProject,
<TargetSelectorSection
targets={props.targets}
selectedTargetPath={props.selectedTargetPath}
onSelectTarget={props.onSelectTarget}
onStyleSelectorRename={props.onStyleSelectorRename}
onStyleSelectorDelete={props.onStyleSelectorDelete}
onStyleSelectorInsert={props.onStyleSelectorInsert}
/>,
)}
{when(multiselectedContract === 'fragment', <FragmentSection />)}
{unless(
multiselectedContract === 'fragment',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -545,6 +546,8 @@ export const BackgroundPicker: React.FunctionComponent<
}
})()

const isMyProject = useIsMyProject()

return (
<InspectorModal
offsetX={props.offsetX - colorPickerWidth}
Expand Down Expand Up @@ -631,6 +634,7 @@ export const BackgroundPicker: React.FunctionComponent<
offsetY={props.offsetY}
id={props.id}
testId={props.testId}
disabled={!isMyProject}
/>
) : (
<ColorPickerInner
Expand All @@ -641,6 +645,7 @@ export const BackgroundPicker: React.FunctionComponent<
offsetY={props.offsetY}
id={props.id}
testId={props.testId}
disabled={!isMyProject}
/>
)
) : null}
Expand Down
Loading

0 comments on commit 4dc398d

Please sign in to comment.