Fix: thumbnail.png would not be created in a few scenarios, the commandType wasn't populated in some workflows. (#6744)
* fix: moving screenshot logic to after KCL runtime. More robust * fix: removing toast debugging * fix: cleaning up the old logic
This commit is contained in:
30
src/App.tsx
30
src/App.tsx
@ -6,12 +6,10 @@ import {
|
|||||||
useLoaderData,
|
useLoaderData,
|
||||||
useLocation,
|
useLocation,
|
||||||
useNavigate,
|
useNavigate,
|
||||||
useRouteLoaderData,
|
|
||||||
useSearchParams,
|
useSearchParams,
|
||||||
} from 'react-router-dom'
|
} from 'react-router-dom'
|
||||||
|
|
||||||
import { AppHeader } from '@src/components/AppHeader'
|
import { AppHeader } from '@src/components/AppHeader'
|
||||||
import { useEngineCommands } from '@src/components/EngineCommands'
|
|
||||||
import { EngineStream } from '@src/components/EngineStream'
|
import { EngineStream } from '@src/components/EngineStream'
|
||||||
import Gizmo from '@src/components/Gizmo'
|
import Gizmo from '@src/components/Gizmo'
|
||||||
import { LowerRightControls } from '@src/components/LowerRightControls'
|
import { LowerRightControls } from '@src/components/LowerRightControls'
|
||||||
@ -22,11 +20,9 @@ import { useAbsoluteFilePath } from '@src/hooks/useAbsoluteFilePath'
|
|||||||
import { useCreateFileLinkQuery } from '@src/hooks/useCreateFileLinkQueryWatcher'
|
import { useCreateFileLinkQuery } from '@src/hooks/useCreateFileLinkQueryWatcher'
|
||||||
import { useEngineConnectionSubscriptions } from '@src/hooks/useEngineConnectionSubscriptions'
|
import { useEngineConnectionSubscriptions } from '@src/hooks/useEngineConnectionSubscriptions'
|
||||||
import { useHotKeyListener } from '@src/hooks/useHotKeyListener'
|
import { useHotKeyListener } from '@src/hooks/useHotKeyListener'
|
||||||
import { writeProjectThumbnailFile } from '@src/lib/desktop'
|
|
||||||
import useHotkeyWrapper from '@src/lib/hotkeyWrapper'
|
import useHotkeyWrapper from '@src/lib/hotkeyWrapper'
|
||||||
import { isDesktop } from '@src/lib/isDesktop'
|
import { isDesktop } from '@src/lib/isDesktop'
|
||||||
import { PATHS } from '@src/lib/paths'
|
import { PATHS } from '@src/lib/paths'
|
||||||
import { takeScreenshotOfVideoStreamCanvas } from '@src/lib/screenshot'
|
|
||||||
import {
|
import {
|
||||||
billingActor,
|
billingActor,
|
||||||
sceneInfra,
|
sceneInfra,
|
||||||
@ -85,10 +81,6 @@ export function App() {
|
|||||||
const projectName = project?.name || null
|
const projectName = project?.name || null
|
||||||
const projectPath = project?.path || null
|
const projectPath = project?.path || null
|
||||||
|
|
||||||
const [commands] = useEngineCommands()
|
|
||||||
const loaderData = useRouteLoaderData(PATHS.FILE) as IndexLoaderData
|
|
||||||
const lastCommandType = commands[commands.length - 1]?.type
|
|
||||||
|
|
||||||
// Run LSP file open hook when navigating between projects or files
|
// Run LSP file open hook when navigating between projects or files
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
onProjectOpen({ name: projectName, path: projectPath }, file || null)
|
onProjectOpen({ name: projectName, path: projectPath }, file || null)
|
||||||
@ -127,28 +119,6 @@ export function App() {
|
|||||||
|
|
||||||
useEngineConnectionSubscriptions()
|
useEngineConnectionSubscriptions()
|
||||||
|
|
||||||
// Generate thumbnail.png when loading the app
|
|
||||||
useEffect(() => {
|
|
||||||
if (isDesktop() && lastCommandType === 'execution-done') {
|
|
||||||
setTimeout(() => {
|
|
||||||
const projectDirectoryWithoutEndingSlash = loaderData?.project?.path
|
|
||||||
if (!projectDirectoryWithoutEndingSlash) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const dataUrl: string = takeScreenshotOfVideoStreamCanvas()
|
|
||||||
// zoom to fit command does not wait, wait 500ms to see if zoom to fit finishes
|
|
||||||
writeProjectThumbnailFile(dataUrl, projectDirectoryWithoutEndingSlash)
|
|
||||||
.then(() => {})
|
|
||||||
.catch((e) => {
|
|
||||||
console.error(
|
|
||||||
`Failed to generate thumbnail for ${projectDirectoryWithoutEndingSlash}`
|
|
||||||
)
|
|
||||||
console.error(e)
|
|
||||||
})
|
|
||||||
}, 500)
|
|
||||||
}
|
|
||||||
}, [lastCommandType, loaderData?.project?.path])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Not too useful for regular flows but on modeling view refresh,
|
// Not too useful for regular flows but on modeling view refresh,
|
||||||
// fetch the token count. The regular flow is the count is initialized
|
// fetch the token count. The regular flow is the count is initialized
|
||||||
|
@ -36,6 +36,7 @@ import {
|
|||||||
engineViewIsometricWithoutGeometryPresent,
|
engineViewIsometricWithoutGeometryPresent,
|
||||||
} from '@src/lib/utils'
|
} from '@src/lib/utils'
|
||||||
import { DEFAULT_DEFAULT_LENGTH_UNIT } from '@src/lib/constants'
|
import { DEFAULT_DEFAULT_LENGTH_UNIT } from '@src/lib/constants'
|
||||||
|
import { createThumbnailPNGOnDesktop } from '@src/lib/screenshot'
|
||||||
|
|
||||||
export const EngineStream = (props: {
|
export const EngineStream = (props: {
|
||||||
pool: string | null
|
pool: string | null
|
||||||
@ -49,7 +50,7 @@ export const EngineStream = (props: {
|
|||||||
|
|
||||||
const engineStreamState = useSelector(engineStreamActor, (state) => state)
|
const engineStreamState = useSelector(engineStreamActor, (state) => state)
|
||||||
|
|
||||||
const { file } = useRouteLoaderData(PATHS.FILE) as IndexLoaderData
|
const { file, project } = useRouteLoaderData(PATHS.FILE) as IndexLoaderData
|
||||||
const last = useRef<number>(Date.now())
|
const last = useRef<number>(Date.now())
|
||||||
const videoWrapperRef = useRef<HTMLDivElement>(null)
|
const videoWrapperRef = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
@ -122,6 +123,12 @@ export const EngineStream = (props: {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (project && project.path) {
|
||||||
|
createThumbnailPNGOnDesktop({
|
||||||
|
projectDirectoryWithoutEndingSlash: project.path,
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(trap)
|
.catch(trap)
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
import { isDesktop } from '@src/lib/isDesktop'
|
||||||
|
import { writeProjectThumbnailFile } from '@src/lib/desktop'
|
||||||
|
|
||||||
export function takeScreenshotOfVideoStreamCanvas() {
|
export function takeScreenshotOfVideoStreamCanvas() {
|
||||||
const canvas = document.querySelector('[data-engine]')
|
const canvas = document.querySelector('[data-engine]')
|
||||||
const video = document.getElementById('video-stream')
|
const video = document.getElementById('video-stream')
|
||||||
@ -41,3 +44,27 @@ export default async function screenshot(): Promise<string> {
|
|||||||
|
|
||||||
return takeScreenshotOfVideoStreamCanvas()
|
return takeScreenshotOfVideoStreamCanvas()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createThumbnailPNGOnDesktop({
|
||||||
|
projectDirectoryWithoutEndingSlash,
|
||||||
|
}: {
|
||||||
|
projectDirectoryWithoutEndingSlash: string
|
||||||
|
}) {
|
||||||
|
if (isDesktop()) {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!projectDirectoryWithoutEndingSlash) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const dataUrl: string = takeScreenshotOfVideoStreamCanvas()
|
||||||
|
// zoom to fit command does not wait, wait 500ms to see if zoom to fit finishes
|
||||||
|
writeProjectThumbnailFile(dataUrl, projectDirectoryWithoutEndingSlash)
|
||||||
|
.then(() => {})
|
||||||
|
.catch((e) => {
|
||||||
|
console.error(
|
||||||
|
`Failed to generate thumbnail for ${projectDirectoryWithoutEndingSlash}`
|
||||||
|
)
|
||||||
|
console.error(e)
|
||||||
|
})
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user