UID refactor 4/ Expose readonly UIState
Summary: Currently state writes can either go through a named handler that is easy to find and debug or they can directly modify the state. By exposing readonly atoms only we ensure that all state writes go through a UIACtions. This adds consistency and ease of future debugging. E.g We could add a utility to wrap all ui actions with logging statements Reviewed By: antonk52 Differential Revision: D47547531 fbshipit-source-id: f88651169d8e7c5f7e31068d64f9aa5b6b573647
This commit is contained in:
committed by
Facebook GitHub Bot
parent
87a1b657c3
commit
957a336349
@@ -27,12 +27,6 @@ import {
|
||||
} from '@ant-design/icons';
|
||||
import {usePlugin, useValue, Layout} from 'flipper-plugin';
|
||||
import {FrameworkEventType} from '../ClientTypes';
|
||||
import {tracker} from '../utils/tracker';
|
||||
import {debounce} from 'lodash';
|
||||
|
||||
const searchTermUpdated = debounce((searchTerm: string) => {
|
||||
tracker.track('search-term-updated', {searchTerm});
|
||||
}, 250);
|
||||
|
||||
export const Controls: React.FC = () => {
|
||||
const instance = usePlugin(plugin);
|
||||
@@ -49,23 +43,12 @@ export const Controls: React.FC = () => {
|
||||
const [showFrameworkEventsModal, setShowFrameworkEventsModal] =
|
||||
useState(false);
|
||||
|
||||
const onSetEventMonitored: (
|
||||
eventType: FrameworkEventType,
|
||||
monitored: boolean,
|
||||
) => void = (eventType: FrameworkEventType, monitored: boolean) => {
|
||||
tracker.track('framework-event-monitored', {eventType, monitored});
|
||||
instance.uiState.frameworkEventMonitoring.update((draft) =>
|
||||
draft.set(eventType, monitored),
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Layout.Horizontal pad="small" gap="small">
|
||||
<Input
|
||||
value={searchTerm}
|
||||
onChange={(e) => {
|
||||
instance.uiState.searchTerm.set(e.target.value);
|
||||
searchTermUpdated(e.target.value);
|
||||
instance.uiActions.onSearchTermUpdated(e.target.value);
|
||||
}}
|
||||
prefix={<SearchOutlined />}
|
||||
placeholder="Search"
|
||||
@@ -73,11 +56,7 @@ export const Controls: React.FC = () => {
|
||||
<Button
|
||||
type="default"
|
||||
shape="circle"
|
||||
onClick={() => {
|
||||
const isPaused = !instance.uiState.isPaused.get();
|
||||
tracker.track('play-pause-toggled', {paused: isPaused});
|
||||
instance.setPlayPause(isPaused);
|
||||
}}
|
||||
onClick={instance.uiActions.onPlayPauseToggled}
|
||||
icon={
|
||||
<Tooltip
|
||||
title={isPaused ? 'Resume live updates' : 'Pause incoming updates'}>
|
||||
@@ -102,7 +81,7 @@ export const Controls: React.FC = () => {
|
||||
instance.uiActions.onSetFilterMainThreadMonitoring
|
||||
}
|
||||
frameworkEventTypes={[...frameworkEventMonitoring.entries()]}
|
||||
onSetEventMonitored={onSetEventMonitored}
|
||||
onSetEventMonitored={instance.uiActions.onSetFrameworkEventMonitored}
|
||||
visible={showFrameworkEventsModal}
|
||||
onCancel={() => setShowFrameworkEventsModal(false)}
|
||||
/>
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
ClientNode,
|
||||
FrameworkEvent,
|
||||
} from '../ClientTypes';
|
||||
import {UIState} from '../DesktopTypes';
|
||||
import {ReadOnlyUIState} from '../DesktopTypes';
|
||||
import React, {useMemo} from 'react';
|
||||
import {
|
||||
DataInspector,
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
} from 'flipper-plugin';
|
||||
|
||||
export function PerfStats(props: {
|
||||
uiState: UIState;
|
||||
uiState: ReadOnlyUIState;
|
||||
nodes: Map<Id, ClientNode>;
|
||||
rootId?: Id;
|
||||
events: DataSource<DynamicPerformanceStatsEvent, number>;
|
||||
|
||||
@@ -253,7 +253,7 @@ export function Tree2({
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
if (isContextMenuOpen === false) {
|
||||
instance.uiState.hoveredNodes.set([]);
|
||||
instance.uiActions.onHoverNode();
|
||||
}
|
||||
}}>
|
||||
{rowVirtualizer.getVirtualItems().map((virtualRow) => (
|
||||
@@ -756,7 +756,7 @@ function useKeyboardShortcuts(
|
||||
selectedNode: Id | undefined,
|
||||
hoveredNodeId: Id | undefined,
|
||||
onSelectNode: OnSelectNode,
|
||||
onHoverNode: (id?: Id) => void,
|
||||
onHoverNode: (...id: Id[]) => void,
|
||||
onExpandNode: (id: Id) => void,
|
||||
onCollapseNode: (id: Id) => void,
|
||||
isUsingKBToScrollUntill: React.MutableRefObject<number>,
|
||||
@@ -861,7 +861,7 @@ function moveSelectedNodeUpOrDown(
|
||||
hoveredNode: Id | undefined,
|
||||
selectedNode: Id | undefined,
|
||||
onSelectNode: OnSelectNode,
|
||||
onHoverNode: (id?: Id) => void,
|
||||
onHoverNode: (...id: Id[]) => void,
|
||||
isUsingKBToScrollUntill: React.MutableRefObject<MillisSinceEpoch>,
|
||||
) {
|
||||
const nodeToUse = selectedNode != null ? selectedNode : hoveredNode;
|
||||
@@ -886,7 +886,7 @@ function moveSelectedNodeViaKeyBoard(
|
||||
treeNodes: TreeNode[],
|
||||
rowVirtualizer: Virtualizer<HTMLDivElement, Element>,
|
||||
onSelectNode: OnSelectNode,
|
||||
onHoverNode: (id?: Id) => void,
|
||||
onHoverNode: (...id: Id[]) => void,
|
||||
isUsingKBToScrollUntil: React.MutableRefObject<number>,
|
||||
) {
|
||||
if (newIdx >= 0 && newIdx < treeNodes.length) {
|
||||
|
||||
@@ -80,7 +80,7 @@ export const Visualization2D: React.FC<
|
||||
hitNodes.length > 0 &&
|
||||
!isEqual(hitNodes, instance.uiState.hoveredNodes.get())
|
||||
) {
|
||||
instance.uiState.hoveredNodes.set(hitNodes);
|
||||
instance.uiActions.onHoverNode(...hitNodes);
|
||||
}
|
||||
}, MouseThrottle);
|
||||
window.addEventListener('mousemove', mouseListener);
|
||||
@@ -95,6 +95,7 @@ export const Visualization2D: React.FC<
|
||||
instance.uiState.isContextMenuOpen,
|
||||
width,
|
||||
snapshotNode,
|
||||
instance.uiActions,
|
||||
]);
|
||||
|
||||
if (!focusState || !snapshotNode) {
|
||||
@@ -110,7 +111,7 @@ export const Visualization2D: React.FC<
|
||||
e.stopPropagation();
|
||||
//the context menu triggers this callback but we dont want to remove hover effect
|
||||
if (!instance.uiState.isContextMenuOpen.get()) {
|
||||
instance.uiState.hoveredNodes.set([]);
|
||||
instance.uiActions.onHoverNode();
|
||||
}
|
||||
|
||||
mouseInVisualiserRef.current = false;
|
||||
@@ -338,7 +339,7 @@ const ContextMenu: React.FC<{nodes: Map<Id, ClientNode>}> = ({children}) => {
|
||||
return (
|
||||
<Dropdown
|
||||
onVisibleChange={(open) => {
|
||||
instance.uiState.isContextMenuOpen.set(open);
|
||||
instance.uiActions.onContextMenuOpen(open);
|
||||
}}
|
||||
trigger={['contextMenu']}
|
||||
overlay={() => {
|
||||
@@ -358,7 +359,7 @@ const ContextMenu: React.FC<{nodes: Map<Id, ClientNode>}> = ({children}) => {
|
||||
key="remove-focus"
|
||||
text="Remove focus"
|
||||
onClick={() => {
|
||||
instance.uiState.focusedNode.set(undefined);
|
||||
instance.uiActions.onFocusNode(undefined);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -39,7 +39,7 @@ export const UIDebuggerMenuItem: React.FC<{
|
||||
disabled={onClick == null}
|
||||
onClick={() => {
|
||||
onClick?.();
|
||||
instance.uiState.isContextMenuOpen.set(false);
|
||||
instance.uiActions.onContextMenuOpen(false);
|
||||
}}>
|
||||
<Layout.Horizontal center gap="small">
|
||||
{icon}
|
||||
|
||||
Reference in New Issue
Block a user