mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Added commit time filter
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
.Background {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: var(--color-modal-background);
|
||||
}
|
||||
|
||||
.Modal {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
display: inline-block;
|
||||
background-color: var(--color-background);
|
||||
padding: 1rem;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.Input {
|
||||
width: 40px;
|
||||
background: none;
|
||||
border: 1px solid transparent;
|
||||
color: var(--color-attribute-editable-value);
|
||||
border-radius: 0.125rem;
|
||||
font-family: var(--font-family-monospace);
|
||||
font-size: var(--font-size-monospace-normal);
|
||||
}
|
||||
.Input:focus {
|
||||
background-color: var(--color-button-background-focus);
|
||||
outline: none;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// @flow
|
||||
|
||||
import React, { useCallback, useEffect, useRef } from 'react';
|
||||
import { useLocalStorage, useModalDismissSignal } from '../hooks';
|
||||
|
||||
import styles from './FilterModal.css';
|
||||
|
||||
type Props = {|
|
||||
dismissModal: Function,
|
||||
|};
|
||||
|
||||
export default function FilterModal({ dismissModal }: Props) {
|
||||
const [isEnabled, setIsEnabled] = useLocalStorage<boolean>(
|
||||
'minCommitDurationFilterEnabled',
|
||||
false
|
||||
);
|
||||
const [value, setValue] = useLocalStorage<number>(
|
||||
'minCommitDurationFilter',
|
||||
0
|
||||
);
|
||||
|
||||
const handleNumberChange = useCallback(
|
||||
({ currentTarget }) => {
|
||||
const newValue = parseInt(currentTarget.value, 10);
|
||||
setValue(Number.isNaN(newValue) || newValue <= 0 ? 0 : newValue);
|
||||
},
|
||||
[setValue]
|
||||
);
|
||||
|
||||
const handleEnabledChange = useCallback(
|
||||
({ currentTarget }) => {
|
||||
setIsEnabled(currentTarget.checked);
|
||||
if (currentTarget.checked) {
|
||||
if (inputRef.current !== null) {
|
||||
inputRef.current.focus();
|
||||
}
|
||||
}
|
||||
},
|
||||
[setIsEnabled]
|
||||
);
|
||||
|
||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||
const modalRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
useModalDismissSignal(modalRef, dismissModal);
|
||||
|
||||
useEffect(() => {
|
||||
if (inputRef.current !== null) {
|
||||
inputRef.current.focus();
|
||||
}
|
||||
}, [inputRef]);
|
||||
|
||||
return (
|
||||
<div className={styles.Background}>
|
||||
<div className={styles.Modal} ref={modalRef}>
|
||||
<label>
|
||||
<input
|
||||
checked={isEnabled}
|
||||
onChange={handleEnabledChange}
|
||||
type="checkbox"
|
||||
/>{' '}
|
||||
Hide commits below
|
||||
</label>{' '}
|
||||
<input
|
||||
className={styles.Input}
|
||||
onChange={handleNumberChange}
|
||||
ref={inputRef}
|
||||
type="number"
|
||||
value={value}
|
||||
/>{' '}
|
||||
(ms)
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
}
|
||||
|
||||
.Content {
|
||||
position: relative;
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
// @flow
|
||||
|
||||
import React, { useContext, useState } from 'react';
|
||||
import React, { useCallback, useContext, useState } from 'react';
|
||||
import { ProfilerContext, ProfilerContextController } from './ProfilerContext';
|
||||
import Button from '../Button';
|
||||
import ButtonIcon from '../ButtonIcon';
|
||||
import TabBar from '../TabBar';
|
||||
import FilterModal from './FilterModal';
|
||||
import RecordToggle from './RecordToggle';
|
||||
|
||||
import styles from './Profiler.css';
|
||||
@@ -22,6 +23,10 @@ export default function ProfilerOuter(_: Props) {
|
||||
function ProfilerInner(_: Props) {
|
||||
const { hasProfilingData, isProfiling } = useContext(ProfilerContext);
|
||||
const [tab, setTab] = useState('flame-chart');
|
||||
const [isFilterModalShowing, setIsFilterModalShowing] = useState(false);
|
||||
|
||||
const showFilterModal = useCallback(() => setIsFilterModalShowing(true));
|
||||
const dismissFilterModal = useCallback(() => setIsFilterModalShowing(false));
|
||||
|
||||
let view = null;
|
||||
if (isProfiling) {
|
||||
@@ -52,12 +57,16 @@ function ProfilerInner(_: Props) {
|
||||
tabs={tabs}
|
||||
/>
|
||||
<div className={styles.Spacer} />
|
||||
<Button disabled title="Filter commits by duration">
|
||||
{/* TODO (profiling) Wire up filter button */}
|
||||
<Button onClick={showFilterModal} title="Filter commits by duration">
|
||||
<ButtonIcon type="filter" />
|
||||
</Button>
|
||||
</div>
|
||||
<div className={styles.Content}>{view}</div>
|
||||
<div className={styles.Content}>
|
||||
{view}
|
||||
{isFilterModalShowing && (
|
||||
<FilterModal dismissModal={dismissFilterModal} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -77,13 +86,11 @@ const NoProfilingData = () => (
|
||||
</div>
|
||||
);
|
||||
|
||||
const RecortdingInProgress = () => {
|
||||
return (
|
||||
<div className={styles.Column}>
|
||||
<div className={styles.Header}>Profiling is in progress...</div>
|
||||
<div className={styles.Row}>
|
||||
Click the record button <RecordToggle /> to stop recording.
|
||||
</div>
|
||||
const RecortdingInProgress = () => (
|
||||
<div className={styles.Column}>
|
||||
<div className={styles.Header}>Profiling is in progress...</div>
|
||||
<div className={styles.Row}>
|
||||
Click the record button <RecordToggle /> to stop recording.
|
||||
</div>
|
||||
);
|
||||
};
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -141,6 +141,7 @@ function updateThemeVariables(theme: Theme): void {
|
||||
updateStyleHelper(theme, 'color-dimmest');
|
||||
updateStyleHelper(theme, 'color-jsx-arrow-brackets');
|
||||
updateStyleHelper(theme, 'color-jsx-arrow-brackets-inverted');
|
||||
updateStyleHelper(theme, 'color-modal-background');
|
||||
updateStyleHelper(theme, 'color-record-active');
|
||||
updateStyleHelper(theme, 'color-record-hover');
|
||||
updateStyleHelper(theme, 'color-record-inactive');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @flow
|
||||
|
||||
import { useCallback, useLayoutEffect, useState } from 'react';
|
||||
import { useCallback, useEffect, useLayoutEffect, useState } from 'react';
|
||||
|
||||
// Forked from https://usehooks.com/useLocalStorage/
|
||||
export function useLocalStorage<T>(
|
||||
@@ -52,3 +52,34 @@ export function useLocalStorage<T>(
|
||||
|
||||
return [storedValue, setValue];
|
||||
}
|
||||
|
||||
export function useModalDismissSignal(
|
||||
modalRef: React$Ref<any>,
|
||||
dismissCallback: Function
|
||||
): void {
|
||||
useEffect(() => {
|
||||
const handleKeyDown = ({ key }: any) => {
|
||||
if (key === 'Escape') {
|
||||
dismissCallback();
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseOrTouch = ({ target }: any) => {
|
||||
// $FlowFixMe
|
||||
if (modalRef.current !== null && !modalRef.current.contains(target)) {
|
||||
dismissCallback();
|
||||
}
|
||||
};
|
||||
|
||||
const body = ((document.body: any): HTMLBodyElement);
|
||||
body.addEventListener('keydown', handleKeyDown);
|
||||
body.addEventListener('mousedown', handleMouseOrTouch);
|
||||
body.addEventListener('touchstart', handleMouseOrTouch);
|
||||
|
||||
return () => {
|
||||
body.removeEventListener('keydown', handleKeyDown);
|
||||
body.removeEventListener('mousedown', handleMouseOrTouch);
|
||||
body.removeEventListener('touchstart', handleMouseOrTouch);
|
||||
};
|
||||
}, [modalRef, dismissCallback]);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
--light-color-dimmest: #eff0f1;
|
||||
--light-color-jsx-arrow-brackets: #333333;
|
||||
--light-color-jsx-arrow-brackets-inverted: rgba(255, 255, 255, 0.7);
|
||||
--light-color-modal-background: rgba(255, 255, 255, 0.25);
|
||||
--light-color-record-active: #fc3a4b;
|
||||
--light-color-record-hover: #000000;
|
||||
--light-color-record-inactive: #cfd1d5;
|
||||
@@ -52,6 +53,7 @@
|
||||
--dark-color-dimmest: #4f5766;
|
||||
--dark-color-jsx-arrow-brackets: #777d88;
|
||||
--dark-color-jsx-arrow-brackets-inverted: rgba(255, 255, 255, 0.7);
|
||||
--dark-color-modal-background: rgba(0, 0, 0, 0.25);
|
||||
--dark-color-record-active: #fc3a4b;
|
||||
--dark-color-record-hover: #ffffff;
|
||||
--dark-color-record-inactive: #777d88;
|
||||
|
||||
Reference in New Issue
Block a user