Implement "floating windows" style UI (#224)
* Basic transparent pane styling * HTML and static asset cleanup * Convert to collapsibles * Polish up DebugPanel * Add hotkey support, remove allotment * Remove allotment css dependency * Merge in from main * Add a different resizable package * Fix tsc errors introduced by merge * Stream has to have at least z-index of 0 * App header has to be above stream z-index * Applied z-index to the wrong element * Scrollable logs, disable UI while dragging * Fix test errors from importing CSS Modules in Jest * Persist open panes configuration * Style tweaks and fix camera step in onboarding * Kurt review, make click-drag handler declarative
This commit is contained in:
@ -1,16 +1,24 @@
|
||||
import { MouseEventHandler, useEffect, useRef } from 'react'
|
||||
import { PanelHeader } from '../components/PanelHeader'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { useStore } from '../useStore'
|
||||
import { throttle } from '../lib/utils'
|
||||
import { EngineCommand } from '../lang/std/engineConnection'
|
||||
|
||||
export const Stream = () => {
|
||||
export const Stream = ({ className = '' }) => {
|
||||
const videoRef = useRef<HTMLVideoElement>(null)
|
||||
const cmdId = useRef('')
|
||||
const { mediaStream, engineCommandManager } = useStore((s) => ({
|
||||
const {
|
||||
mediaStream,
|
||||
engineCommandManager,
|
||||
setIsMouseDownInStream,
|
||||
fileId,
|
||||
setFileId,
|
||||
setCmdId,
|
||||
} = useStore((s) => ({
|
||||
mediaStream: s.mediaStream,
|
||||
engineCommandManager: s.engineCommandManager,
|
||||
isMouseDownInStream: s.isMouseDownInStream,
|
||||
setIsMouseDownInStream: s.setIsMouseDownInStream,
|
||||
fileId: s.fileId,
|
||||
setFileId: s.setFileId,
|
||||
setCmdId: s.setCmdId,
|
||||
}))
|
||||
|
||||
useEffect(() => {
|
||||
@ -22,36 +30,8 @@ export const Stream = () => {
|
||||
if (!videoRef.current) return
|
||||
if (!mediaStream) return
|
||||
videoRef.current.srcObject = mediaStream
|
||||
}, [mediaStream, engineCommandManager])
|
||||
|
||||
const file_id = uuidv4()
|
||||
|
||||
const debounceSocketSend = throttle<EngineCommand>((message) => {
|
||||
engineCommandManager?.sendSceneCommand(message)
|
||||
}, 16)
|
||||
const handleMouseMove: MouseEventHandler<HTMLVideoElement> = ({
|
||||
clientX,
|
||||
clientY,
|
||||
ctrlKey,
|
||||
}) => {
|
||||
if (!videoRef.current) return
|
||||
if (!cmdId.current) return
|
||||
const { left, top } = videoRef.current.getBoundingClientRect()
|
||||
const x = clientX - left
|
||||
const y = clientY - top
|
||||
const interaction = ctrlKey ? 'pan' : 'rotate'
|
||||
|
||||
debounceSocketSend({
|
||||
type: 'modeling_cmd_req',
|
||||
cmd: {
|
||||
type: 'camera_drag_move',
|
||||
interaction,
|
||||
window: { x, y },
|
||||
},
|
||||
cmd_id: uuidv4(),
|
||||
file_id: file_id,
|
||||
})
|
||||
}
|
||||
setFileId(uuidv4())
|
||||
}, [mediaStream, engineCommandManager, setFileId])
|
||||
|
||||
const handleMouseDown: MouseEventHandler<HTMLVideoElement> = ({
|
||||
clientX,
|
||||
@ -65,7 +45,7 @@ export const Stream = () => {
|
||||
console.log('click', x, y)
|
||||
|
||||
const newId = uuidv4()
|
||||
cmdId.current = newId
|
||||
setCmdId(newId)
|
||||
|
||||
const interaction = ctrlKey ? 'pan' : 'rotate'
|
||||
|
||||
@ -77,9 +57,12 @@ export const Stream = () => {
|
||||
window: { x, y },
|
||||
},
|
||||
cmd_id: newId,
|
||||
file_id,
|
||||
file_id: fileId,
|
||||
})
|
||||
|
||||
setIsMouseDownInStream(true)
|
||||
}
|
||||
|
||||
const handleMouseUp: MouseEventHandler<HTMLVideoElement> = ({
|
||||
clientX,
|
||||
clientY,
|
||||
@ -90,9 +73,8 @@ export const Stream = () => {
|
||||
const x = clientX - left
|
||||
const y = clientY - top
|
||||
|
||||
if (cmdId.current == null) {
|
||||
return
|
||||
}
|
||||
const newCmdId = uuidv4()
|
||||
setCmdId(newCmdId)
|
||||
|
||||
const interaction = ctrlKey ? 'pan' : 'rotate'
|
||||
|
||||
@ -103,26 +85,27 @@ export const Stream = () => {
|
||||
interaction,
|
||||
window: { x, y },
|
||||
},
|
||||
cmd_id: uuidv4(),
|
||||
file_id: file_id,
|
||||
cmd_id: newCmdId,
|
||||
file_id: fileId,
|
||||
})
|
||||
cmdId.current = ''
|
||||
|
||||
setCmdId('')
|
||||
|
||||
setIsMouseDownInStream(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<div id="stream">
|
||||
<PanelHeader title="Stream" />
|
||||
<div id="stream" className={className}>
|
||||
<video
|
||||
ref={videoRef}
|
||||
muted
|
||||
autoPlay
|
||||
controls={false}
|
||||
onMouseMove={handleMouseMove}
|
||||
onMouseDown={handleMouseDown}
|
||||
onMouseUp={handleMouseUp}
|
||||
onMouseLeave={handleMouseUp}
|
||||
onContextMenu={(e) => e.preventDefault()}
|
||||
onContextMenuCapture={(e) => e.preventDefault()}
|
||||
className="w-full h-full"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
Reference in New Issue
Block a user