mirror of
https://github.com/zebrajr/react.git
synced 2026-01-15 12:15:22 +00:00
[DevTools] Show list of named Activities in Suspense tab (#35092)
This commit is contained in:
committed by
GitHub
parent
ea4899e13f
commit
7f1a085b28
@@ -1058,6 +1058,33 @@ export default class Store extends EventEmitter<{
|
||||
return timeline;
|
||||
}
|
||||
|
||||
getActivities(): Array<{id: Element['id'], depth: number}> {
|
||||
const target: Array<{id: Element['id'], depth: number}> = [];
|
||||
// TODO: Keep a live tree in the backend so we don't need to recalculate
|
||||
// this each time while also including filtered Activities.
|
||||
this._pushActivitiesInDocumentOrder(this.roots, target, 0);
|
||||
return target;
|
||||
}
|
||||
|
||||
_pushActivitiesInDocumentOrder(
|
||||
children: $ReadOnlyArray<Element['id']>,
|
||||
target: Array<{id: Element['id'], depth: number}>,
|
||||
depth: number,
|
||||
): void {
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const child = this._idToElement.get(children[i]);
|
||||
if (child === undefined) {
|
||||
continue;
|
||||
}
|
||||
if (child.type === ElementTypeActivity && child.nameProp !== null) {
|
||||
target.push({id: child.id, depth});
|
||||
this._pushActivitiesInDocumentOrder(child.children, target, depth + 1);
|
||||
} else {
|
||||
this._pushActivitiesInDocumentOrder(child.children, target, depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getRendererIDForElement(id: number): number | null {
|
||||
let current = this._idToElement.get(id);
|
||||
while (current !== undefined) {
|
||||
|
||||
@@ -59,6 +59,7 @@ export type StateContext = {
|
||||
|
||||
// Activity slice
|
||||
activityID: Element['id'] | null,
|
||||
activities: $ReadOnlyArray<{id: Element['id'], depth: number}>,
|
||||
|
||||
// Inspection element panel
|
||||
inspectedElementID: number | null,
|
||||
@@ -172,6 +173,7 @@ type State = {
|
||||
|
||||
// Activity slice
|
||||
activityID: Element['id'] | null,
|
||||
activities: $ReadOnlyArray<{id: Element['id'], depth: number}>,
|
||||
|
||||
// Inspection element panel
|
||||
inspectedElementID: number | null,
|
||||
@@ -809,6 +811,7 @@ function reduceActivityState(
|
||||
case 'HANDLE_STORE_MUTATION':
|
||||
let {activityID} = state;
|
||||
const [, , activitySliceIDChange] = action.payload;
|
||||
const activities = store.getActivities();
|
||||
if (activitySliceIDChange === 0 && activityID !== null) {
|
||||
activityID = null;
|
||||
} else if (
|
||||
@@ -817,10 +820,11 @@ function reduceActivityState(
|
||||
) {
|
||||
activityID = activitySliceIDChange;
|
||||
}
|
||||
if (activityID !== state.activityID) {
|
||||
if (activityID !== state.activityID || activities !== state.activities) {
|
||||
return {
|
||||
...state,
|
||||
activityID,
|
||||
activities,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -863,6 +867,7 @@ function getInitialState({
|
||||
|
||||
// Activity slice
|
||||
activityID: null,
|
||||
activities: store.getActivities(),
|
||||
|
||||
// Inspection element panel
|
||||
inspectedElementID:
|
||||
|
||||
@@ -1,20 +1,33 @@
|
||||
.ActivityList {
|
||||
.ActivityListContaier {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.ActivityListHeader {
|
||||
/* even if empty, provides layout alignment with the main view */
|
||||
display: flex;
|
||||
flex: 0 0 42px;
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
.ActivityListList {
|
||||
cursor: default;
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ActivityList[data-pending-activity-slice-selection="true"] {
|
||||
.ActivityListList[data-pending-activity-slice-selection="true"] {
|
||||
cursor: wait;
|
||||
}
|
||||
|
||||
.ActivityList:focus {
|
||||
.ActivityListList:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.ActivityListItem {
|
||||
color: var(--color-component-name);
|
||||
line-height: var(--line-height-data);
|
||||
padding: 0 0.25rem;
|
||||
user-select: none;
|
||||
}
|
||||
@@ -27,7 +40,7 @@
|
||||
background-color: var(--color-background-inactive);
|
||||
}
|
||||
|
||||
.ActivityList:focus .ActivityListItem[aria-selected="true"] {
|
||||
.ActivityListList:focus .ActivityListItem[aria-selected="true"] {
|
||||
background-color: var(--color-background-selected);
|
||||
color: var(--color-text-selected);
|
||||
|
||||
|
||||
@@ -15,10 +15,14 @@ import typeof {
|
||||
SyntheticMouseEvent,
|
||||
SyntheticKeyboardEvent,
|
||||
} from 'react-dom-bindings/src/events/SyntheticEvent';
|
||||
import type Store from 'react-devtools-shared/src/devtools/store';
|
||||
|
||||
import * as React from 'react';
|
||||
import {useContext, useTransition} from 'react';
|
||||
import {ComponentFilterActivitySlice} from 'react-devtools-shared/src/frontend/types';
|
||||
import {useContext, useMemo, useTransition} from 'react';
|
||||
import {
|
||||
ComponentFilterActivitySlice,
|
||||
ElementTypeActivity,
|
||||
} from 'react-devtools-shared/src/frontend/types';
|
||||
import styles from './ActivityList.css';
|
||||
import {
|
||||
TreeStateContext,
|
||||
@@ -26,6 +30,8 @@ import {
|
||||
} from '../Components/TreeContext';
|
||||
import {useHighlightHostInstance} from '../hooks';
|
||||
import {StoreContext} from '../context';
|
||||
import ButtonIcon from '../ButtonIcon';
|
||||
import Button from '../Button';
|
||||
|
||||
export function useChangeActivitySliceAction(): (
|
||||
id: Element['id'] | null,
|
||||
@@ -62,15 +68,49 @@ export function useChangeActivitySliceAction(): (
|
||||
return changeActivitySliceAction;
|
||||
}
|
||||
|
||||
function findNearestActivityParentID(
|
||||
elementID: Element['id'],
|
||||
store: Store,
|
||||
): Element['id'] | null {
|
||||
let currentID: null | Element['id'] = elementID;
|
||||
while (currentID !== null) {
|
||||
const element = store.getElementByID(currentID);
|
||||
if (element === null) {
|
||||
return null;
|
||||
}
|
||||
if (element.type === ElementTypeActivity) {
|
||||
return element.id;
|
||||
}
|
||||
currentID = element.parentID;
|
||||
}
|
||||
|
||||
return currentID;
|
||||
}
|
||||
|
||||
function useSelectedActivityID(): Element['id'] | null {
|
||||
const {inspectedElementID} = useContext(TreeStateContext);
|
||||
const store = useContext(StoreContext);
|
||||
return useMemo(() => {
|
||||
if (inspectedElementID === null) {
|
||||
return null;
|
||||
}
|
||||
const nearestActivityID = findNearestActivityParentID(
|
||||
inspectedElementID,
|
||||
store,
|
||||
);
|
||||
return nearestActivityID;
|
||||
}, [inspectedElementID, store]);
|
||||
}
|
||||
|
||||
export default function ActivityList({
|
||||
activities,
|
||||
}: {
|
||||
activities: $ReadOnlyArray<Element>,
|
||||
activities: $ReadOnlyArray<{id: Element['id'], depth: number}>,
|
||||
}): React$Node {
|
||||
const {inspectedElementID} = useContext(TreeStateContext);
|
||||
const {activityID, inspectedElementID} = useContext(TreeStateContext);
|
||||
const treeDispatch = useContext(TreeDispatcherContext);
|
||||
// TODO: Derive from inspected element
|
||||
const selectedActivityID = inspectedElementID;
|
||||
const store = useContext(StoreContext);
|
||||
const selectedActivityID = useSelectedActivityID();
|
||||
const {highlightHostInstance, clearHighlightHostInstance} =
|
||||
useHighlightHostInstance();
|
||||
|
||||
@@ -79,8 +119,13 @@ export default function ActivityList({
|
||||
const changeActivitySliceAction = useChangeActivitySliceAction();
|
||||
|
||||
function handleKeyDown(event: SyntheticKeyboardEvent) {
|
||||
// TODO: Implement keyboard navigation
|
||||
switch (event.key) {
|
||||
case 'Escape':
|
||||
startActivitySliceSelection(() => {
|
||||
changeActivitySliceAction(null);
|
||||
});
|
||||
event.preventDefault();
|
||||
break;
|
||||
case 'Enter':
|
||||
case ' ':
|
||||
if (inspectedElementID !== null) {
|
||||
@@ -149,25 +194,61 @@ export default function ActivityList({
|
||||
}
|
||||
|
||||
return (
|
||||
<ol
|
||||
role="listbox"
|
||||
className={styles.ActivityList}
|
||||
data-pending-activity-slice-selection={isPendingActivitySliceSelection}
|
||||
tabIndex={0}
|
||||
onKeyDown={handleKeyDown}>
|
||||
{activities.map(activity => (
|
||||
<li
|
||||
key={activity.id}
|
||||
role="option"
|
||||
aria-selected={activity.id === selectedActivityID ? 'true' : 'false'}
|
||||
className={styles.ActivityListItem}
|
||||
onClick={handleClick.bind(null, activity.id)}
|
||||
onDoubleClick={handleDoubleClick}
|
||||
onPointerOver={highlightHostInstance.bind(null, activity.id, false)}
|
||||
onPointerLeave={clearHighlightHostInstance}>
|
||||
{activity.nameProp}
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
<div className={styles.ActivityListContaier}>
|
||||
<div className={styles.ActivityListHeader}>
|
||||
{activityID !== null && (
|
||||
// TODO: Obsolete once filtered Activities are included in this list.
|
||||
<Button
|
||||
onClick={startActivitySliceSelection.bind(
|
||||
null,
|
||||
changeActivitySliceAction.bind(null, null),
|
||||
)}
|
||||
title="Back to full tree view">
|
||||
<ButtonIcon type="previous" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<ol
|
||||
role="listbox"
|
||||
className={styles.ActivityListList}
|
||||
data-pending-activity-slice-selection={isPendingActivitySliceSelection}
|
||||
tabIndex={0}
|
||||
onKeyDown={handleKeyDown}>
|
||||
{activities.map(({id, depth}) => {
|
||||
const activity = store.getElementByID(id);
|
||||
if (activity === null) {
|
||||
return null;
|
||||
}
|
||||
const name = activity.nameProp;
|
||||
if (name === null) {
|
||||
// This shouldn't actually happen. We only want to show activities with a name.
|
||||
// And hide the whole list if no named Activities are present.
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO: Filtered Activities should have dedicated styles once we include
|
||||
// filtered Activities in this list.
|
||||
return (
|
||||
<li
|
||||
key={activity.id}
|
||||
role="option"
|
||||
aria-selected={
|
||||
activity.id === selectedActivityID ? 'true' : 'false'
|
||||
}
|
||||
className={styles.ActivityListItem}
|
||||
onClick={handleClick.bind(null, activity.id)}
|
||||
onDoubleClick={handleDoubleClick}
|
||||
onPointerOver={highlightHostInstance.bind(
|
||||
null,
|
||||
activity.id,
|
||||
false,
|
||||
)}
|
||||
onPointerLeave={clearHighlightHostInstance}>
|
||||
{'\u00A0'.repeat(depth) + name}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ol>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
}
|
||||
|
||||
.ActivityList {
|
||||
flex: 0 0 var(--horizontal-resize-tree-list-percentage);
|
||||
flex: 0 0 var(--horizontal-resize-activity-list-percentage);;
|
||||
border-right: 1px solid var(--color-border);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
@@ -6,14 +6,11 @@
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
import type {Element} from 'react-devtools-shared/src/frontend/types';
|
||||
|
||||
import * as React from 'react';
|
||||
import {
|
||||
useContext,
|
||||
useEffect,
|
||||
useLayoutEffect,
|
||||
useMemo,
|
||||
useReducer,
|
||||
useRef,
|
||||
Fragment,
|
||||
@@ -44,12 +41,13 @@ import typeof {SyntheticPointerEvent} from 'react-dom-bindings/src/events/Synthe
|
||||
import SettingsModal from 'react-devtools-shared/src/devtools/views/Settings/SettingsModal';
|
||||
import SettingsModalContextToggle from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContextToggle';
|
||||
import {SettingsModalContextController} from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContext';
|
||||
import {TreeStateContext} from '../Components/TreeContext';
|
||||
|
||||
type Orientation = 'horizontal' | 'vertical';
|
||||
|
||||
type LayoutActionType =
|
||||
| 'ACTION_SET_TREE_LIST_TOGGLE'
|
||||
| 'ACTION_SET_TREE_LIST_HORIZONTAL_FRACTION'
|
||||
| 'ACTION_SET_ACTIVITY_LIST_TOGGLE'
|
||||
| 'ACTION_SET_ACTIVITY_LIST_HORIZONTAL_FRACTION'
|
||||
| 'ACTION_SET_INSPECTED_ELEMENT_TOGGLE'
|
||||
| 'ACTION_SET_INSPECTED_ELEMENT_HORIZONTAL_FRACTION'
|
||||
| 'ACTION_SET_INSPECTED_ELEMENT_VERTICAL_FRACTION';
|
||||
@@ -59,8 +57,8 @@ type LayoutAction = {
|
||||
};
|
||||
|
||||
type LayoutState = {
|
||||
treeListHidden: boolean,
|
||||
treeListHorizontalFraction: number,
|
||||
activityListHidden: boolean,
|
||||
activityListHorizontalFraction: number,
|
||||
inspectedElementHidden: boolean,
|
||||
inspectedElementHorizontalFraction: number,
|
||||
inspectedElementVerticalFraction: number,
|
||||
@@ -97,7 +95,7 @@ function ToggleUniqueSuspenders() {
|
||||
);
|
||||
}
|
||||
|
||||
function ToggleTreeList({
|
||||
function ToggleActivityList({
|
||||
dispatch,
|
||||
state,
|
||||
}: {
|
||||
@@ -108,13 +106,15 @@ function ToggleTreeList({
|
||||
<Button
|
||||
onClick={() =>
|
||||
dispatch({
|
||||
type: 'ACTION_SET_TREE_LIST_TOGGLE',
|
||||
type: 'ACTION_SET_ACTIVITY_LIST_TOGGLE',
|
||||
payload: null,
|
||||
})
|
||||
}
|
||||
title={state.treeListHidden ? 'Show Tree List' : 'Hide Tree List'}>
|
||||
title={
|
||||
state.activityListHidden ? 'Show Activity List' : 'Hide Activity List'
|
||||
}>
|
||||
<ButtonIcon
|
||||
type={state.treeListHidden ? 'panel-left-open' : 'panel-left-close'}
|
||||
type={state.activityListHidden ? 'panel-left-open' : 'panel-left-close'}
|
||||
/>
|
||||
</Button>
|
||||
);
|
||||
@@ -272,17 +272,6 @@ function SynchronizedScrollContainer({
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: Get this from the store directly.
|
||||
// The backend needs to keep a separate tree so that resuspending keeps Activity around.
|
||||
function useActivities(): $ReadOnlyArray<Element> {
|
||||
const activities = useMemo(() => {
|
||||
const items: Array<Element> = [];
|
||||
return items;
|
||||
}, []);
|
||||
|
||||
return activities;
|
||||
}
|
||||
|
||||
function SuspenseTab(_: {}) {
|
||||
const store = useContext(StoreContext);
|
||||
const {hideSettings} = useContext(OptionsContext);
|
||||
@@ -292,14 +281,14 @@ function SuspenseTab(_: {}) {
|
||||
initLayoutState,
|
||||
);
|
||||
|
||||
const activities = useActivities();
|
||||
const {activities} = useContext(TreeStateContext);
|
||||
// If there are no named Activity boundaries, we don't have any tree list and we should hide
|
||||
// both the panel and the button to toggle it.
|
||||
const treeListDisabled = activities.length === 0;
|
||||
const activityListDisabled = activities.length === 0;
|
||||
|
||||
const wrapperTreeRef = useRef<null | HTMLElement>(null);
|
||||
const resizeTreeRef = useRef<null | HTMLElement>(null);
|
||||
const resizeTreeListRef = useRef<null | HTMLElement>(null);
|
||||
const resizeActivityListRef = useRef<null | HTMLElement>(null);
|
||||
|
||||
// TODO: We'll show the recently inspected element in this tab when it should probably
|
||||
// switch to the nearest Suspense boundary when we switch into this tab.
|
||||
@@ -308,8 +297,8 @@ function SuspenseTab(_: {}) {
|
||||
inspectedElementHidden,
|
||||
inspectedElementHorizontalFraction,
|
||||
inspectedElementVerticalFraction,
|
||||
treeListHidden,
|
||||
treeListHorizontalFraction,
|
||||
activityListHidden,
|
||||
activityListHorizontalFraction,
|
||||
} = state;
|
||||
|
||||
useLayoutEffect(() => {
|
||||
@@ -328,12 +317,12 @@ function SuspenseTab(_: {}) {
|
||||
inspectedElementVerticalFraction * 100,
|
||||
);
|
||||
|
||||
const resizeTreeListElement = resizeTreeListRef.current;
|
||||
const resizeActivityListElement = resizeActivityListRef.current;
|
||||
setResizeCSSVariable(
|
||||
resizeTreeListElement,
|
||||
'tree-list',
|
||||
resizeActivityListElement,
|
||||
'activity-list',
|
||||
'horizontal',
|
||||
treeListHorizontalFraction * 100,
|
||||
activityListHorizontalFraction * 100,
|
||||
);
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
@@ -344,8 +333,8 @@ function SuspenseTab(_: {}) {
|
||||
inspectedElementHidden,
|
||||
inspectedElementHorizontalFraction,
|
||||
inspectedElementVerticalFraction,
|
||||
treeListHidden,
|
||||
treeListHorizontalFraction,
|
||||
activityListHidden,
|
||||
activityListHorizontalFraction,
|
||||
}),
|
||||
);
|
||||
}, 500);
|
||||
@@ -355,8 +344,8 @@ function SuspenseTab(_: {}) {
|
||||
inspectedElementHidden,
|
||||
inspectedElementHorizontalFraction,
|
||||
inspectedElementVerticalFraction,
|
||||
treeListHidden,
|
||||
treeListHorizontalFraction,
|
||||
activityListHidden,
|
||||
activityListHorizontalFraction,
|
||||
]);
|
||||
|
||||
const onResizeStart = (event: SyntheticPointerEvent) => {
|
||||
@@ -420,14 +409,14 @@ function SuspenseTab(_: {}) {
|
||||
}
|
||||
};
|
||||
|
||||
const onResizeTreeList = (event: SyntheticPointerEvent) => {
|
||||
const onResizeActivityList = (event: SyntheticPointerEvent) => {
|
||||
const element = event.currentTarget;
|
||||
const isResizing = element.hasPointerCapture(event.pointerId);
|
||||
if (!isResizing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const resizeElement = resizeTreeListRef.current;
|
||||
const resizeElement = resizeActivityListRef.current;
|
||||
const wrapperElement = resizeTreeRef.current;
|
||||
|
||||
if (wrapperElement === null || resizeElement === null) {
|
||||
@@ -443,11 +432,11 @@ function SuspenseTab(_: {}) {
|
||||
const currentMousePosition =
|
||||
orientation === 'horizontal' ? event.clientX - left : event.clientY - top;
|
||||
|
||||
const boundaryMin = MINIMUM_TREE_LIST_SIZE;
|
||||
const boundaryMin = MINIMUM_ACTIVITY_LIST_SIZE;
|
||||
const boundaryMax =
|
||||
orientation === 'horizontal'
|
||||
? width - MINIMUM_TREE_LIST_SIZE
|
||||
: height - MINIMUM_TREE_LIST_SIZE;
|
||||
? width - MINIMUM_ACTIVITY_LIST_SIZE
|
||||
: height - MINIMUM_ACTIVITY_LIST_SIZE;
|
||||
|
||||
const isMousePositionInBounds =
|
||||
currentMousePosition > boundaryMin && currentMousePosition < boundaryMax;
|
||||
@@ -455,10 +444,15 @@ function SuspenseTab(_: {}) {
|
||||
if (isMousePositionInBounds) {
|
||||
const resizedElementDimension =
|
||||
orientation === 'horizontal' ? width : height;
|
||||
const actionType = 'ACTION_SET_TREE_LIST_HORIZONTAL_FRACTION';
|
||||
const actionType = 'ACTION_SET_ACTIVITY_LIST_HORIZONTAL_FRACTION';
|
||||
const percentage = (currentMousePosition / resizedElementDimension) * 100;
|
||||
|
||||
setResizeCSSVariable(resizeElement, 'tree-list', orientation, percentage);
|
||||
setResizeCSSVariable(
|
||||
resizeElement,
|
||||
'activity-list',
|
||||
orientation,
|
||||
percentage,
|
||||
);
|
||||
|
||||
dispatch({
|
||||
type: actionType,
|
||||
@@ -473,19 +467,21 @@ function SuspenseTab(_: {}) {
|
||||
<SettingsModalContextController>
|
||||
<div className={styles.SuspenseTab} ref={wrapperTreeRef}>
|
||||
<div className={styles.TreeWrapper} ref={resizeTreeRef}>
|
||||
{treeListDisabled ? null : (
|
||||
{activityListDisabled ? null : (
|
||||
<div
|
||||
className={styles.ActivityList}
|
||||
hidden={treeListHidden}
|
||||
ref={resizeTreeListRef}>
|
||||
hidden={activityListHidden}
|
||||
ref={resizeActivityListRef}>
|
||||
<ActivityList activities={activities} />
|
||||
</div>
|
||||
)}
|
||||
{treeListDisabled ? null : (
|
||||
<div className={styles.ResizeBarWrapper} hidden={treeListHidden}>
|
||||
{activityListDisabled ? null : (
|
||||
<div
|
||||
className={styles.ResizeBarWrapper}
|
||||
hidden={activityListHidden}>
|
||||
<div
|
||||
onPointerDown={onResizeStart}
|
||||
onPointerMove={onResizeTreeList}
|
||||
onPointerMove={onResizeActivityList}
|
||||
onPointerUp={onResizeEnd}
|
||||
className={styles.ResizeBar}
|
||||
/>
|
||||
@@ -493,10 +489,10 @@ function SuspenseTab(_: {}) {
|
||||
)}
|
||||
<div className={styles.TreeView}>
|
||||
<header className={styles.SuspenseTreeViewHeader}>
|
||||
{treeListDisabled ? (
|
||||
{activityListDisabled ? (
|
||||
<div />
|
||||
) : (
|
||||
<ToggleTreeList dispatch={dispatch} state={state} />
|
||||
<ToggleActivityList dispatch={dispatch} state={state} />
|
||||
)}
|
||||
{store.supportsClickToInspect && (
|
||||
<Fragment>
|
||||
@@ -559,19 +555,19 @@ function SuspenseTab(_: {}) {
|
||||
const LOCAL_STORAGE_KEY = 'React::DevTools::SuspenseTab::layout';
|
||||
const VERTICAL_TREE_MODE_MAX_WIDTH = 600;
|
||||
const MINIMUM_TREE_SIZE = 100;
|
||||
const MINIMUM_TREE_LIST_SIZE = 100;
|
||||
const MINIMUM_ACTIVITY_LIST_SIZE = 100;
|
||||
|
||||
function layoutReducer(state: LayoutState, action: LayoutAction): LayoutState {
|
||||
switch (action.type) {
|
||||
case 'ACTION_SET_TREE_LIST_TOGGLE':
|
||||
case 'ACTION_SET_ACTIVITY_LIST_TOGGLE':
|
||||
return {
|
||||
...state,
|
||||
treeListHidden: !state.treeListHidden,
|
||||
activityListHidden: !state.activityListHidden,
|
||||
};
|
||||
case 'ACTION_SET_TREE_LIST_HORIZONTAL_FRACTION':
|
||||
case 'ACTION_SET_ACTIVITY_LIST_HORIZONTAL_FRACTION':
|
||||
return {
|
||||
...state,
|
||||
treeListHorizontalFraction: action.payload,
|
||||
activityListHorizontalFraction: action.payload,
|
||||
};
|
||||
case 'ACTION_SET_INSPECTED_ELEMENT_TOGGLE':
|
||||
return {
|
||||
@@ -597,8 +593,8 @@ function initLayoutState(): LayoutState {
|
||||
let inspectedElementHidden = false;
|
||||
let inspectedElementHorizontalFraction = 0.65;
|
||||
let inspectedElementVerticalFraction = 0.5;
|
||||
let treeListHidden = false;
|
||||
let treeListHorizontalFraction = 0.35;
|
||||
let activityListHidden = false;
|
||||
let activityListHorizontalFraction = 0.35;
|
||||
|
||||
try {
|
||||
let data = localStorageGetItem(LOCAL_STORAGE_KEY);
|
||||
@@ -608,8 +604,8 @@ function initLayoutState(): LayoutState {
|
||||
inspectedElementHorizontalFraction =
|
||||
data.inspectedElementHorizontalFraction;
|
||||
inspectedElementVerticalFraction = data.inspectedElementVerticalFraction;
|
||||
treeListHidden = data.treeListHidden;
|
||||
treeListHorizontalFraction = data.treeListHorizontalFraction;
|
||||
activityListHidden = data.activityListHidden;
|
||||
activityListHorizontalFraction = data.activityListHorizontalFraction;
|
||||
}
|
||||
} catch (error) {}
|
||||
|
||||
@@ -617,8 +613,8 @@ function initLayoutState(): LayoutState {
|
||||
inspectedElementHidden,
|
||||
inspectedElementHorizontalFraction,
|
||||
inspectedElementVerticalFraction,
|
||||
treeListHidden,
|
||||
treeListHorizontalFraction,
|
||||
activityListHidden,
|
||||
activityListHorizontalFraction,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -634,7 +630,7 @@ function getTreeOrientation(
|
||||
|
||||
function setResizeCSSVariable(
|
||||
resizeElement: null | HTMLElement,
|
||||
name: 'tree' | 'tree-list',
|
||||
name: 'tree' | 'activity-list',
|
||||
orientation: null | Orientation,
|
||||
percentage: number,
|
||||
): void {
|
||||
|
||||
@@ -77,13 +77,13 @@ function Root({children}: {children: React.Node}): React.Node {
|
||||
|
||||
export default function Segments(): React.Node {
|
||||
return (
|
||||
<React.Activity name="/" mode="visible">
|
||||
<React.Activity name="root" mode="visible">
|
||||
<Root>
|
||||
<React.Activity name="/outer/" mode="visible">
|
||||
<React.Activity name="outer" mode="visible">
|
||||
<OuterSegment>
|
||||
<React.Activity name="/outer/inner" mode="visible">
|
||||
<React.Activity name="inner" mode="visible">
|
||||
<InnerSegment>
|
||||
<React.Activity name="/outer/inner/page" mode="visible">
|
||||
<React.Activity name="slot" mode="visible">
|
||||
<Page />
|
||||
</React.Activity>
|
||||
</InnerSegment>
|
||||
|
||||
Reference in New Issue
Block a user