This commit is contained in:
lee-at-zoo-corp
2025-03-21 16:10:49 -04:00
parent 2cca1376e2
commit 4c9851efbf
7 changed files with 124 additions and 97 deletions

View File

@ -981,17 +981,21 @@ export class CameraControls {
}
async saveRemoteCameraState() {
const cameraViewStateResponse = await this.engineCommandManager.sendSceneCommand({
const cameraViewStateResponse =
await this.engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: { type: 'default_camera_get_view' },
})
if (!cameraViewStateResponse) return
if ('resp' in cameraViewStateResponse
&& 'modeling_response' in cameraViewStateResponse.resp.data
&& 'data' in cameraViewStateResponse.resp.data.modeling_response
&& 'view' in cameraViewStateResponse.resp.data.modeling_response.data) {
this.oldCameraState = cameraViewStateResponse.resp.data.modeling_response.data.view
if (
'resp' in cameraViewStateResponse &&
'modeling_response' in cameraViewStateResponse.resp.data &&
'data' in cameraViewStateResponse.resp.data.modeling_response &&
'view' in cameraViewStateResponse.resp.data.modeling_response.data
) {
this.oldCameraState =
cameraViewStateResponse.resp.data.modeling_response.data.view
}
}

View File

@ -3,11 +3,7 @@ import { useEngineCommands } from '@src/components/EngineCommands'
import { Spinner } from '@src/components/Spinner'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import {
faPlay,
faPause,
faSpinner,
} from '@fortawesome/free-solid-svg-icons'
import { faPlay, faPause, faSpinner } from '@fortawesome/free-solid-svg-icons'
export const ModelStateIndicator = () => {
const engineStreamState = useSelector(engineStreamActor, (state) => state)
@ -18,12 +14,14 @@ export const ModelStateIndicator = () => {
if (engineStreamState.value === EngineStreamState.Paused) {
className += 'text-secondary'
icon = <FontAwesomeIcon
icon = (
<FontAwesomeIcon
data-testid={dataTestId + '-paused'}
icon={faPause}
width="20"
height="20"
/>
)
} else if (engineStreamState.value === EngineStreamState.Playing) {
className += 'text-secondary'
icon = (
@ -36,12 +34,14 @@ export const ModelStateIndicator = () => {
)
} else {
className += 'text-secondary'
icon = <FontAwesomeIcon
icon = (
<FontAwesomeIcon
data-testid={dataTestId + '-resuming'}
icon={faSpinner}
width="20"
height="20"
/>
)
}
return (

View File

@ -86,7 +86,7 @@ export const NetworkHealthIndicator = () => {
error,
setHasCopied,
hasCopied,
ping
ping,
} = useNetworkContext()
return (
@ -130,10 +130,12 @@ export const NetworkHealthIndicator = () => {
{NETWORK_HEALTH_TEXT[overallState]}
</p>
</div>
<div
className={`flex items-center justify-between p-2 rounded-t-sm`}
<div className={`flex items-center justify-between p-2 rounded-t-sm`}>
<h2
className={`text-xs font-sans font-normal ${overallConnectionStateColor[overallState].icon}`}
>
<h2 className={`text-xs font-sans font-normal ${overallConnectionStateColor[overallState].icon}`}>Ping</h2>
Ping
</h2>
<p
data-testid="network"
className={`font-bold text-xs uppercase px-2 py-1 rounded-sm ${overallConnectionStateColor[overallState].icon}`}

View File

@ -71,7 +71,7 @@ export function useNetworkStatus() {
? NetworkHealthState.Disconnected
: hasIssues || hasIssues === undefined
? NetworkHealthState.Issue
: ping > (16.6*3) // we consider ping longer than 3 frames as weak
: ping > 16.6 * 3 // we consider ping longer than 3 frames as weak
? NetworkHealthState.Weak
: NetworkHealthState.Ok
)

View File

@ -332,15 +332,19 @@ class EngineConnection extends EventTarget {
this.pingIntervalId = setInterval(() => {
// Only start a new ping when the other is fulfilled.
if (this.pingPongSpan.ping) { return }
if (this.pingPongSpan.ping) {
return
}
// Don't start pinging until we're connected.
if (this.state.type !== EngineConnectionStateType.ConnectionEstablished) { return }
if (this.state.type !== EngineConnectionStateType.ConnectionEstablished) {
return
}
this.send({ type: 'ping' })
this.pingPongSpan = {
ping: new Date(),
pong: undefined
pong: undefined,
}
}, pingIntervalMs)
@ -1000,7 +1004,10 @@ class EngineConnection extends EventTarget {
this.pingPongSpan.pong = new Date()
this.dispatchEvent(
new CustomEvent(EngineConnectionEvents.PingPongChanged, {
detail: Math.min(999, Math.floor(this.pingPongSpan.pong - this.pingPongSpan.ping)),
detail: Math.min(
999,
Math.floor(this.pingPongSpan.pong - this.pingPongSpan.ping)
),
})
)
// Clear the initial ping so our interval ping loop can fire again

View File

@ -219,13 +219,23 @@ export function createSettings() {
(typeof v === 'number' &&
v >= 1 * MS_IN_MINUTE &&
v <= 60 * MS_IN_MINUTE),
Component: ({ value: settingValueInStorage, updateValue: writeSettingValueToStorage }) => {
Component: ({
value: settingValueInStorage,
updateValue: writeSettingValueToStorage,
}) => {
const [timeoutId, setTimeoutId] = useState(undefined)
const [preview, setPreview] = useState(settingValueInStorage === undefined ? settingValueInStorage : (settingValueInStorage / MS_IN_MINUTE))
const onChangeRange = (e: React.SyntheticEvent) => setPreview(e.currentTarget.value)
const [preview, setPreview] = useState(
settingValueInStorage === undefined
? settingValueInStorage
: settingValueInStorage / MS_IN_MINUTE
)
const onChangeRange = (e: React.SyntheticEvent) =>
setPreview(e.currentTarget.value)
const onSaveRange = (e: React.SyntheticEvent) => {
if (preview === undefined) return
writeSettingValueToStorage(Number(e.currentTarget.value) * MS_IN_MINUTE)
writeSettingValueToStorage(
Number(e.currentTarget.value) * MS_IN_MINUTE
)
}
return (
@ -235,17 +245,24 @@ export function createSettings() {
type="checkbox"
checked={settingValueInStorage !== undefined}
onChange={(event) => {
if (timeoutId) { return }
if (timeoutId) {
return
}
const isChecked = event.currentTarget.checked
clearTimeout(timeoutId)
setTimeoutId(setTimeout(() => {
setTimeoutId(
setTimeout(() => {
const requested = !isChecked ? undefined : 5
setPreview(requested)
writeSettingValueToStorage(requested === undefined ? undefined : Number(requested) * MS_IN_MINUTE)
writeSettingValueToStorage(
requested === undefined
? undefined
: Number(requested) * MS_IN_MINUTE
)
setTimeoutId(undefined)
}, 100))
}
}
}, 100)
)
}}
className="block w-4 h-4"
/>
<div></div>
@ -259,9 +276,7 @@ export function createSettings() {
onPointerUp={onSaveRange}
disabled={preview === undefined}
value={
preview !== null && preview !== undefined
? preview
: 5
preview !== null && preview !== undefined ? preview : 5
}
min={1}
max={60}
@ -279,7 +294,8 @@ export function createSettings() {
)}
</div>
</div>
)},
)
},
}),
allowOrbitInSketchMode: new Setting<boolean>({
defaultValue: false,

View File

@ -118,9 +118,7 @@ export const engineStreamMachine = setup({
// will not reexecute.
// When calling cache before _any_ executions it errors, but non-fatal.
await rustContext
.clearSceneAndBustCache(
{ settings: await jsAppSettings() },
)
.clearSceneAndBustCache({ settings: await jsAppSettings() })
.catch(console.warn)
await kclManager.executeCode(params.zoomToFit)