Skip to content

Commit

Permalink
feat(devtools): toggle the display of devtools while inspecting React…
Browse files Browse the repository at this point in the history
… elements (#5303)
  • Loading branch information
Asuka109 authored Jan 24, 2024
1 parent 97cbdec commit 2d3971d
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@
justify-content: center;
align-items: center;
transition: opacity 200ms;
border: none;
background-color: transparent;
cursor: pointer;

&[data-loading='true'] {
&:disabled {
cursor: wait;
pointer-events: none;
}

&[data-type='default'] {
opacity: 0.4;
&:hover {
&:not(:disabled):hover {
opacity: 1;
}
}
Expand Down
7 changes: 3 additions & 4 deletions packages/devtools/client/src/components/Devtools/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from 'react';
import { useAsyncFn } from 'react-use';
import { Promisable } from 'type-fest';
import { Box } from '@radix-ui/themes';
import styles from './Button.module.scss';

export interface DevtoolsCapsuleButtonProps extends React.PropsWithChildren {
Expand All @@ -18,13 +17,13 @@ export const DevtoolsCapsuleButton: React.FC<
);

return (
<Box
<button
className={styles.container}
onClick={handleClick}
data-type={props.type ?? 'default'}
data-loading={clickState.loading}
disabled={clickState.loading}
>
{props.children}
</Box>
</button>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
padding: 0 var(--space-1);
transition: box-shadow 400ms;
user-select: none;
animation: slideInFromRight 400ms ease-out forwards;

&:hover {
box-shadow: var(--shadow-5), 0 0 20px var(--gray-a7);
Expand All @@ -47,3 +48,13 @@
background-size: contain;
}

@keyframes slideInFromRight {
0% {
opacity: 0;
transform: translateX(50%);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
52 changes: 38 additions & 14 deletions packages/devtools/client/src/components/Devtools/Capsule.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { SetupClientParams } from '@modern-js/devtools-kit';
import { Flex, Theme } from '@radix-ui/themes';
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { useEvent, useToggle } from 'react-use';
import { HiMiniCursorArrowRipple } from 'react-icons/hi2';
import { withQuery } from 'ufo';
Expand All @@ -9,8 +9,9 @@ import styles from './Capsule.module.scss';
import { FrameBox } from './FrameBox';
import { DevtoolsCapsuleButton } from './Button';
import { useStickyDraggable } from '@/utils/draggable';
import { $client } from '@/entries/mount/state';
import { $client, bridge, wallAgent } from '@/entries/mount/state';
import { pTimeout } from '@/utils/promise';
import { ReactDevtoolsWallListener } from '@/utils/react-devtools';

export const DevtoolsCapsule: React.FC<SetupClientParams> = props => {
const logoSrc = props.def.assets.logo;
Expand All @@ -37,12 +38,37 @@ export const DevtoolsCapsule: React.FC<SetupClientParams> = props => {
e.shiftKey && e.altKey && e.code === 'KeyD' && toggleDevtools();
});

useEffect(() => {
const handleStartInspecting = () => {
toggleDevtools(false);
document.documentElement.style.setProperty('cursor', 'cell');
};
bridge.addListener('startInspectingNative', handleStartInspecting);

const handleBeforeWallSend: ReactDevtoolsWallListener = e => {
if (e.event !== 'stopInspectingNative') return;
toggleDevtools(true);
document.documentElement.style.removeProperty('cursor');
};
wallAgent.hook('send', handleBeforeWallSend);

return () => {
bridge.removeListener('startInspectingNative', handleStartInspecting);
wallAgent.removeHook('send', handleBeforeWallSend);
};
}, []);

const handleClickInspect = async () => {
document.documentElement.style.setProperty('cursor', 'wait');
toggleDevtools(false);
setLoadDevtools(true);
const client = await pTimeout($client, 10_000).catch(() => null);
if (!client) return;
client.remote.pullUpReactInspector();
try {
const client = await pTimeout($client, 10_000);
client.remote.pullUpReactInspector();
} catch (e) {
console.error(e);
document.documentElement.style.removeProperty('cursor');
}
};

return (
Expand All @@ -56,15 +82,13 @@ export const DevtoolsCapsule: React.FC<SetupClientParams> = props => {
/>
</div>
</Visible>
<Flex asChild align="center">
<div className={styles.fab} {...draggable.props}>
<DevtoolsCapsuleButton type="primary" onClick={toggleDevtools}>
<img className={styles.logo} src={logoSrc}></img>
</DevtoolsCapsuleButton>
<DevtoolsCapsuleButton onClick={handleClickInspect}>
<HiMiniCursorArrowRipple />
</DevtoolsCapsuleButton>
</div>
<Flex className={styles.fab} {...draggable.props} align="center">
<DevtoolsCapsuleButton type="primary" onClick={toggleDevtools}>
<img className={styles.logo} src={logoSrc}></img>
</DevtoolsCapsuleButton>
<DevtoolsCapsuleButton onClick={handleClickInspect}>
<HiMiniCursorArrowRipple />
</DevtoolsCapsuleButton>
</Flex>
</Theme>
);
Expand Down
1 change: 1 addition & 0 deletions packages/devtools/client/src/utils/promise.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export const pTimeout = <T>(promise: Promise<T>, timeout: number) =>
let active = true;
const timer = setTimeout(() => {
active = false;
reject(new Error('Promise Timeout'));
}, timeout);
promise.then(res => {
active && resolve(res);
Expand Down
14 changes: 10 additions & 4 deletions packages/devtools/client/src/utils/react-devtools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ export interface ReactDevtoolsWallEvent {
transferable?: any[] | undefined;
}

export type ReactDevtoolsWallListener = (event: ReactDevtoolsWallEvent) => void;
export type ReactDevtoolsWallListener = (
event: ReactDevtoolsWallEvent,
...rest: unknown[]
) => void;

export type WallAgentHooks = Record<
'send' | 'receive',
(...args: any[]) => void
ReactDevtoolsWallListener
>;

export type BirpcReturnLike = Record<string, (...args: any[]) => void> & {
Expand All @@ -36,8 +39,11 @@ export class WallAgent extends Hookable<WallAgentHooks> implements Wall {

bindRemote(remote: BirpcReturn<object, object>, methodName: string) {
const _remote = remote as any;
_remote.$functions[methodName] = (...args: any[]) => {
this.callHook('receive', ...args);
_remote.$functions[methodName] = (
event: ReactDevtoolsWallEvent,
...rest: unknown[]
) => {
this.callHook('receive', event, ...rest);
};
this.hook('send', (...args) => {
_remote[methodName](...args);
Expand Down

0 comments on commit 2d3971d

Please sign in to comment.