1- import React from "react"
1+ import React , { useRef } from "react"
22import range from "lodash/range"
33import { styled } from "@material-ui/core/styles"
44import useColors from "../../hooks/use-colors"
55import TimeStamp from "../TimeStamp"
6+ import {
7+ useTimeCursorTime ,
8+ useSetTimeCursorTime ,
9+ } from "../../hooks/use-time-cursor-time"
10+ import useRootAudioElm from "../../hooks/use-root-audio-elm"
11+ import useEventCallback from "use-event-callback"
612
713import { formatTime } from "../../utils/format-time"
814
@@ -11,6 +17,7 @@ const Container = styled("div")(({ width, themeColors }) => ({
1117 overflow : "hidden" ,
1218 position : "relative" ,
1319 height : 64 ,
20+ cursor : "pointer" ,
1421 borderBottom : `1px solid ${ themeColors . Selection } ` ,
1522 color : themeColors . fg ,
1623} ) )
@@ -21,13 +28,25 @@ const TimeText = styled("div")(({ x, faded }) => ({
2128 fontSize : 12 ,
2229 fontVariantNumeric : "tabular-nums" ,
2330 position : "absolute" ,
31+ top : 16 ,
2432 left : x ,
2533 borderLeft : "1px solid rgba(255,255,255,0.5)" ,
2634 paddingLeft : 4 ,
2735 whiteSpace : "pre-wrap" ,
2836 opacity : faded ? 0.25 : 0.75 ,
2937} ) )
3038
39+ const TimeCursor = styled ( "div" ) ( ( { left, themeColors } ) => ( {
40+ position : "absolute" ,
41+ width : 0 ,
42+ height : 0 ,
43+ top : 0 ,
44+ left : left - 6 ,
45+ borderLeft : "8px solid transparent" ,
46+ borderRight : "8px solid transparent" ,
47+ borderTop : `12px solid ${ themeColors . green } ` ,
48+ } ) )
49+
3150const Svg = styled ( "svg" ) ( {
3251 position : "absolute" ,
3352 left : 0 ,
@@ -43,6 +62,7 @@ export const Timeline = ({
4362 gridLineMetrics,
4463 onClickTimestamp,
4564 onRemoveTimestamp,
65+ timeCursorTime : timeCursorTimeProp ,
4666} ) => {
4767 const themeColors = useColors ( )
4868 const visibleDuration = visibleTimeEnd - visibleTimeStart
@@ -51,15 +71,39 @@ export const Timeline = ({
5171 const timeTextTimes = range ( timeTextCount ) . map (
5272 ( i ) => visibleTimeStart + ( visibleDuration / timeTextCount ) * i
5373 )
74+ const recoilTimeCursorTime = useTimeCursorTime ( )
75+ const setTimeCursorTime = useSetTimeCursorTime ( )
76+ const [ rootAudioElm ] = useRootAudioElm ( )
77+ const timeCursorTime =
78+ timeCursorTimeProp === undefined ? recoilTimeCursorTime : timeCursorTimeProp
5479
5580 const {
5681 numberOfMajorGridLines,
5782 majorGridLinePixelOffset,
5883 majorGridLinePixelDistance,
5984 } = gridLineMetrics
6085
86+ const containerRef = useRef ( )
87+
88+ const onClickTimeline = useEventCallback ( ( e ) => {
89+ if ( ! rootAudioElm ) return
90+ const { clientX } = e
91+ const pxDistanceFromStart =
92+ clientX - containerRef . current . getBoundingClientRect ( ) . left
93+ const time =
94+ ( pxDistanceFromStart / width ) * ( visibleTimeEnd - visibleTimeStart ) +
95+ visibleTimeStart
96+ rootAudioElm . currentTime = time / 1000
97+ setTimeCursorTime ( time )
98+ } )
99+
61100 return (
62- < Container themeColors = { themeColors } width = { width } >
101+ < Container
102+ ref = { containerRef }
103+ themeColors = { themeColors }
104+ width = { width }
105+ onClick = { rootAudioElm ? onClickTimeline : undefined }
106+ >
63107 { range ( timeTextCount ) . map ( ( timeTextIndex ) => (
64108 < TimeText
65109 key = { timeTextIndex }
@@ -102,6 +146,12 @@ export const Timeline = ({
102146 />
103147 )
104148 } ) }
149+ { timeCursorTime !== undefined && (
150+ < TimeCursor
151+ themeColors = { themeColors }
152+ left = { ( ( timeCursorTime - visibleTimeStart ) / visibleDuration ) * width }
153+ />
154+ ) }
105155 </ Container >
106156 )
107157}
0 commit comments