Add ui-debugger modes
Summary: ## This diff: Add debugger mode infrastructure We want to enable infrastructure allowing adding modes in the future without branching client and plugin code This infra allows for the client to send a message informing flipper about the supported modes (following diffs) Currently broadcasting mode change event over to the client Reviewed By: lblasa Differential Revision: D49385860 fbshipit-source-id: 2db6f65064d1ff7e1f57b2da93c3ed195400fb7f
This commit is contained in:
committed by
Facebook GitHub Bot
parent
c3ad4f7180
commit
1c3720fd5c
@@ -7,6 +7,8 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {TraversalMode} from './DesktopTypes';
|
||||||
|
|
||||||
export type Events = {
|
export type Events = {
|
||||||
init: InitEvent;
|
init: InitEvent;
|
||||||
subtreeUpdate: SubtreeUpdateEvent;
|
subtreeUpdate: SubtreeUpdateEvent;
|
||||||
@@ -14,6 +16,11 @@ export type Events = {
|
|||||||
perfStats: PerfStatsEvent;
|
perfStats: PerfStatsEvent;
|
||||||
performanceStats: PerformanceStatsEvent;
|
performanceStats: PerformanceStatsEvent;
|
||||||
metadataUpdate: UpdateMetadataEvent;
|
metadataUpdate: UpdateMetadataEvent;
|
||||||
|
setTraversalMode: SetTraversalModeEvent;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SetTraversalModeEvent = {
|
||||||
|
mode: TraversalMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FrameScanEvent = {
|
export type FrameScanEvent = {
|
||||||
@@ -69,6 +76,8 @@ export type FrameworkEvent = {
|
|||||||
export type InitEvent = {
|
export type InitEvent = {
|
||||||
rootId: Id;
|
rootId: Id;
|
||||||
frameworkEventMetadata?: FrameworkEventMetadata[];
|
frameworkEventMetadata?: FrameworkEventMetadata[];
|
||||||
|
supportedTraversalModes?: TraversalMode[];
|
||||||
|
currentTraversalMode?: TraversalMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,6 +119,10 @@ export type UpdateMetadataEvent = {
|
|||||||
attributeMetadata: Record<MetadataId, Metadata>;
|
attributeMetadata: Record<MetadataId, Metadata>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type UpdateAvailableTraversalModeEvent = {
|
||||||
|
modes: TraversalMode[];
|
||||||
|
};
|
||||||
|
|
||||||
export type ClientNode = {
|
export type ClientNode = {
|
||||||
id: Id;
|
id: Id;
|
||||||
parent?: Id;
|
parent?: Id;
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ export type UIState = {
|
|||||||
visualiserWidth: Atom<number>;
|
visualiserWidth: Atom<number>;
|
||||||
frameworkEventMonitoring: Atom<Map<FrameworkEventType, boolean>>;
|
frameworkEventMonitoring: Atom<Map<FrameworkEventType, boolean>>;
|
||||||
filterMainThreadMonitoring: Atom<boolean>;
|
filterMainThreadMonitoring: Atom<boolean>;
|
||||||
|
|
||||||
|
supportedTraversalModes: Atom<TraversalMode[]>;
|
||||||
|
currentTraversalMode: Atom<TraversalMode>;
|
||||||
};
|
};
|
||||||
|
|
||||||
//enumerates the keys of input type and casts each to ReadOnlyAtom, this is so we only expose read only atoms to the UI
|
//enumerates the keys of input type and casts each to ReadOnlyAtom, this is so we only expose read only atoms to the UI
|
||||||
@@ -66,6 +69,8 @@ export type NestedNode = {
|
|||||||
activeChildIdx?: number;
|
activeChildIdx?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type TraversalMode = 'view-hierarchy' | 'accessibility-hierarchy';
|
||||||
|
|
||||||
export type ViewMode =
|
export type ViewMode =
|
||||||
| {mode: 'default'}
|
| {mode: 'default'}
|
||||||
| {mode: 'frameworkEventsTable'; nodeId: Id; isTree: boolean};
|
| {mode: 'frameworkEventsTable'; nodeId: Id; isTree: boolean};
|
||||||
@@ -106,6 +111,7 @@ export type UIActions = {
|
|||||||
onCollapseAllNonAncestors: (nodeId: Id) => void;
|
onCollapseAllNonAncestors: (nodeId: Id) => void;
|
||||||
onCollapseAllRecursively: (nodeId: Id) => void;
|
onCollapseAllRecursively: (nodeId: Id) => void;
|
||||||
ensureAncestorsExpanded: (nodeId: Id) => void;
|
ensureAncestorsExpanded: (nodeId: Id) => void;
|
||||||
|
setCurrentTraversalMode: (mode: TraversalMode) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SelectionSource =
|
export type SelectionSource =
|
||||||
|
|||||||
@@ -18,10 +18,12 @@ import {
|
|||||||
Space,
|
Space,
|
||||||
Switch,
|
Switch,
|
||||||
Badge,
|
Badge,
|
||||||
|
Dropdown,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import {
|
import {
|
||||||
EyeOutlined,
|
EyeOutlined,
|
||||||
PauseCircleOutlined,
|
PauseCircleOutlined,
|
||||||
|
AppstoreOutlined,
|
||||||
PlayCircleOutlined,
|
PlayCircleOutlined,
|
||||||
SearchOutlined,
|
SearchOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
@@ -31,6 +33,7 @@ import {
|
|||||||
buildTreeSelectData,
|
buildTreeSelectData,
|
||||||
FrameworkEventsTreeSelect,
|
FrameworkEventsTreeSelect,
|
||||||
} from '../shared/FrameworkEventsTreeSelect';
|
} from '../shared/FrameworkEventsTreeSelect';
|
||||||
|
import {TraversalMode} from '../../DesktopTypes';
|
||||||
|
|
||||||
export const TreeControls: React.FC = () => {
|
export const TreeControls: React.FC = () => {
|
||||||
const instance = usePlugin(plugin);
|
const instance = usePlugin(plugin);
|
||||||
@@ -44,13 +47,50 @@ export const TreeControls: React.FC = () => {
|
|||||||
instance.uiState.frameworkEventMonitoring,
|
instance.uiState.frameworkEventMonitoring,
|
||||||
);
|
);
|
||||||
|
|
||||||
const frameworkEventMetadata = useValue(instance.frameworkEventMetadata);
|
|
||||||
|
|
||||||
const [showFrameworkEventsModal, setShowFrameworkEventsModal] =
|
const [showFrameworkEventsModal, setShowFrameworkEventsModal] =
|
||||||
useState(false);
|
useState(false);
|
||||||
|
|
||||||
|
const frameworkEventMetadata = useValue(instance.frameworkEventMetadata);
|
||||||
|
|
||||||
|
const currentTraversalMode = useValue(instance.uiState.currentTraversalMode);
|
||||||
|
const supportedTraversalModes = useValue(
|
||||||
|
instance.uiState.supportedTraversalModes,
|
||||||
|
);
|
||||||
|
const labelForMode = (mode: TraversalMode) => {
|
||||||
|
switch (mode) {
|
||||||
|
case 'view-hierarchy':
|
||||||
|
return 'UI Hierarchy';
|
||||||
|
case 'accessibility-hierarchy':
|
||||||
|
return 'Accessibility Hierarchy';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const menus = supportedTraversalModes.map((mode) => ({
|
||||||
|
key: mode,
|
||||||
|
label: labelForMode(mode),
|
||||||
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout.Horizontal gap="medium" pad="medium">
|
<Layout.Horizontal gap="medium" pad="medium">
|
||||||
|
{supportedTraversalModes.length > 1 ? (
|
||||||
|
<Dropdown
|
||||||
|
menu={{
|
||||||
|
selectable: true,
|
||||||
|
selectedKeys: [currentTraversalMode],
|
||||||
|
items: menus,
|
||||||
|
onSelect: async (event) => {
|
||||||
|
const mode = event.selectedKeys[0] as TraversalMode;
|
||||||
|
instance.uiActions.setCurrentTraversalMode(mode); // update UI
|
||||||
|
await instance.onTraversalModeChange(mode); // update mobile client
|
||||||
|
},
|
||||||
|
}}>
|
||||||
|
<Tooltip title="Debugger Mode">
|
||||||
|
<Button shape="circle">
|
||||||
|
<AppstoreOutlined />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
</Dropdown>
|
||||||
|
) : null}
|
||||||
<Input
|
<Input
|
||||||
value={searchTerm}
|
value={searchTerm}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
UIState,
|
UIState,
|
||||||
NodeSelection,
|
NodeSelection,
|
||||||
|
TraversalMode,
|
||||||
StreamState,
|
StreamState,
|
||||||
ReadOnlyUIState,
|
ReadOnlyUIState,
|
||||||
LiveClientState,
|
LiveClientState,
|
||||||
@@ -38,7 +39,15 @@ import {uiActions} from './plugin/uiActions';
|
|||||||
import {first} from 'lodash';
|
import {first} from 'lodash';
|
||||||
import {getNode} from './utils/map';
|
import {getNode} from './utils/map';
|
||||||
|
|
||||||
export function plugin(client: PluginClient<Events>) {
|
type TraversalModeChangeEvent = {
|
||||||
|
mode: TraversalMode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Methods = {
|
||||||
|
onTraversalModeChange(params: TraversalModeChangeEvent): Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function plugin(client: PluginClient<Events, Methods>) {
|
||||||
const rootId = createState<Id | undefined>(undefined);
|
const rootId = createState<Id | undefined>(undefined);
|
||||||
const metadata = createState<Map<MetadataId, Metadata>>(new Map());
|
const metadata = createState<Map<MetadataId, Metadata>>(new Map());
|
||||||
|
|
||||||
@@ -87,6 +96,22 @@ export function plugin(client: PluginClient<Events>) {
|
|||||||
draft.set(frameworkEventMeta.type, false);
|
draft.set(frameworkEventMeta.type, false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
if (
|
||||||
|
event.supportedTraversalModes &&
|
||||||
|
event.supportedTraversalModes.length > 1
|
||||||
|
) {
|
||||||
|
uiState.supportedTraversalModes.set(event.supportedTraversalModes);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
event.currentTraversalMode &&
|
||||||
|
uiState.supportedTraversalModes.get().includes(event.currentTraversalMode)
|
||||||
|
) {
|
||||||
|
uiState.currentTraversalMode.set(event.currentTraversalMode);
|
||||||
|
console.log(
|
||||||
|
`[ui-debugger] Unsupported debugger mode ${event.currentTraversalMode}.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
frameworkEventMetadata.update((draft) => {
|
frameworkEventMetadata.update((draft) => {
|
||||||
event.frameworkEventMetadata?.forEach((frameworkEventMeta) => {
|
event.frameworkEventMetadata?.forEach((frameworkEventMeta) => {
|
||||||
draft.set(frameworkEventMeta.type, frameworkEventMeta);
|
draft.set(frameworkEventMeta.type, frameworkEventMeta);
|
||||||
@@ -256,6 +281,9 @@ export function plugin(client: PluginClient<Events>) {
|
|||||||
});
|
});
|
||||||
client.onMessage('frameScan', processFrame);
|
client.onMessage('frameScan', processFrame);
|
||||||
|
|
||||||
|
const onTraversalModeChange = async (mode: TraversalMode) =>
|
||||||
|
client.send('onTraversalModeChange', {mode});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
rootId,
|
rootId,
|
||||||
uiState: uiState as ReadOnlyUIState,
|
uiState: uiState as ReadOnlyUIState,
|
||||||
@@ -268,6 +296,7 @@ export function plugin(client: PluginClient<Events>) {
|
|||||||
metadata,
|
metadata,
|
||||||
perfEvents,
|
perfEvents,
|
||||||
os: client.device.os,
|
os: client.device.os,
|
||||||
|
onTraversalModeChange,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,5 +337,9 @@ function createUIState(): UIState {
|
|||||||
focusedNode: createState<Id | undefined>(undefined),
|
focusedNode: createState<Id | undefined>(undefined),
|
||||||
expandedNodes: createState<Set<Id>>(new Set()),
|
expandedNodes: createState<Set<Id>>(new Set()),
|
||||||
wireFrameMode: createState<WireFrameMode>('All'),
|
wireFrameMode: createState<WireFrameMode>('All'),
|
||||||
|
|
||||||
|
// view-hierarchy is the default state so we start with it until we fetch supported modes from the client
|
||||||
|
supportedTraversalModes: createState<TraversalMode[]>(['view-hierarchy']),
|
||||||
|
currentTraversalMode: createState<TraversalMode>('view-hierarchy'),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {Atom} from 'flipper-plugin';
|
|||||||
import {debounce} from 'lodash';
|
import {debounce} from 'lodash';
|
||||||
import {ClientNode, FrameworkEventType, Id, SnapshotInfo} from '../ClientTypes';
|
import {ClientNode, FrameworkEventType, Id, SnapshotInfo} from '../ClientTypes';
|
||||||
import {
|
import {
|
||||||
|
TraversalMode,
|
||||||
LiveClientState,
|
LiveClientState,
|
||||||
SelectionSource,
|
SelectionSource,
|
||||||
UIActions,
|
UIActions,
|
||||||
@@ -189,6 +190,11 @@ export function uiActions(
|
|||||||
searchTermUpdatedDebounced(searchTerm);
|
searchTermUpdatedDebounced(searchTerm);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setCurrentTraversalMode = (mode: TraversalMode) => {
|
||||||
|
tracker.track('traversal-mode-updated', {mode});
|
||||||
|
uiState.currentTraversalMode.set(mode);
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
onExpandNode,
|
onExpandNode,
|
||||||
onCollapseNode,
|
onCollapseNode,
|
||||||
@@ -207,5 +213,6 @@ export function uiActions(
|
|||||||
onExpandAllRecursively,
|
onExpandAllRecursively,
|
||||||
onCollapseAllRecursively,
|
onCollapseAllRecursively,
|
||||||
ensureAncestorsExpanded,
|
ensureAncestorsExpanded,
|
||||||
|
setCurrentTraversalMode,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
import {getFlipperLib} from 'flipper-plugin';
|
import {getFlipperLib} from 'flipper-plugin';
|
||||||
|
|
||||||
import {FrameworkEventType, Tag} from '../ClientTypes';
|
import {FrameworkEventType, Tag} from '../ClientTypes';
|
||||||
import {SelectionSource} from '../DesktopTypes';
|
import {TraversalMode, SelectionSource} from '../DesktopTypes';
|
||||||
|
|
||||||
const UI_DEBUGGER_IDENTIFIER = 'ui-debugger';
|
const UI_DEBUGGER_IDENTIFIER = 'ui-debugger';
|
||||||
|
|
||||||
@@ -67,6 +67,7 @@ type TrackerEvents = {
|
|||||||
'context-menu-expand-recursive': {};
|
'context-menu-expand-recursive': {};
|
||||||
'context-menu-collapse-recursive': {};
|
'context-menu-collapse-recursive': {};
|
||||||
'context-menu-collapse-non-ancestors': {};
|
'context-menu-collapse-non-ancestors': {};
|
||||||
|
'traversal-mode-updated': {mode: TraversalMode};
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface Tracker {
|
export interface Tracker {
|
||||||
|
|||||||
Reference in New Issue
Block a user