Yarn workspaces

Summary:
1) moved "sonar/desktop/src" to "sonar/desktop/app/src", so "app" is now a separate package containing the core Flipper app code
2) Configured yarn workspaces with the root in "sonar/desktop": app, static, pkg, doctor, headless-tests. Plugins are not included for now, I plan to do this later.

Reviewed By: jknoxville

Differential Revision: D20535782

fbshipit-source-id: 600b2301960f37c7d72166e0d04eba462bec9fc1
This commit is contained in:
Anton Nikolaev
2020-03-20 13:31:37 -07:00
committed by Facebook GitHub Bot
parent 676d7bbd24
commit 863f89351e
340 changed files with 1635 additions and 294 deletions

View File

@@ -0,0 +1,242 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {Component} from 'react';
import styled from '@emotion/styled';
import Text from './Text';
import FlexRow from './FlexRow';
import {colors} from './colors';
import React from 'react';
type DataPoint = {
time: number;
color?: string;
label: string;
key: string;
};
type Props = {
onClick?: (keys: Array<string>) => void;
selected?: string | null | undefined;
points: DataPoint[];
lineHeight: number;
maxGap: number;
};
type MouseEventHandler = (
event: React.MouseEvent<HTMLDivElement, MouseEvent>,
) => void;
const Markers = styled.div<{totalTime: number}>(props => ({
position: 'relative',
margin: 10,
height: props.totalTime,
'::before': {
content: '""',
width: 1,
borderLeft: `1px dotted ${colors.light30}`,
position: 'absolute',
top: 5,
bottom: 20,
left: 5,
},
}));
Markers.displayName = 'MarkerTimeline:Markers';
const Point = styled(FlexRow)<{
positionY: number;
onClick: MouseEventHandler | undefined;
number: number | undefined;
threadColor: string;
selected: boolean;
cut: boolean;
}>(props => ({
position: 'absolute',
top: props.positionY,
left: 0,
right: 10,
cursor: props.onClick ? 'pointer' : 'default',
borderRadius: 3,
alignItems: 'flex-start',
lineHeight: '16px',
':hover': {
background: `linear-gradient(to top, rgba(255,255,255,0) 0, #ffffff 10px)`,
paddingBottom: 5,
zIndex: 2,
'> span': {
whiteSpace: 'initial',
},
},
'::before': {
position: 'relative',
textAlign: 'center',
fontSize: 8,
fontWeight: 500,
content: props.number ? `'${props.number}'` : '""',
display: 'inline-block',
width: 9,
height: 9,
flexShrink: 0,
color: 'rgba(0,0,0,0.4)',
lineHeight: '9px',
borderRadius: '999em',
border: '1px solid rgba(0,0,0,0.2)',
backgroundColor: props.threadColor,
marginRight: 6,
zIndex: 3,
boxShadow: props.selected
? `0 0 0 2px ${colors.macOSTitleBarIconSelected}`
: undefined,
},
'::after': {
content: props.cut ? '""' : undefined,
position: 'absolute',
width: 11,
top: -20,
left: 0,
height: 2,
background: colors.white,
borderTop: `1px solid ${colors.light30}`,
borderBottom: `1px solid ${colors.light30}`,
transform: `skewY(-10deg)`,
},
}));
Point.displayName = 'MakerTimeline:Point';
const Time = styled.span({
color: colors.light30,
fontWeight: 300,
marginRight: 4,
marginTop: -2,
});
Time.displayName = 'MakerTimeline:Time';
const Code = styled(Text)({
overflow: 'hidden',
textOverflow: 'ellipsis',
marginTop: -1,
});
Code.displayName = 'MakerTimeline:Code';
type TimePoint = {
timestamp: number;
markerNames: Array<string>;
markerKeys: Array<string>;
isCut: boolean;
positionY: number;
color: string;
};
type State = {
timePoints: Array<TimePoint>;
};
export default class MarkerTimeline extends Component<Props, State> {
static defaultProps = {
lineHeight: 22,
maxGap: 100,
};
static getDerivedStateFromProps(props: Props) {
const sortedMarkers: [number, DataPoint[]][] = Array.from(
props.points
.reduce((acc: Map<number, DataPoint[]>, cv: DataPoint) => {
const list = acc.get(cv.time);
if (list) {
list.push(cv);
} else {
acc.set(cv.time, [cv]);
}
return acc;
}, new Map())
.entries(),
).sort((a, b) => a[0] - b[0]);
const smallestGap = sortedMarkers.reduce((acc, cv, i, arr) => {
if (i > 0) {
return Math.min(acc, cv[0] - arr[i - 1][0]);
} else {
return acc;
}
}, Infinity);
let positionY = 0;
const timePoints: Array<TimePoint> = [];
for (let i = 0; i < sortedMarkers.length; i++) {
const [timestamp, points] = sortedMarkers[i];
let isCut = false;
const color = sortedMarkers[i][1][0].color || colors.white;
if (i > 0) {
const relativeTimestamp = timestamp - sortedMarkers[i - 1][0];
const gap = (relativeTimestamp / smallestGap) * props.lineHeight;
if (gap > props.maxGap) {
positionY += props.maxGap;
isCut = true;
} else {
positionY += gap;
}
}
timePoints.push({
timestamp,
markerNames: points.map(p => p.label),
markerKeys: points.map(p => p.key),
positionY,
isCut,
color,
});
}
return {timePoints};
}
state: State = {
timePoints: [],
};
render() {
const {timePoints} = this.state;
const {onClick} = this.props;
if (!this.props.points || this.props.points.length === 0) {
return null;
}
return (
<Markers
totalTime={
timePoints[timePoints.length - 1].positionY + this.props.lineHeight
}>
{timePoints.map((p: TimePoint, i: number) => {
return (
<Point
key={i}
threadColor={p.color}
cut={p.isCut}
positionY={p.positionY}
onClick={onClick ? () => onClick(p.markerKeys) : undefined}
selected={
this.props.selected
? p.markerKeys.includes(this.props.selected)
: false
}
number={
p.markerNames.length > 1 ? p.markerNames.length : undefined
}>
<Time>{p.timestamp}ms</Time>{' '}
<Code code>{p.markerNames.join(', ')}</Code>
</Point>
);
})}
</Markers>
);
}
}