import { useCallback, useEffect, useRef, useState } from 'react' import { getPlatform } from '../../core/platform' import '../../styles/DevToolsBuffer.css' interface DevToolsBufferProps { isActive: boolean } const _w = window as any if (!_w.__moaDevtoolsView) { _w.__moaDevtoolsView = null } function DevToolsUnavailable() { const platform = getPlatform() const message = platform.type === 'capacitor' ? 'DevTools is not available on mobile.' : 'DevTools requires desktop mode (Electron).' return (
{message} Use your browser's built-in developer tools instead.
) } export default function DevToolsBuffer({ isActive }: DevToolsBufferProps) { const platform = getPlatform() if (platform.type !== 'electron') { return } return } function ElectronDevToolsBuffer({ isActive }: { isActive: boolean }) { const containerRef = useRef(null) const viewRef = useRef(null) const [webContentsId, setWebContentsId] = useState(null) const [embedded, setEmbedded] = useState(false) const ipcRenderer = (window as any).require('electron').ipcRenderer useEffect(() => { const container = containerRef.current if (!container) return let view = _w.__moaDevtoolsView as any if (!view) { view = document.createElement('webview') as any view.src = 'about:blank' view.style.flex = '1' view.style.width = '100%' view.style.height = '100%' view.style.background = 'var(--bg-primary)' _w.__moaDevtoolsView = view } container.appendChild(view) viewRef.current = view return () => { if (view.parentNode === container) { container.removeChild(view) } } }, []) useEffect(() => { const view = viewRef.current if (!view) return const setReady = () => { try { const id = view.getWebContentsId?.() if (typeof id === 'number' && id > 0) { setWebContentsId(id) } } catch { // Not ready yet } } setReady() view.addEventListener('dom-ready', setReady) return () => { view.removeEventListener('dom-ready', setReady) } }, []) useEffect(() => { let active = true ipcRenderer.invoke('devtools:is-embedded').then((isEmbedded: boolean) => { if (active) { setEmbedded(!!isEmbedded) } }).catch(() => { if (active) { setEmbedded(false) } }) return () => { active = false } }, [ipcRenderer]) useEffect(() => { if (!isActive || embedded || !webContentsId) return let cancelled = false ipcRenderer.invoke('devtools:embed', webContentsId).then((ok: boolean) => { if (!cancelled) { setEmbedded(!!ok) } }).catch(() => { if (!cancelled) { setEmbedded(false) } }) return () => { cancelled = true } }, [isActive, embedded, webContentsId, ipcRenderer]) const closeDevTools = useCallback(async () => { await ipcRenderer.invoke('devtools:close-embedded') setEmbedded(false) }, [ipcRenderer]) return (
Inspecting: MOA renderer
{!embedded && (
DevTools are inactive. Use the toolbar button or Cmd+Opt+I / Ctrl+Shift+I.
)}
) }