Skip to content

Commit

Permalink
Merge branch 'master' into feature/github-fork-url
Browse files Browse the repository at this point in the history
  • Loading branch information
balazsbajorics committed Jan 10, 2024
2 parents 6b39827 + 7055b9f commit 8330cad
Show file tree
Hide file tree
Showing 16 changed files with 257 additions and 67 deletions.
15 changes: 10 additions & 5 deletions editor/src/components/canvas/controls/canvas-offset-wrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ export function useApplyCanvasOffsetToStyle(setScaleToo: boolean): React.RefObje
const elementRef = React.useRef<HTMLDivElement>(null)
const canvasOffsetRef = useRefEditorState((store) => store.editor.canvas.roundedCanvasOffset)
const scaleRef = useRefEditorState((store) => store.editor.canvas.scale)
const isScrollAnimationActiveRef = useRefEditorState(
(store) => store.editor.canvas.scrollAnimation,
)

const mode = useEditorState(
Substores.restOfEditor,
Expand All @@ -45,13 +48,15 @@ export function useApplyCanvasOffsetToStyle(setScaleToo: boolean): React.RefObje
setScaleToo && scaleRef.current >= 1 ? `${scaleRef.current * 100}%` : '1',
)

elementRef.current.style.setProperty(
'transition',
isFollowMode(mode) ? `transform ${liveblocksThrottle}ms linear` : 'none',
)
if (!isScrollAnimationActiveRef.current) {
elementRef.current.style.setProperty(
'transition',
isFollowMode(mode) ? `transform ${liveblocksThrottle}ms linear` : 'none',
)
}
}
},
[elementRef, setScaleToo, scaleRef, mode],
[setScaleToo, scaleRef, isScrollAnimationActiveRef, mode],
)

useSelectorWithCallback(
Expand Down
36 changes: 15 additions & 21 deletions editor/src/components/canvas/controls/comment-indicator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { setRightMenuTab } from '../../editor/actions/action-creators'
import { RightMenuTab } from '../../editor/store/editor-state'
import { when } from '../../../utils/react-conditionals'
import { CommentRepliesCounter } from './comment-replies-counter'
import { useMyUserId } from '../../../core/shared/multiplayer-hooks'

const IndicatorSize = 24
const MagnifyScale = 1.15
Expand Down Expand Up @@ -113,20 +114,10 @@ function useCommentBeingComposed(): TemporaryCommentIndicatorProps | null {

const collabs = useStorage((storage) => storage.collaborators)

const userId = useEditorState(
Substores.userState,
(store) => {
if (store.userState.loginState.type !== 'LOGGED_IN') {
return null
}

return store.userState.loginState.user.userId
},
'CommentThread userId',
)
const myUserId = useMyUserId()

const collaboratorInfo = React.useMemo(() => {
const collaborator = optionalMap((id) => collabs[id], userId)
const collaborator = optionalMap((id) => collabs[id], myUserId)
if (collaborator == null) {
return {
initials: 'AN',
Expand All @@ -140,7 +131,7 @@ function useCommentBeingComposed(): TemporaryCommentIndicatorProps | null {
color: multiplayerColorFromIndex(collaborator.colorIndex),
avatar: collaborator.avatar,
}
}, [collabs, userId])
}, [collabs, myUserId])

if (position == null) {
return null
Expand Down Expand Up @@ -194,6 +185,12 @@ interface CommentIndicatorUIProps {
export const CommentIndicatorUI = React.memo<CommentIndicatorUIProps>((props) => {
const { position, bgColor, fgColor, avatarUrl, avatarInitials, resolved, isActive, read } = props

const canvasScale = useEditorState(
Substores.canvas,
(store) => store.editor.canvas.scale,
'CommentIndicatorUI scale',
)

function getIndicatorStyle() {
const base: Interpolation<Theme> = {
position: 'fixed',
Expand All @@ -207,7 +204,9 @@ export const CommentIndicatorUI = React.memo<CommentIndicatorUIProps>((props) =>
alignItems: 'center',
justifyContent: 'center',
boxShadow: UtopiaStyles.shadowStyles.mid.boxShadow,
border: '.4px solid #a3a3a340',
opacity: resolved ? 0.6 : 'undefined',
zoom: 1 / canvasScale,
}

const transform: Interpolation<Theme> = {
Expand Down Expand Up @@ -274,14 +273,7 @@ const CommentIndicator = React.memo(({ thread }: CommentIndicatorProps) => {
'CommentIndicator canvasOffset',
)

const { location, scene: commentScene } = useCanvasLocationOfThread(thread)

const remixLocationRoute = thread.metadata.remixLocationRoute ?? null

const remixState = useRemixNavigationContext(commentScene)

const isOnAnotherRoute =
remixLocationRoute != null && remixLocationRoute !== remixState?.location.pathname
const { location } = useCanvasLocationOfThread(thread)

const readByMe = useMyThreadReadStatus(thread)

Expand Down Expand Up @@ -445,12 +437,14 @@ const HoveredCommentIndicator = React.memo((props: HoveredCommentIndicatorProps)
width: 250,
boxShadow: UtopiaStyles.shadowStyles.mid.boxShadow,
background: colorTheme.bg1.value,
border: '.4px solid #a3a3a340',
zIndex: 1,
position: 'fixed',
bottom: canvasHeight - IndicatorSize - position.y,
// temporarily moving the hovered comment indicator to align with the not hovered version
left: position.x - 3,
overflow: 'hidden',
zoom: 1 / canvasScale,
}}
onMouseDown={onMouseDown}
onClick={onClick}
Expand Down
32 changes: 31 additions & 1 deletion editor/src/components/canvas/controls/comment-popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ const CommentThread = React.memo(({ comment }: CommentThreadProps) => {

const readByMe = useMyThreadReadStatus(thread)

useScrollWhenOverflowing(listRef)

const commentsCount = React.useMemo(
() => thread?.comments.filter((c) => c.deletedAt == null).length ?? 0,
[thread],
Expand Down Expand Up @@ -280,8 +282,8 @@ const CommentThread = React.memo(({ comment }: CommentThreadProps) => {
}
const tolerance = 20 // px

const isOverflowing = isOverflowingElement(element)
const atBottom = element.scrollHeight - element.scrollTop <= PopupMaxHeight + tolerance
const isOverflowing = element.scrollHeight > PopupMaxHeight
setShowShadowBottom(!atBottom && isOverflowing)

const atTop = element.scrollTop > tolerance
Expand Down Expand Up @@ -315,6 +317,7 @@ const CommentThread = React.memo(({ comment }: CommentThreadProps) => {
background: colorTheme.bg0.value,
borderRadius: 4,
overflow: 'hidden',
zoom: 1 / canvasScale,
}}
onKeyDown={stopPropagation}
onKeyUp={stopPropagation}
Expand Down Expand Up @@ -570,3 +573,30 @@ const HeaderComment = React.memo(
},
)
HeaderComment.displayName = 'HeaderComment'

function isOverflowingElement(element: HTMLDivElement | null): boolean {
if (element == null) {
return false
}
return element.scrollHeight > PopupMaxHeight
}

function useScrollWhenOverflowing(listRef: React.MutableRefObject<HTMLDivElement | null>) {
const stopWheelPropagation = React.useCallback(
(event: any) => {
if (isOverflowingElement(listRef.current)) {
event.stopPropagation()
}
},
[listRef],
)

React.useEffect(() => {
const element = listRef.current
if (element == null) {
return
}
element.addEventListener('wheel', stopWheelPropagation)
return () => element.removeEventListener('wheel', stopWheelPropagation)
}, [listRef, stopWheelPropagation])
}
11 changes: 11 additions & 0 deletions editor/src/components/canvas/controls/new-canvas-controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ import {
import { useSelectionArea } from './selection-area-hooks'
import { RemixSceneLabelControl } from './select-mode/remix-scene-label'
import { NO_OP } from '../../../core/shared/utils'
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 @@ -375,6 +378,8 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => {
[editorMode, selectModeHooks],
)

const roomStatus = useStatus()

const getResizeStatus = () => {
const selectedViews = localSelectedViews
if (textEditor != null || keysPressed['z']) {
Expand Down Expand Up @@ -562,6 +567,12 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => {
)}
{when(isSelectMode(editorMode), <DistanceGuidelineControl />)}
<GuidelineControls />
{when(
roomStatus === 'connected',
<MultiplayerWrapper errorFallback={null} suspenseFallback={null}>
<MultiplayerPresence />
</MultiplayerWrapper>,
)}
</>,
)}
</div>
Expand Down
6 changes: 0 additions & 6 deletions editor/src/components/canvas/design-panel-root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,6 @@ const DesignPanelRootInner = React.memo(() => {
}}
>
<CanvasWrapperComponent />
{when(
roomStatus === 'connected',
<MultiplayerWrapper errorFallback={null} suspenseFallback={null}>
<MultiplayerPresence />
</MultiplayerWrapper>,
)}
<GridPanelsContainer />
</SimpleFlexColumn>
}
Expand Down
25 changes: 21 additions & 4 deletions editor/src/components/canvas/multiplayer-presence.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,9 @@ import CanvasActions from './canvas-actions'
import { activeFrameActionToString } from './commands/set-active-frames-command'
import { canvasPointToWindowPoint, windowToCanvasCoordinates } from './dom-lookup'
import { ActiveRemixSceneAtom, RemixNavigationAtom } from './remix/utopia-remix-root-component'
import { useRemixPresence } from '../../core/shared/multiplayer-hooks'
import { useMyUserId, useRemixPresence } from '../../core/shared/multiplayer-hooks'
import { CanvasOffsetWrapper } from './controls/canvas-offset-wrapper'
import { when } from '../../utils/react-conditionals'
import { isFeatureEnabled } from '../../utils/feature-switches'
import { CommentIndicators } from './controls/comment-indicator'
import { CommentPopup } from './controls/comment-popup'

Expand Down Expand Up @@ -160,13 +159,20 @@ const MultiplayerCursors = React.memo(() => {
})
const myRemixPresence = me.presence.remix ?? null

const canvasScale = useEditorState(
Substores.canvas,
(store) => store.editor.canvas.scale,
'MultiplayerCursors canvasScale',
)

return (
<div
style={{
position: 'fixed',
top: 0,
left: 0,
pointerEvents: 'none',
zoom: 1 / canvasScale,
}}
>
{others.map((other) => {
Expand Down Expand Up @@ -240,6 +246,7 @@ const MultiplayerCursor = React.memo(
style={{
filter: 'drop-shadow(1px 2px 3px rgb(0 0 0 / 0.3))',
transform: 'translate(0px, 0px)',
zoom: canvasScale > 1 ? 1 / canvasScale : 1,
}}
>
<OtherUserPointer color={color.background} />
Expand All @@ -257,6 +264,10 @@ const MultiplayerCursor = React.memo(
left: 6,
top: 15,
zoom: canvasScale > 1 ? 1 / canvasScale : 1,
minHeight: 16,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
{name}
Expand Down Expand Up @@ -389,6 +400,7 @@ const FollowingOverlay = React.memo(() => {
justifyContent: 'center',
paddingBottom: 14,
cursor: 'default',
zoom: 1 / canvasScale,
}}
>
<div
Expand All @@ -408,12 +420,15 @@ const FollowingOverlay = React.memo(() => {
FollowingOverlay.displayName = 'FollowingOverlay'

const MultiplayerShadows = React.memo(() => {
const me = useSelf()
const myUserId = useMyUserId()
const updateMyPresence = useUpdateMyPresence()

const collabs = useStorage((store) => store.collaborators)
const others = useOthers((list) => {
const presences = normalizeOthersList(me.id, list)
if (myUserId == null) {
return []
}
const presences = normalizeOthersList(myUserId, list)
return presences.map((p) => ({
presenceInfo: p,
userInfo: collabs[p.id],
Expand Down Expand Up @@ -501,6 +516,7 @@ const MultiplayerShadows = React.memo(() => {
pointerEvents: 'none',
border: `1px dashed ${color.background}`,
opacity: 0.5,
zoom: 1 / canvasScale,
}}
/>
<motion.div
Expand Down Expand Up @@ -532,6 +548,7 @@ const MultiplayerShadows = React.memo(() => {
fontSize: 9,
color: color.background,
border: `1px dashed ${color.background}`,
zoom: 1 / canvasScale,
}}
>
{activeFrameActionToString(action)}
Expand Down
Loading

0 comments on commit 8330cad

Please sign in to comment.