diff --git a/packages/react-devtools-inline/src/frontend.js b/packages/react-devtools-inline/src/frontend.js index d9645999b3f0b..79bda7ecd8fb8 100644 --- a/packages/react-devtools-inline/src/frontend.js +++ b/packages/react-devtools-inline/src/frontend.js @@ -20,11 +20,16 @@ import type {Wall} from 'react-devtools-shared/src/types'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; import type {Props} from 'react-devtools-shared/src/devtools/views/DevTools'; -export function createStore(bridge: FrontendBridge): Store { +type Config = {| + supportsNativeInspection?: boolean, +|}; + +export function createStore(bridge: FrontendBridge, config?: Config): Store { return new Store(bridge, { checkBridgeProtocolCompatibility: true, supportsTraceUpdates: true, supportsSchedulingProfiler: true, + supportsNativeInspection: config?.supportsNativeInspection !== false, }); } diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.js b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.js index d0774d95f9611..f63da7b54a67d 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.js @@ -10,7 +10,7 @@ import * as React from 'react'; import {useCallback, useContext} from 'react'; import {TreeDispatcherContext, TreeStateContext} from './TreeContext'; -import {BridgeContext, StoreContext} from '../context'; +import {BridgeContext, StoreContext, OptionsContext} from '../context'; import Button from '../Button'; import ButtonIcon from '../ButtonIcon'; import {ModalDialogContext} from '../ModalDialog'; @@ -37,6 +37,12 @@ export default function InspectedElementWrapper(_: Props) { ); const bridge = useContext(BridgeContext); const store = useContext(StoreContext); + const { + hideToggleErrorAction, + hideToggleSuspenseAction, + hideLogAction, + hideViewSourceAction, + } = useContext(OptionsContext); const {dispatch: modalDialogDispatch} = useContext(ModalDialogContext); const { @@ -108,10 +114,14 @@ export default function InspectedElementWrapper(_: Props) { inspectedElement.state != null; const canToggleError = - inspectedElement != null && inspectedElement.canToggleError; + !hideToggleErrorAction && + inspectedElement != null && + inspectedElement.canToggleError; const canToggleSuspense = - inspectedElement != null && inspectedElement.canToggleSuspense; + !hideToggleSuspenseAction && + inspectedElement != null && + inspectedElement.canToggleSuspense; const toggleErrored = useCallback(() => { if (inspectedElement == null || targetErrorBoundaryID == null) { @@ -248,19 +258,23 @@ export default function InspectedElementWrapper(_: Props) { )} - - + {!hideLogAction && ( + + )} + {!hideViewSourceAction && ( + + )} {inspectedElement === null && ( diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementPropsTree.js b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementPropsTree.js index 7b6569cd32ce5..1673b5f9b1926 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementPropsTree.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementPropsTree.js @@ -9,6 +9,7 @@ import {copy} from 'clipboard-js'; import * as React from 'react'; +import {OptionsContext} from '../context'; import Button from '../Button'; import ButtonIcon from '../ButtonIcon'; import KeyValue from './KeyValue'; @@ -35,6 +36,8 @@ export default function InspectedElementPropsTree({ inspectedElement, store, }: Props) { + const {readOnly} = React.useContext(OptionsContext); + const { canEditFunctionProps, canEditFunctionPropsDeletePaths, @@ -45,7 +48,8 @@ export default function InspectedElementPropsTree({ const canDeletePaths = type === ElementTypeClass || canEditFunctionPropsDeletePaths; - const canEditValues = type === ElementTypeClass || canEditFunctionProps; + const canEditValues = + !readOnly && (type === ElementTypeClass || canEditFunctionProps); const canRenamePaths = type === ElementTypeClass || canEditFunctionPropsRenamePaths; diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSuspenseToggle.js b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSuspenseToggle.js index d486116bb84fe..0b0ce0ecac8a9 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSuspenseToggle.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSuspenseToggle.js @@ -8,6 +8,7 @@ */ import * as React from 'react'; +import {OptionsContext} from '../context'; import EditableValue from './EditableValue'; import Store from '../../store'; import {ElementTypeSuspense} from 'react-devtools-shared/src/types'; @@ -27,7 +28,10 @@ export default function InspectedElementSuspenseToggle({ inspectedElement, store, }: Props) { - const {canToggleSuspense, id, state, type} = inspectedElement; + const {readOnly} = React.useContext(OptionsContext); + + const {id, state, type} = inspectedElement; + const canToggleSuspense = !readOnly && inspectedElement.canToggleSuspense; if (type !== ElementTypeSuspense) { return null; diff --git a/packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js b/packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js index be45bab429dda..f09c9f3d602d2 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js @@ -9,6 +9,7 @@ import * as React from 'react'; import {useTransition, useContext, useRef, useState} from 'react'; +import {OptionsContext} from '../context'; import EditableName from './EditableName'; import EditableValue from './EditableValue'; import NewArrayValue from './NewArrayValue'; @@ -74,6 +75,11 @@ export default function KeyValue({ store, value, }: KeyValueProps) { + const {readOnly: readOnlyGlobalFlag} = useContext(OptionsContext); + canDeletePaths = !readOnlyGlobalFlag && canDeletePaths; + canEditValues = !readOnlyGlobalFlag && canEditValues; + canRenamePaths = !readOnlyGlobalFlag && canRenamePaths; + const {id} = inspectedElement; const [isOpen, setIsOpen] = useState(false); @@ -82,10 +88,10 @@ export default function KeyValue({ const {inspectPaths} = useContext(InspectedElementContext); let isInspectable = false; - let isReadOnly = false; + let isReadOnlyBasedOnMetadata = false; if (value !== null && typeof value === 'object') { isInspectable = value[meta.inspectable] && value[meta.size] !== 0; - isReadOnly = value[meta.readonly]; + isReadOnlyBasedOnMetadata = value[meta.readonly]; } const [isInspectPathsPending, startInspectPathsTransition] = useTransition(); @@ -330,9 +336,9 @@ export default function KeyValue({ key={index} alphaSort={alphaSort} bridge={bridge} - canDeletePaths={canDeletePaths && !isReadOnly} - canEditValues={canEditValues && !isReadOnly} - canRenamePaths={canRenamePaths && !isReadOnly} + canDeletePaths={canDeletePaths && !isReadOnlyBasedOnMetadata} + canEditValues={canEditValues && !isReadOnlyBasedOnMetadata} + canRenamePaths={canRenamePaths && !isReadOnlyBasedOnMetadata} canRenamePathsAtDepth={canRenamePathsAtDepth} depth={depth + 1} element={element} @@ -348,7 +354,7 @@ export default function KeyValue({ /> )); - if (canEditValues && !isReadOnly) { + if (canEditValues && !isReadOnlyBasedOnMetadata) { children.push( )); - if (canEditValues && !isReadOnly) { + if (canEditValues && !isReadOnlyBasedOnMetadata) { children.push( }> {ownerID !== null ? : } -
{showInlineWarningsAndErrors && ownerID === null && (errors > 0 || warnings > 0) && ( +
{errors > 0 && (
@@ -376,10 +377,14 @@ export default function Tree(props: Props) { title="Clear all errors and warnings"> -
)} - + {!hideSettings && ( + +
+ + + )}