fix core dump screenshot (#2911)
* fix core dump screenshot * make it robust
This commit is contained in:
@ -25,7 +25,6 @@ import ModalContainer from 'react-modal-promise'
|
|||||||
import useHotkeyWrapper from 'lib/hotkeyWrapper'
|
import useHotkeyWrapper from 'lib/hotkeyWrapper'
|
||||||
import Gizmo from 'components/Gizmo'
|
import Gizmo from 'components/Gizmo'
|
||||||
import { CoreDumpManager } from 'lib/coredump'
|
import { CoreDumpManager } from 'lib/coredump'
|
||||||
import { useAppState } from 'AppState'
|
|
||||||
|
|
||||||
export function App() {
|
export function App() {
|
||||||
useRefreshSettings(paths.FILE + 'SETTINGS')
|
useRefreshSettings(paths.FILE + 'SETTINGS')
|
||||||
@ -45,17 +44,12 @@ export function App() {
|
|||||||
|
|
||||||
useHotKeyListener()
|
useHotKeyListener()
|
||||||
const { context } = useModelingContext()
|
const { context } = useModelingContext()
|
||||||
const { setAppState } = useAppState()
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setAppState({ htmlRef: ref })
|
|
||||||
}, [ref])
|
|
||||||
|
|
||||||
const { auth, settings } = useSettingsAuthContext()
|
const { auth, settings } = useSettingsAuthContext()
|
||||||
const token = auth?.context?.token
|
const token = auth?.context?.token
|
||||||
|
|
||||||
const coreDumpManager = useMemo(
|
const coreDumpManager = useMemo(
|
||||||
() => new CoreDumpManager(engineCommandManager, ref, token),
|
() => new CoreDumpManager(engineCommandManager, token),
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -10,12 +10,10 @@ Please do not fill this up with junk.
|
|||||||
|
|
||||||
interface AppState {
|
interface AppState {
|
||||||
isStreamReady: boolean
|
isStreamReady: boolean
|
||||||
htmlRef: React.RefObject<HTMLDivElement> | null
|
|
||||||
setAppState: (newAppState: Partial<AppState>) => void
|
setAppState: (newAppState: Partial<AppState>) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const AppStateContext = createContext<AppState>({
|
const AppStateContext = createContext<AppState>({
|
||||||
htmlRef: null,
|
|
||||||
isStreamReady: false,
|
isStreamReady: false,
|
||||||
setAppState: () => {},
|
setAppState: () => {},
|
||||||
})
|
})
|
||||||
@ -24,7 +22,6 @@ export const useAppState = () => useContext(AppStateContext)
|
|||||||
|
|
||||||
export const AppStateProvider = ({ children }: { children: ReactNode }) => {
|
export const AppStateProvider = ({ children }: { children: ReactNode }) => {
|
||||||
const [appState, _setAppState] = useState<AppState>({
|
const [appState, _setAppState] = useState<AppState>({
|
||||||
htmlRef: null,
|
|
||||||
isStreamReady: false,
|
isStreamReady: false,
|
||||||
setAppState: () => {},
|
setAppState: () => {},
|
||||||
})
|
})
|
||||||
@ -34,7 +31,6 @@ export const AppStateProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
return (
|
return (
|
||||||
<AppStateContext.Provider
|
<AppStateContext.Provider
|
||||||
value={{
|
value={{
|
||||||
htmlRef: appState.htmlRef,
|
|
||||||
isStreamReady: appState.isStreamReady,
|
isStreamReady: appState.isStreamReady,
|
||||||
setAppState,
|
setAppState,
|
||||||
}}
|
}}
|
||||||
|
@ -40,7 +40,7 @@ import useHotkeyWrapper from 'lib/hotkeyWrapper'
|
|||||||
import toast from 'react-hot-toast'
|
import toast from 'react-hot-toast'
|
||||||
import { coreDump } from 'lang/wasm'
|
import { coreDump } from 'lang/wasm'
|
||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { AppStateProvider, useAppState } from 'AppState'
|
import { AppStateProvider } from 'AppState'
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
@ -180,9 +180,8 @@ export const Router = () => {
|
|||||||
function CoreDump() {
|
function CoreDump() {
|
||||||
const { auth } = useSettingsAuthContext()
|
const { auth } = useSettingsAuthContext()
|
||||||
const token = auth?.context?.token
|
const token = auth?.context?.token
|
||||||
const { htmlRef } = useAppState()
|
|
||||||
const coreDumpManager = useMemo(
|
const coreDumpManager = useMemo(
|
||||||
() => new CoreDumpManager(engineCommandManager, htmlRef, token),
|
() => new CoreDumpManager(engineCommandManager, token),
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
useHotkeyWrapper(['meta + shift + .'], () => {
|
useHotkeyWrapper(['meta + shift + .'], () => {
|
||||||
|
@ -6,14 +6,12 @@ import React, { useMemo } from 'react'
|
|||||||
import toast from 'react-hot-toast'
|
import toast from 'react-hot-toast'
|
||||||
import Tooltip from './Tooltip'
|
import Tooltip from './Tooltip'
|
||||||
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
||||||
import { useAppState } from 'AppState'
|
|
||||||
|
|
||||||
export const RefreshButton = ({ children }: React.PropsWithChildren) => {
|
export const RefreshButton = ({ children }: React.PropsWithChildren) => {
|
||||||
const { auth } = useSettingsAuthContext()
|
const { auth } = useSettingsAuthContext()
|
||||||
const token = auth?.context?.token
|
const token = auth?.context?.token
|
||||||
const { htmlRef } = useAppState()
|
|
||||||
const coreDumpManager = useMemo(
|
const coreDumpManager = useMemo(
|
||||||
() => new CoreDumpManager(engineCommandManager, htmlRef, token),
|
() => new CoreDumpManager(engineCommandManager, token),
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ import {
|
|||||||
import { APP_VERSION } from 'routes/Settings'
|
import { APP_VERSION } from 'routes/Settings'
|
||||||
import { UAParser } from 'ua-parser-js'
|
import { UAParser } from 'ua-parser-js'
|
||||||
import screenshot from 'lib/screenshot'
|
import screenshot from 'lib/screenshot'
|
||||||
import React from 'react'
|
|
||||||
import { VITE_KC_API_BASE_URL } from 'env'
|
import { VITE_KC_API_BASE_URL } from 'env'
|
||||||
|
|
||||||
/* eslint-disable suggest-no-throw/suggest-no-throw --
|
/* eslint-disable suggest-no-throw/suggest-no-throw --
|
||||||
@ -33,17 +32,14 @@ import { VITE_KC_API_BASE_URL } from 'env'
|
|||||||
// TODO: Throw more
|
// TODO: Throw more
|
||||||
export class CoreDumpManager {
|
export class CoreDumpManager {
|
||||||
engineCommandManager: EngineCommandManager
|
engineCommandManager: EngineCommandManager
|
||||||
htmlRef: React.RefObject<HTMLDivElement> | null
|
|
||||||
token: string | undefined
|
token: string | undefined
|
||||||
baseUrl: string = VITE_KC_API_BASE_URL
|
baseUrl: string = VITE_KC_API_BASE_URL
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
engineCommandManager: EngineCommandManager,
|
engineCommandManager: EngineCommandManager,
|
||||||
htmlRef: React.RefObject<HTMLDivElement> | null,
|
|
||||||
token: string | undefined
|
token: string | undefined
|
||||||
) {
|
) {
|
||||||
this.engineCommandManager = engineCommandManager
|
this.engineCommandManager = engineCommandManager
|
||||||
this.htmlRef = htmlRef
|
|
||||||
this.token = token
|
this.token = token
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,12 +445,11 @@ export class CoreDumpManager {
|
|||||||
|
|
||||||
// Return a data URL (png format) of the screenshot of the current page.
|
// Return a data URL (png format) of the screenshot of the current page.
|
||||||
screenshot(): Promise<string> {
|
screenshot(): Promise<string> {
|
||||||
return screenshot(this.htmlRef)
|
return (
|
||||||
.then((screenshot: string) => {
|
screenshot()
|
||||||
return screenshot
|
.then((screenshotStr: string) => screenshotStr)
|
||||||
})
|
// maybe rust should handle an error, but an empty string at least doesn't cause the core dump to fail entirely
|
||||||
.catch((error: any) => {
|
.catch((error: any) => ``)
|
||||||
throw new Error(`Error getting screenshot: ${error}`)
|
)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,15 @@
|
|||||||
import React from 'react'
|
|
||||||
import html2canvas from 'html2canvas-pro'
|
import html2canvas from 'html2canvas-pro'
|
||||||
|
|
||||||
// Return a data URL (png format) of the screenshot of the current page.
|
// Return a data URL (png format) of the screenshot of the current page.
|
||||||
export default async function screenshot(
|
export default async function screenshot(): Promise<string> {
|
||||||
htmlRef: React.RefObject<HTMLDivElement> | null
|
if (typeof window === 'undefined') {
|
||||||
): Promise<string> {
|
return Promise.reject(
|
||||||
if (htmlRef === null) {
|
new Error(
|
||||||
return Promise.reject(new Error('htmlRef is null'))
|
"element isn't defined because there's no window, are you running in Node?"
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (htmlRef.current === null) {
|
return html2canvas(document.documentElement)
|
||||||
return Promise.reject(new Error('htmlRef is null'))
|
|
||||||
}
|
|
||||||
return html2canvas(htmlRef.current)
|
|
||||||
.then((canvas) => {
|
.then((canvas) => {
|
||||||
return canvas.toDataURL()
|
return canvas.toDataURL()
|
||||||
})
|
})
|
||||||
|
@ -39,7 +39,6 @@ import {
|
|||||||
listProjects,
|
listProjects,
|
||||||
renameProjectDirectory,
|
renameProjectDirectory,
|
||||||
} from 'lib/tauri'
|
} from 'lib/tauri'
|
||||||
import { useAppState } from 'AppState'
|
|
||||||
|
|
||||||
// This route only opens in the Tauri desktop context for now,
|
// This route only opens in the Tauri desktop context for now,
|
||||||
// as defined in Router.tsx, so we can use the Tauri APIs and types.
|
// as defined in Router.tsx, so we can use the Tauri APIs and types.
|
||||||
@ -66,11 +65,6 @@ const Home = () => {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
const ref = useRef<HTMLDivElement>(null)
|
const ref = useRef<HTMLDivElement>(null)
|
||||||
const { setAppState } = useAppState()
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setAppState({ htmlRef: ref })
|
|
||||||
}, [ref])
|
|
||||||
|
|
||||||
const [state, send, actor] = useMachine(homeMachine, {
|
const [state, send, actor] = useMachine(homeMachine, {
|
||||||
context: {
|
context: {
|
||||||
|
Reference in New Issue
Block a user