Skip to content

Commit

Permalink
default to comment mode, hide non-read-only modes
Browse files Browse the repository at this point in the history
  • Loading branch information
ruggi committed Dec 6, 2023
1 parent e99b2e5 commit 7dfc52f
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 45 deletions.
30 changes: 19 additions & 11 deletions editor/src/components/canvas/design-panel-root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,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 { when } from '../../utils/react-conditionals'
import { unless, 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 @@ -38,6 +38,7 @@ import { MultiplayerWrapper } from '../../utils/multiplayer-wrapper'
import { CommentSection } from '../inspector/sections/comment-section'
import { isFeatureEnabled } from '../../utils/feature-switches'
import { CommentsPane } from '../inspector/comments-pane'
import { useIsViewer } from '../editor/store/project-server-state-hooks'

interface NumberSize {
width: number
Expand Down Expand Up @@ -229,6 +230,8 @@ export const RightPane = React.memo<ResizableRightPaneProps>((props) => {
onClickTab(RightMenuTab.Settings)
}, [onClickTab])

const isViewer = useIsViewer()

if (!isRightMenuExpanded) {
return null
}
Expand All @@ -253,16 +256,21 @@ export const RightPane = React.memo<ResizableRightPaneProps>((props) => {
selected={selectedTab === RightMenuTab.Inspector}
onClick={onClickInspectorTab}
/>
<MenuTab
label={'Insert'}
selected={selectedTab === RightMenuTab.Insert}
onClick={onClickInsertTab}
/>
<MenuTab
label={'Variables'}
selected={selectedTab === RightMenuTab.Variables}
onClick={onClickVariablesTab}
/>
{unless(
isViewer,
<>
<MenuTab
label={'Insert'}
selected={selectedTab === RightMenuTab.Insert}
onClick={onClickInsertTab}
/>
<MenuTab
label={'Variables'}
selected={selectedTab === RightMenuTab.Variables}
onClick={onClickVariablesTab}
/>
</>,
)}
{when(
isFeatureEnabled('Commenting'),
<MenuTab
Expand Down
10 changes: 8 additions & 2 deletions editor/src/components/canvas/multiplayer-presence.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,16 @@ export const MultiplayerPresence = React.memo(() => {
}
}, [updateMyPresence])

const [roomId, setRoomId] = React.useState<string>(room.id)

React.useEffect(() => {
// when the room changes, reset
setTimeout(() => dispatch([switchEditorMode(EditorModes.selectMode(null, false, 'none'))]), 0)
}, [room.id, dispatch])
// (unfortunately there's not a subscription event for room id changes :()
if (roomId !== room.id) {
setRoomId(room.id)
dispatch([switchEditorMode(EditorModes.selectMode(null, false, 'none'))])
}
}, [room.id, roomId, dispatch])

if (!isLoggedIn(loginState)) {
return null
Expand Down
54 changes: 30 additions & 24 deletions editor/src/components/editor/canvas-toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,12 @@ import {
} from './insert-callbacks'
import { useDispatch } from './store/dispatch-context'
import { Substores, useEditorState, useRefEditorState } from './store/store-hook'
import { togglePanel } from './actions/action-creators'
import { defaultTransparentViewElement } from './defaults'
import { generateUidWithExistingComponents } from '../../core/model/element-template-utils'
import { useToolbarMode } from './canvas-toolbar-states'
import { when } from '../../utils/react-conditionals'
import { unless, when } from '../../utils/react-conditionals'
import { StrategyIndicator } from '../canvas/controls/select-mode/strategy-indicator'
import { toggleAbsolutePositioningCommands } from '../inspector/inspector-common'
import { NO_OP } from '../../core/shared/utils'
import { createFilter } from 'react-select'
import WindowedSelect from 'react-windowed-select'
import { InspectorInputEmotionStyle } from '../../uuiui/inputs/base-input'
Expand All @@ -70,6 +68,7 @@ import {
} from '../canvas/ui/floating-insert-menu'
import { isFeatureEnabled } from '../../utils/feature-switches'
import { floatingInsertMenuStateSwap } from './store/editor-state'
import { useIsViewer } from './store/project-server-state-hooks'

export const InsertMenuButtonTestId = 'insert-menu-button'
export const PlayModeButtonTestId = 'canvas-toolbar-play-mode'
Expand Down Expand Up @@ -410,6 +409,8 @@ export const CanvasToolbar = React.memo(() => {
'TopMenu loggedIn',
)

const isViewer = useIsViewer()

return (
<FlexColumn
style={{ alignItems: 'start', justifySelf: 'center' }}
Expand Down Expand Up @@ -442,27 +443,32 @@ export const CanvasToolbar = React.memo(() => {
style={{ width: 36 }}
/>
</Tooltip>
<Tooltip title='Insert or Edit Text' placement='bottom'>
<InsertModeButton
iconType='text'
iconCategory='tools'
primary={canvasToolbarMode.primary === 'text'}
onClick={insertTextCallback}
keepActiveInLiveMode
style={{ width: 36 }}
/>
</Tooltip>
<Tooltip title='Insert' placement='bottom'>
<InsertModeButton
testid={InsertMenuButtonTestId}
iconType='insert'
iconCategory='tools'
primary={canvasToolbarMode.primary === 'insert'}
onClick={toggleInsertButtonClicked}
keepActiveInLiveMode
style={{ width: 36 }}
/>
</Tooltip>
{unless(
isViewer,
<>
<Tooltip title='Insert or Edit Text' placement='bottom'>
<InsertModeButton
iconType='text'
iconCategory='tools'
primary={canvasToolbarMode.primary === 'text'}
onClick={insertTextCallback}
keepActiveInLiveMode
style={{ width: 36 }}
/>
</Tooltip>
<Tooltip title='Insert' placement='bottom'>
<InsertModeButton
testid={InsertMenuButtonTestId}
iconType='insert'
iconCategory='tools'
primary={canvasToolbarMode.primary === 'insert'}
onClick={toggleInsertButtonClicked}
keepActiveInLiveMode
style={{ width: 36 }}
/>
</Tooltip>
</>,
)}
<Tooltip title='Live Mode' placement='bottom'>
<InsertModeButton
testid={PlayModeButtonTestId}
Expand Down
26 changes: 24 additions & 2 deletions editor/src/components/editor/editor-component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,32 @@ import {
githubOperationPrettyName,
LeftMenuTab,
} from './store/editor-state'
import { Substores, useEditorState, useRefEditorState } from './store/store-hook'
import {
Substores,
useEditorState,
useRefEditorState,
useSelectorWithCallback,
} from './store/store-hook'
import { ConfirmDisconnectBranchDialog } from '../filebrowser/confirm-branch-disconnect'
import { when } from '../../utils/react-conditionals'
import { LowPriorityStoreProvider } from './store/store-context-providers'
import { useDispatch } from './store/dispatch-context'
import type { EditorAction } from './action-types'
import { EditorCommon } from './editor-component-common'
import { notice } from '../common/notice'
import { ProjectServerStateUpdater } from './store/project-server-state'
import {
ProjectServerStateUpdater,
isProjectViewer,
isProjectViewerFromState,
} from './store/project-server-state'
import { RoomProvider, initialPresence, useRoom, initialStorage } from '../../../liveblocks.config'
import { generateUUID } from '../../utils/utils'
import { isLiveblocksEnabled } from './liveblocks-utils'
import type { Storage, Presence, RoomEvent, UserMeta } from '../../../liveblocks.config'
import LiveblocksProvider from '@liveblocks/yjs'
import { isRoomId, projectIdToRoomId } from '../../core/shared/multiplayer'
import { useDisplayOwnershipWarning } from './project-owner-hooks'
import { EditorModes } from './editor-modes'

const liveModeToastId = 'play-mode-toast'

Expand Down Expand Up @@ -209,6 +219,7 @@ export const EditorComponentInner = React.memo((props: EditorProps) => {
...handleKeyDown(
event,
editorStoreRef.current.editor,
editorStoreRef.current.projectServerState,
metadataRef,
navigatorTargetsRef,
namesByKey,
Expand Down Expand Up @@ -345,6 +356,17 @@ export const EditorComponentInner = React.memo((props: EditorProps) => {
[dispatch],
)

useSelectorWithCallback(
Substores.projectServerState,
(store) => store.projectServerState.isMyProject,
(isMyProject) => {
if (isProjectViewer(isMyProject)) {
dispatch([EditorActions.switchEditorMode(EditorModes.commentMode(null, 'not-dragging'))])
}
},
'EditorComponentInner viewer mode',
)

return (
<>
<ColorThemeComponent />
Expand Down
18 changes: 17 additions & 1 deletion editor/src/components/editor/global-shortcuts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ import {
TOGGLE_FOCUSED_OMNIBOX_TAB,
FOCUS_CLASS_NAME_INPUT,
INSERT_DIV_SHORTCUT,
OPEN_EYEDROPPPER as OPEN_EYEDROPPER,
OPEN_EYEDROPPER,
TEXT_EDIT_MODE,
TOGGLE_TEXT_BOLD,
TOGGLE_TEXT_ITALIC,
Expand Down Expand Up @@ -146,6 +146,7 @@ import type { ElementPathTrees } from '../../core/shared/element-path-tree'
import { createPasteToReplacePostActionActions } from '../canvas/canvas-strategies/post-action-options/post-action-options'
import { wrapInDivStrategy } from './wrap-in-callbacks'
import { isFeatureEnabled } from '../../utils/feature-switches'
import { isProjectViewerFromState, type ProjectServerState } from './store/project-server-state'

function updateKeysPressed(
keysPressed: KeysPressed,
Expand Down Expand Up @@ -354,6 +355,7 @@ export function preventBrowserShortcuts(editor: EditorState, event: KeyboardEven
export function handleKeyDown(
event: KeyboardEvent,
editor: EditorState,
projectServerState: ProjectServerState,
metadataRef: { current: ElementInstanceMetadataMap },
navigatorTargetsRef: { current: Array<NavigatorEntry> },
namesByKey: ShortcutNamesByKey,
Expand All @@ -362,6 +364,8 @@ export function handleKeyDown(
// Stop the browser from firing things like save dialogs.
preventBrowserShortcuts(editor, event)

const isViewer = isProjectViewerFromState(projectServerState)

// Ensure that any key presses are appropriately recorded.
const key = Keyboard.keyCharacterForCode(event.keyCode)
const editorTargeted = editorIsTarget(event, editor)
Expand Down Expand Up @@ -605,6 +609,9 @@ export function handleKeyDown(
return [EditorActions.toggleHidden()]
},
[INSERT_IMAGE_SHORTCUT]: () => {
if (isViewer) {
return []
}
if (isSelectMode(editor.mode) || isInsertMode(editor.mode)) {
// FIXME: Side effects.
insertImage(dispatch)
Expand Down Expand Up @@ -742,6 +749,9 @@ export function handleKeyDown(
}
},
[ADD_ELEMENT_SHORTCUT]: () => {
if (isViewer) {
return []
}
if (isSelectMode(editor.mode)) {
return [
EditorActions.openFloatingInsertMenu({
Expand Down Expand Up @@ -775,6 +785,9 @@ export function handleKeyDown(
return []
},
[TEXT_EDIT_MODE]: () => {
if (isViewer) {
return []
}
const newUID = generateUidWithExistingComponents(editor.projectContents)

actions.push(
Expand Down Expand Up @@ -949,6 +962,9 @@ export function handleKeyDown(
return [EditorActions.applyCommandsAction(commands)]
},
[OPEN_INSERT_MENU]: () => {
if (isViewer) {
return []
}
return [
EditorActions.setPanelVisibility('rightmenu', true),
EditorActions.setRightMenuTab(RightMenuTab.Insert),
Expand Down
4 changes: 2 additions & 2 deletions editor/src/components/editor/shortcut-definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export const PASTE_TO_REPLACE = 'paste-to-replace'
export const PASTE_STYLE_PROPERTIES = 'paste-style-properties'
export const COPY_STYLE_PROPERTIES = 'copy-style-properties'

export const OPEN_EYEDROPPPER = 'open-eyedropper'
export const OPEN_EYEDROPPER = 'open-eyedropper'
export const CONVERT_TO_FLEX_CONTAINER = 'convert-to-flex-container'
export const REMOVE_ABSOLUTE_POSITIONING = 'remove-absolute-positioning'
export const RESIZE_TO_FIT = 'resize-to-fit'
Expand Down Expand Up @@ -218,7 +218,7 @@ const shortcutDetailsWithDefaults: ShortcutDetails = {
),
[CONVERT_ELEMENT_SHORTCUT]: shortcut('Convert selected element to...', key('s', [])),
[ADD_ELEMENT_SHORTCUT]: shortcut('Add element...', key('a', [])),
[OPEN_EYEDROPPPER]: shortcut('Open the eyedropper', key('c', 'ctrl')),
[OPEN_EYEDROPPER]: shortcut('Open the eyedropper', key('c', 'ctrl')),
[TEXT_EDIT_MODE]: shortcut('Activate text edit mode', key('t', [])),
[TOGGLE_TEXT_BOLD]: shortcut(
'Toggle font-weight to bold of the currently selected text element.',
Expand Down
3 changes: 2 additions & 1 deletion editor/src/components/editor/store/dispatch-strategies.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import { last } from '../../../core/shared/array-utils'
import type { BuiltInDependencies } from '../../../core/es-modules/package-manager/built-in-dependencies-list'
import { isInsertMode } from '../editor-modes'
import { patchedCreateRemixDerivedDataMemo } from './remix-derived-data'
import { isProjectViewerFromState } from './project-server-state'

interface HandleStrategiesResult {
unpatchedEditorState: EditorState
Expand Down Expand Up @@ -657,7 +658,7 @@ export function handleStrategies(
let unpatchedEditorState: EditorState
let patchedEditorState: EditorState
let newStrategyState: StrategyState
if (storedState.projectServerState.isMyProject === 'no') {
if (isProjectViewerFromState(storedState.projectServerState)) {
unpatchedEditorState = result.unpatchedEditor
patchedEditorState = result.unpatchedEditor
newStrategyState = result.strategyState
Expand Down
11 changes: 11 additions & 0 deletions editor/src/components/editor/store/project-server-state-hooks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { isProjectViewerFromState } from './project-server-state'
import { Substores, useEditorState } from './store-hook'

export function useIsViewer(): boolean {
const isViewer = useEditorState(
Substores.projectServerState,
(store) => isProjectViewerFromState(store.projectServerState),
'useIsViewer isViewer',
)
return isViewer
}
12 changes: 11 additions & 1 deletion editor/src/components/editor/store/project-server-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ export function projectMetadataFromServer(
}
}

export type IsMyProject = 'yes' | 'no' | 'unknown'

export interface ProjectServerState {
isMyProject: 'yes' | 'no' | 'unknown'
isMyProject: IsMyProject
ownerId: string | null
projectData: ProjectMetadataFromServer | null
forkedFromProjectData: ProjectMetadataFromServer | null
Expand Down Expand Up @@ -118,3 +120,11 @@ export const ProjectServerStateUpdater = React.memo(
return <>{children}</>
},
)

export function isProjectViewerFromState(state: ProjectServerState): boolean {
return isProjectViewer(state.isMyProject)
}

export function isProjectViewer(isMyProject: IsMyProject): boolean {
return isMyProject === 'no'
}
1 change: 0 additions & 1 deletion editor/src/components/navigator/dependency-list-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
AlternateColorThemeComponent,
} from '../../uuiui'
import { MenuProvider, MomentumContextMenu } from '../../uuiui-deps'
import { handleKeyDown } from '../editor/global-shortcuts'
import type { DependencyPackageDetails } from '../editor/store/editor-state'
import { unless } from '../../utils/react-conditionals'

Expand Down

0 comments on commit 7dfc52f

Please sign in to comment.