fix core dump screenshot (#2911)

* fix core dump screenshot

* make it robust
This commit is contained in:
Kurt Hutten
2024-07-04 15:58:29 +10:00
committed by GitHub
parent 6370d45f94
commit 0dfee64e3b
7 changed files with 18 additions and 44 deletions

View File

@ -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),
[] []
) )

View File

@ -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,
}} }}

View File

@ -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 + .'], () => {

View File

@ -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),
[] []
) )

View File

@ -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}`) )
})
} }
} }

View File

@ -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()
}) })

View File

@ -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: {