add display/hide collaborator cursors

This commit is contained in:
hjlarry 2025-09-23 17:32:23 +08:00
parent f49476a206
commit 05a67f4716
5 changed files with 41 additions and 3 deletions

View File

@ -0,0 +1,11 @@
import { create } from 'zustand'
type UserCursorsState = {
showUserCursors: boolean
toggleUserCursors: () => void
}
export const useUserCursorsState = create<UserCursorsState>(set => ({
showUserCursors: true,
toggleUserCursors: () => set(state => ({ showUserCursors: !state.showUserCursors })),
}))

View File

@ -13,6 +13,7 @@ import { WorkflowWithInnerContext } from '@/app/components/workflow'
import type { WorkflowProps } from '@/app/components/workflow' import type { WorkflowProps } from '@/app/components/workflow'
import WorkflowChildren from './workflow-children' import WorkflowChildren from './workflow-children'
import UserCursors from '@/app/components/workflow/collaboration/components/user-cursors' import UserCursors from '@/app/components/workflow/collaboration/components/user-cursors'
import { useUserCursorsState } from './user-cursors-state'
import { import {
useAvailableNodesMetaData, useAvailableNodesMetaData,
@ -46,8 +47,9 @@ const WorkflowMain = ({
const reactFlow = useReactFlow() const reactFlow = useReactFlow()
const store = useStoreApi() const store = useStoreApi()
const { startCursorTracking, stopCursorTracking, onlineUsers, cursors, isConnected } = useCollaboration(appId, store) const { startCursorTracking, stopCursorTracking, onlineUsers, cursors, isConnected } = useCollaboration(appId || '', store)
const [myUserId, setMyUserId] = useState<string | null>(null) const [myUserId, setMyUserId] = useState<string | null>(null)
const { showUserCursors } = useUserCursorsState()
useEffect(() => { useEffect(() => {
if (isConnected) if (isConnected)
@ -300,7 +302,7 @@ const WorkflowMain = ({
> >
<WorkflowChildren /> <WorkflowChildren />
</WorkflowWithInnerContext> </WorkflowWithInnerContext>
<UserCursors cursors={filteredCursors} myUserId={myUserId} onlineUsers={onlineUsers} /> <UserCursors cursors={showUserCursors ? filteredCursors : {}} myUserId={myUserId} onlineUsers={onlineUsers} />
</div> </div>
) )
} }

View File

@ -5,6 +5,7 @@ import ZoomInOut from './zoom-in-out'
import VariableTrigger from '../variable-inspect/trigger' import VariableTrigger from '../variable-inspect/trigger'
import VariableInspectPanel from '../variable-inspect' import VariableInspectPanel from '../variable-inspect'
import { useStore } from '../store' import { useStore } from '../store'
import { useUserCursorsState } from '@/app/components/workflow-app/components/user-cursors-state'
export type OperatorProps = { export type OperatorProps = {
handleUndo: () => void handleUndo: () => void
@ -14,6 +15,7 @@ export type OperatorProps = {
const Operator = ({ handleUndo, handleRedo }: OperatorProps) => { const Operator = ({ handleUndo, handleRedo }: OperatorProps) => {
const bottomPanelRef = useRef<HTMLDivElement>(null) const bottomPanelRef = useRef<HTMLDivElement>(null)
const [showMiniMap, setShowMiniMap] = useState(true) const [showMiniMap, setShowMiniMap] = useState(true)
const { showUserCursors, toggleUserCursors } = useUserCursorsState()
const handleToggleMiniMap = useCallback(() => { const handleToggleMiniMap = useCallback(() => {
setShowMiniMap(prev => !prev) setShowMiniMap(prev => !prev)
@ -79,6 +81,8 @@ const Operator = ({ handleUndo, handleRedo }: OperatorProps) => {
<ZoomInOut <ZoomInOut
showMiniMap={showMiniMap} showMiniMap={showMiniMap}
onToggleMiniMap={handleToggleMiniMap} onToggleMiniMap={handleToggleMiniMap}
showUserCursors={showUserCursors}
onToggleUserCursors={toggleUserCursors}
/> />
</div> </div>
</div> </div>

View File

@ -39,17 +39,22 @@ enum ZoomType {
zoomTo75 = 'zoomTo75', zoomTo75 = 'zoomTo75',
zoomTo100 = 'zoomTo100', zoomTo100 = 'zoomTo100',
zoomTo200 = 'zoomTo200', zoomTo200 = 'zoomTo200',
toggleUserCursors = 'toggleUserCursors',
toggleMiniMap = 'toggleMiniMap', toggleMiniMap = 'toggleMiniMap',
} }
type ZoomInOutProps = { type ZoomInOutProps = {
showMiniMap?: boolean showMiniMap?: boolean
onToggleMiniMap?: () => void onToggleMiniMap?: () => void
showUserCursors?: boolean
onToggleUserCursors?: () => void
} }
const ZoomInOut: FC<ZoomInOutProps> = ({ const ZoomInOut: FC<ZoomInOutProps> = ({
showMiniMap = true, showMiniMap = true,
onToggleMiniMap, onToggleMiniMap,
showUserCursors = true,
onToggleUserCursors,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const { const {
@ -94,6 +99,10 @@ const ZoomInOut: FC<ZoomInOutProps> = ({
}, },
], ],
[ [
{
key: ZoomType.toggleUserCursors,
text: t('workflow.operator.showUserCursors'),
},
{ {
key: ZoomType.toggleMiniMap, key: ZoomType.toggleMiniMap,
text: t('workflow.operator.showMiniMap'), text: t('workflow.operator.showMiniMap'),
@ -123,6 +132,11 @@ const ZoomInOut: FC<ZoomInOutProps> = ({
if (type === ZoomType.zoomTo200) if (type === ZoomType.zoomTo200)
zoomTo(2) zoomTo(2)
if (type === ZoomType.toggleUserCursors) {
onToggleUserCursors?.()
return
}
if (type === ZoomType.toggleMiniMap) { if (type === ZoomType.toggleMiniMap) {
onToggleMiniMap?.() onToggleMiniMap?.()
return return
@ -211,10 +225,16 @@ const ZoomInOut: FC<ZoomInOutProps> = ({
options.map(option => ( options.map(option => (
<div <div
key={option.key} key={option.key}
className='system-md-regular flex h-8 cursor-pointer items-center justify-between space-x-1 rounded-lg py-1.5 pl-3 pr-2 text-text-secondary hover:bg-state-base-hover' className='system-md-regular flex h-8 cursor-pointer items-center justify-between space-x-1 rounded-lg px-2 py-1.5 text-text-secondary hover:bg-state-base-hover'
onClick={() => handleZoom(option.key)} onClick={() => handleZoom(option.key)}
> >
<div className='flex items-center space-x-2'> <div className='flex items-center space-x-2'>
{option.key === ZoomType.toggleUserCursors && showUserCursors && (
<RiCheckLine className='h-4 w-4 text-text-primary' />
)}
{option.key === ZoomType.toggleUserCursors && !showUserCursors && (
<div className='h-4 w-4' />
)}
{option.key === ZoomType.toggleMiniMap && showMiniMap && ( {option.key === ZoomType.toggleMiniMap && showMiniMap && (
<RiCheckLine className='h-4 w-4 text-text-primary' /> <RiCheckLine className='h-4 w-4 text-text-primary' />
)} )}

View File

@ -326,6 +326,7 @@ const translation = {
zoomTo50: 'Zoom to 50%', zoomTo50: 'Zoom to 50%',
zoomTo100: 'Zoom to 100%', zoomTo100: 'Zoom to 100%',
zoomToFit: 'Zoom to Fit', zoomToFit: 'Zoom to Fit',
showUserCursors: 'Collaborator cursors',
showMiniMap: 'Minimap', showMiniMap: 'Minimap',
alignNodes: 'Align Nodes', alignNodes: 'Align Nodes',
alignLeft: 'Left', alignLeft: 'Left',