diff --git a/src/ui/actions/app.ts b/src/ui/actions/app.ts index 98038dde907..aa5eb5d2255 100644 --- a/src/ui/actions/app.ts +++ b/src/ui/actions/app.ts @@ -95,12 +95,6 @@ export function setupApp(recordingId: RecordingId, store: UIStore) { }); ThreadFront.listenForLoadChanges(); - - // ThreadFront.getAnnotations(({ annotations }) => { - // for (const { point, time, kind, contents } of annotations) { - // console.log("FoundAnnotation", point, time, kind, contents); - // } - // }); } function onUnprocessedRegions({ regions }: unprocessedRegions): UIThunkAction { diff --git a/src/ui/components/SecondaryToolbox/ReactDevTools.js b/src/ui/components/SecondaryToolbox/ReactDevTools.js new file mode 100644 index 00000000000..9b248e62b94 --- /dev/null +++ b/src/ui/components/SecondaryToolbox/ReactDevTools.js @@ -0,0 +1,97 @@ +import React from "react"; + +import { + createBridge, + createStore, + initialize as createDevTools, +} from "react-devtools-inline/frontend"; +import { ThreadFront } from "protocol/thread"; +import { features } from "ui/utils/prefs"; + +let bridge, store, wall, DevTools; +const messages = []; + +function InitReactDevTools() { + if (!features.reactDevtools) { + return null; + } + const target = { + postMessage: function () {}, + }; + + wall = { + emit() {}, + listen(listener) { + wall._listener = listener; + }, + send(event, payload) { + wall._listener({ event, payload }); + }, + }; + + bridge = createBridge(target, wall); + store = createStore(bridge); + DevTools = createDevTools(target, { bridge, store }); +} + +InitReactDevTools(); + +ThreadFront.getAnnotations(({ annotations }) => { + for (const { point, time, kind, contents } of annotations) { + const message = JSON.parse(contents); + messages.push({ point, time, message }); + } +}); + +let currentTime = null; +let rerenderComponentsTab; + +ThreadFront.on("paused", data => { + if (currentTime === data.time) { + return; + } + + InitReactDevTools(); + + // TODO Use point AND time eventually + messages + .filter(({ time }) => time <= data.time) + .forEach(({ message }) => { + if (message.event === "operations") { + wall.send(message.event, message.payload); + } + }); + + // HACK TODO This should use a subscription + if (typeof rerenderComponentsTab === "function") { + rerenderComponentsTab(); + } +}); + +// TODO Pass custom bridge +// TODO Use portal containers for Profiler & Components +export function ReactDevtoolsPanel() { + if (!features.reactDevtools) { + return null; + } + + const [count, setCount] = React.useState(0); + + // HACK TODO This hack handles the fact that DevTools wasn't writen + // with the expectation that a new Bridge or Store prop would be pasesd + // and doens't handle that case properly. + rerenderComponentsTab = () => { + setCount(count + 1); + }; + + return ( + + ); +} diff --git a/src/ui/components/SecondaryToolbox/index.js b/src/ui/components/SecondaryToolbox/index.js index ccc435170f9..720bebf97fd 100644 --- a/src/ui/components/SecondaryToolbox/index.js +++ b/src/ui/components/SecondaryToolbox/index.js @@ -6,77 +6,12 @@ import { features } from "ui/utils/prefs"; import Video from "../Video"; import WebConsoleApp from "devtools/client/webconsole/components/App"; import InspectorApp from "devtools/client/inspector/components/App"; -import { - createBridge, - createStore, - initialize as createDevTools, -} from "react-devtools-inline/frontend"; -import { ThreadFront } from "protocol/thread"; import "./SecondaryToolbox.css"; import NodePicker from "../NodePicker"; import { selectors } from "../../reducers"; import { actions } from "../../actions"; - -let bridge, store, wall, DevTools; - -function InitReactDevTools() { - if (!features.reactDevtools) { - return null; - } - const target = { - postMessage: function () {}, - }; - - wall = { - emit({ data }) {}, - listen(listener) { - wall._listener = listener; - }, - send(event: string, payload: any, transferable?: Array) { - wall._listener({ event, payload }); - }, - }; - - bridge = createBridge(target, wall); - store = createStore(bridge); - DevTools = createDevTools(target, { bridge, store }); -} - -InitReactDevTools(); - -const messages = []; -ThreadFront.getAnnotations(({ annotations }) => { - for (const { point, time, kind, contents } of annotations) { - const message = JSON.parse(contents); - messages.push({ point, time, message }); - } -}); - -let currentTime = null; -let rerenderComponentsTab; - -ThreadFront.on("paused", data => { - if (currentTime === data.time) { - return; - } - - InitReactDevTools(); - - // TODO Use point AND time eventually - messages - .filter(({ time }) => time <= data.time) - .forEach(({ message }) => { - if (message.event === "operations") { - wall.send(message.event, message.payload); - } - }); - - // HACK TODO This should use a subscription - if (typeof rerenderComponentsTab === "function") { - rerenderComponentsTab(); - } -}); +import { ReactDevtoolsPanel } from "./ReactDevTools"; function PanelButtons({ selectedPanel, setSelectedPanel, narrowMode }) { const { @@ -123,9 +58,9 @@ function PanelButtons({ selectedPanel, setSelectedPanel, narrowMode }) { {features.reactDevtools && ( @@ -152,34 +87,6 @@ function InspectorPanel() { ); } -// TODO Pass custom bridge -// TODO Use portal containers for Profiler & Components -function Components() { - if (!features.reactDevtools) { - return null; - } - - const [count, setCount] = React.useState(0); - - // HACK TODO This hack handles the fact that DevTools wasn't writen - // with the expectation that a new Bridge or Store prop would be pasesd - // and doens't handle that case properly. - rerenderComponentsTab = () => { - setCount(count + 1); - }; - - return ( - - ); -} - function SecondaryToolbox({ selectedPanel, setSelectedPanel, narrowMode }) { const { userSettings: { show_elements }, @@ -198,7 +105,7 @@ function SecondaryToolbox({ selectedPanel, setSelectedPanel, narrowMode }) { {selectedPanel == "console" ? : null} {selectedPanel == "inspector" && show_elements ? : null} {selectedPanel == "viewer" && narrowMode ?