mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-10-30 14:49:14 +00:00
97 lines
3.1 KiB
TypeScript
97 lines
3.1 KiB
TypeScript
import {useRef} from 'react';
|
|
import styled from '@emotion/styled';
|
|
|
|
import Panel from 'sentry/components/panels/panel';
|
|
import Placeholder from 'sentry/components/placeholder';
|
|
import {
|
|
MajorGridlines,
|
|
MinorGridlines,
|
|
} from 'sentry/components/replays/breadcrumbs/gridlines';
|
|
import ReplayTimelineEvents from 'sentry/components/replays/breadcrumbs/replayTimelineEvents';
|
|
import Stacked from 'sentry/components/replays/breadcrumbs/stacked';
|
|
import {TimelineScrubber} from 'sentry/components/replays/player/scrubber';
|
|
import {useTimelineScrubberMouseTracking} from 'sentry/components/replays/player/useScrubberMouseTracking';
|
|
import {useReplayContext} from 'sentry/components/replays/replayContext';
|
|
import {divide} from 'sentry/components/replays/utils';
|
|
import toPercent from 'sentry/utils/number/toPercent';
|
|
import {useDimensions} from 'sentry/utils/useDimensions';
|
|
import useProjectFromId from 'sentry/utils/useProjectFromId';
|
|
|
|
export default function ReplayTimeline() {
|
|
const {replay, currentTime, timelineScale} = useReplayContext();
|
|
const projectSlug = useProjectFromId({
|
|
project_id: replay?.getReplay().project_id,
|
|
})?.slug;
|
|
|
|
const panelRef = useRef<HTMLDivElement>(null);
|
|
const mouseTrackingProps = useTimelineScrubberMouseTracking(
|
|
{elem: panelRef},
|
|
timelineScale
|
|
);
|
|
|
|
const stackedRef = useRef<HTMLDivElement>(null);
|
|
const {width} = useDimensions<HTMLDivElement>({elementRef: stackedRef});
|
|
|
|
if (!replay) {
|
|
return <Placeholder height="20px" />;
|
|
}
|
|
|
|
const durationMs = replay.getDurationMs();
|
|
const startTimestampMs = replay.getStartTimestampMs();
|
|
const chapterFrames = replay.getChapterFrames();
|
|
|
|
// timeline is in the middle
|
|
const initialTranslate = 0.5 / timelineScale;
|
|
const percentComplete = divide(currentTime, durationMs);
|
|
|
|
const starting = percentComplete < initialTranslate;
|
|
const ending = percentComplete + initialTranslate > 1;
|
|
|
|
const translate = () => {
|
|
if (starting) {
|
|
return 0;
|
|
}
|
|
if (ending) {
|
|
return initialTranslate - (1 - initialTranslate);
|
|
}
|
|
return initialTranslate - (currentTime > durationMs ? 1 : percentComplete);
|
|
};
|
|
|
|
return (
|
|
<VisiblePanel ref={panelRef} {...mouseTrackingProps}>
|
|
<Stacked
|
|
style={{
|
|
width: `${toPercent(timelineScale)}`,
|
|
transform: `translate(${toPercent(translate())}, 0%)`,
|
|
}}
|
|
ref={stackedRef}
|
|
>
|
|
<MinorGridlines durationMs={durationMs} width={width} />
|
|
<MajorGridlines durationMs={durationMs} width={width} />
|
|
<TimelineScrubber />
|
|
<TimelineEventsContainer>
|
|
<ReplayTimelineEvents
|
|
durationMs={durationMs}
|
|
frames={chapterFrames}
|
|
projectSlug={projectSlug}
|
|
startTimestampMs={startTimestampMs}
|
|
width={width}
|
|
/>
|
|
</TimelineEventsContainer>
|
|
</Stacked>
|
|
</VisiblePanel>
|
|
);
|
|
}
|
|
|
|
const VisiblePanel = styled(Panel)`
|
|
margin: 0;
|
|
border: 0;
|
|
overflow: hidden;
|
|
background: ${p => p.theme.translucentInnerBorder};
|
|
`;
|
|
|
|
const TimelineEventsContainer = styled('div')`
|
|
padding-top: 10px;
|
|
padding-bottom: 10px;
|
|
`;
|