From a7bf239913b28717aa550e1597a8b38ea27453cf Mon Sep 17 00:00:00 2001 From: Jhen Date: Sun, 20 Aug 2023 15:16:47 +0800 Subject: [PATCH] Inject custom devtools scripts --- app/containers/App.js | 65 ++++++++++++++++++++++++++++------ app/legacy/containers/App.js | 2 +- app/utils/devtools.js | 67 ++++++++++++++++++++++++++++++++++- electron/devtools.js | 68 ------------------------------------ electron/window.js | 3 +- 5 files changed, 123 insertions(+), 82 deletions(-) delete mode 100644 electron/devtools.js diff --git a/app/containers/App.js b/app/containers/App.js index a0a208d3..234012b9 100644 --- a/app/containers/App.js +++ b/app/containers/App.js @@ -1,6 +1,10 @@ import React, { useEffect, useState, useRef } from 'react' import qs from 'querystring' import styled from 'styled-components' +import { + catchConsoleLogLink, + removeUnecessaryTabs, +} from '../utils/devtools' const devtoolsHash = 'd9568d04d7dd79269c5a655d7ada69650c5a8336' // Chrome 100 @@ -42,24 +46,65 @@ export default function App() { useEffect(() => { const interval = setInterval(() => { - fetchInspectorInfo().then((info) => { - if ( - !info || - info.webSocketDebuggerUrl !== inspectorInfo.current?.webSocketDebuggerUrl - ) { - inspectorInfo.current = info - setUpdate((prev) => prev + 1) - } - }).catch(noop) + fetchInspectorInfo() + .then((info) => { + if ( + !info || + info.webSocketDebuggerUrl !== + inspectorInfo.current?.webSocketDebuggerUrl + ) { + inspectorInfo.current = info + setUpdate((prev) => prev + 1) + } + }) + .catch(noop) }, 5e3) return () => clearInterval(interval) }, []) console.log(inspectorInfo) + const webview = useRef(null) + if (!inspectorInfo.current) return null return ( - + { + webview.current = ref + if (ref) { + ref.addEventListener('dom-ready', () => { + const view = webview.current + const devtools = { devToolsWebContents: view } + + let interval + const waitReady = () => { + const requestId = view.findInPage('Console') + + const listener = (e) => { + if (e.result.matches > 0 && e.result.requestId === requestId) { + view.stopFindInPage('keepSelection') + + catchConsoleLogLink(devtools, 'localhost', 8081) // TODO + // TODO: if (config.showAllDevToolsTab !== true) + removeUnecessaryTabs(devtools) + + clearInterval(interval) + view.removeEventListener('found-in-page', listener) + } + } + + view.addEventListener('found-in-page', listener) + } + + interval = setInterval(waitReady, 500) + waitReady() + }) + } + }} + style={{ minHeight: 500, width: '100%' }} + autosize="on" + src={inspectorInfo.current?.devtoolsURL} + /> ) } diff --git a/app/legacy/containers/App.js b/app/legacy/containers/App.js index e95df4d2..897dd755 100644 --- a/app/legacy/containers/App.js +++ b/app/legacy/containers/App.js @@ -10,7 +10,7 @@ import ReduxDevTools from './redux/DevTools' import ReactInspector from './ReactInspector' import FormInput from '../../components/FormInput' import Draggable from '../../components/Draggable' -import { catchConsoleLogLink } from '../../../electron/devtools' +import { catchConsoleLogLink } from '../../utils/devtools' const currentWindow = getCurrentWindow() diff --git a/app/utils/devtools.js b/app/utils/devtools.js index 84d0e264..4f2e7b34 100644 --- a/app/utils/devtools.js +++ b/app/utils/devtools.js @@ -1,4 +1,32 @@ -import { getCatchConsoleLogScript } from '../../electron/devtools' +export const getCatchConsoleLogScript = (port) => ` + window.__RN_PACKAGER_MATCHER__ = /^http:\\/\\/[^:]+:${port}/; + if (!window.__INJECT_OPEN_IN_EDITOR_SCRIPT__) { + const rndHelperQuery = 'iframe[data-devtools-extension="RNDebugger devtools helper"]'; + document.addEventListener('click', event => { + if (!window.__IS_OPEN_IN_EDITOR_ENABLED__) { + return; + } + const { target } = event; + if (target.className === 'devtools-link') { + const source = target.title; + if (source && source.match(window.__RN_PACKAGER_MATCHER__)) { + const rndHelper = document.querySelector(rndHelperQuery); + if (rndHelper && rndHelper.contentWindow) { + rndHelper.contentWindow.postMessage( + { + type: 'open-in-editor', + source: source.replace(window.__RN_PACKAGER_MATCHER__, '') + }, + '*' + ); + return event.stopPropagation(); + } + } + } + }, true); + window.__INJECT_OPEN_IN_EDITOR_SCRIPT__ = true; + } +` let enabled = false export const toggleOpenInEditor = (win, port) => { @@ -40,3 +68,40 @@ export const selectRNDebuggerWorkerContext = (win) => { }, 100)`) } } + +export const catchConsoleLogLink = (win, host = 'localhost', port = 8081) => { + if (win.devToolsWebContents) { + return win.devToolsWebContents.executeJavaScript(`(() => { + ${getCatchConsoleLogScript(host, port)} + })()`) + } +} + +export const removeUnecessaryTabs = (win) => { + if (win.devToolsWebContents + ) { + return win.devToolsWebContents.executeJavaScript(`(() => { + const tabbedPane = UI.inspectorView.tabbedPane; + if (tabbedPane) { + tabbedPane.closeTab('elements'); + tabbedPane.closeTab('security'); + tabbedPane.closeTab('audits'); + tabbedPane.closeTab('audits2'); + tabbedPane.closeTab('lighthouse'); + + tabbedPane.leftToolbar().element.remove(); + } + })()`).then(resExec=> console.log(resExec)) + .catch(errExec=> console.log('ERROR', errExec)); + } +} + +export const activeTabs = (win) => { + if (win.devToolsWebContents) { + // Active network tab so we can do clearNetworkLogs + return win.devToolsWebContents.executeJavaScript(`(() => { + DevToolsAPI.showPanel('network'); + DevToolsAPI.showPanel('console'); + })()`) + } +} \ No newline at end of file diff --git a/electron/devtools.js b/electron/devtools.js deleted file mode 100644 index 386cd126..00000000 --- a/electron/devtools.js +++ /dev/null @@ -1,68 +0,0 @@ -export const getCatchConsoleLogScript = (port) => ` - window.__RN_PACKAGER_MATCHER__ = /^http:\\/\\/[^:]+:${port}/; - if (!window.__INJECT_OPEN_IN_EDITOR_SCRIPT__) { - const rndHelperQuery = 'iframe[data-devtools-extension="RNDebugger devtools helper"]'; - document.addEventListener('click', event => { - if (!window.__IS_OPEN_IN_EDITOR_ENABLED__) { - return; - } - const { target } = event; - if (target.className === 'devtools-link') { - const source = target.title; - if (source && source.match(window.__RN_PACKAGER_MATCHER__)) { - const rndHelper = document.querySelector(rndHelperQuery); - if (rndHelper && rndHelper.contentWindow) { - rndHelper.contentWindow.postMessage( - { - type: 'open-in-editor', - source: source.replace(window.__RN_PACKAGER_MATCHER__, '') - }, - '*' - ); - return event.stopPropagation(); - } - } - } - }, true); - window.__INJECT_OPEN_IN_EDITOR_SCRIPT__ = true; - } -` - -export const catchConsoleLogLink = (win, host = 'localhost', port = 8081) => { - if (win.devToolsWebContents) { - return win.devToolsWebContents.executeJavaScript(`(() => { - ${getCatchConsoleLogScript(host, port)} - })()`) - } -} - -export const removeUnecessaryTabs = (win) => { - if ( - process.env.NODE_ENV === 'production' - && !process.env.DEBUG_RNDEBUGGER - && win.devToolsWebContents - ) { - return win.devToolsWebContents.executeJavaScript(`(() => { - const tabbedPane = UI.inspectorView.tabbedPane; - if (tabbedPane) { - tabbedPane.closeTab('elements'); - tabbedPane.closeTab('security'); - tabbedPane.closeTab('audits'); - tabbedPane.closeTab('audits2'); - tabbedPane.closeTab('lighthouse'); - - tabbedPane.leftToolbar().element.remove(); - } - })()`) - } -} - -export const activeTabs = (win) => { - if (win.devToolsWebContents) { - // Active network tab so we can do clearNetworkLogs - return win.devToolsWebContents.executeJavaScript(`(() => { - DevToolsAPI.showPanel('network'); - DevToolsAPI.showPanel('console'); - })()`) - } -} diff --git a/electron/window.js b/electron/window.js index f1580e69..146db663 100644 --- a/electron/window.js +++ b/electron/window.js @@ -5,8 +5,7 @@ import { import Store from 'electron-store' import { enable } from '@electron/remote/main' import autoUpdate from './update' -import { catchConsoleLogLink, removeUnecessaryTabs, activeTabs } from './devtools' -import { selectRNDebuggerWorkerContext } from '../app/utils/devtools' +import { selectRNDebuggerWorkerContext, catchConsoleLogLink, removeUnecessaryTabs, activeTabs } from '../app/utils/devtools' import { readConfig, filePath as configFile } from './config' import { registerContextMenu } from './context-menu'