Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: updated timestamps ui #2496

Merged
merged 1 commit into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions src/components/mindset/components/MediaPlayer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,22 +116,18 @@ const MediaPlayerComponent = ({ mediaUrl }: Props) => {
if (!isSeeking) {
const currentTime = progress.playedSeconds

setPlayingTime(currentTime)

return

const edge = findCurrentEdge(edges, currentTime)

if (edge) {
setActiveEdge(edge)
} else {
setActiveEdge(null)
}

// find playing link and set it to state
}
}

console.log(handleProgress)

const handleReady = () => {
if (playerRef) {
setStatus('ready')
Expand Down Expand Up @@ -167,6 +163,7 @@ const MediaPlayerComponent = ({ mediaUrl }: Props) => {
onError={handleError}
onPause={handlePause}
onPlay={handlePlay}
onProgress={handleProgress}
onReady={handleReady}
playing={isPlaying}
url={mediaUrl || ''}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import clsx from 'clsx'
import { useEffect, useState } from 'react'
import { useEffect, useRef, useState } from 'react'
import styled from 'styled-components'
import { Flex } from '~/components/common/Flex'
import { usePlayerStore } from '~/stores/usePlayerStore'
import { colors } from '~/utils'
import { secondsToMediaTime } from '~/utils/secondsToMediaTime'
Expand Down Expand Up @@ -32,10 +33,14 @@ type TranscriptData = {

export const Viewer = ({ transcriptString }: Props) => {
const [currentTime, setCurrentTime] = useState(0)
const [userScrolling, setUserScrolling] = useState(false)
const { playerRef } = usePlayerStore((s) => s)
const cleaned = transcriptString.replace(/^["']|["']$/g, '')

const transcriptData: TranscriptData[] = JSON.parse(cleaned)
const activeRef = useRef<HTMLDivElement | null>(null)
const wrapperRef = useRef<HTMLDivElement | null>(null)
const scrollTimeout = useRef<NodeJS.Timeout | null>(null)

useEffect(() => {
const interval = setInterval(() => {
Expand All @@ -49,36 +54,74 @@ export const Viewer = ({ transcriptString }: Props) => {
return () => clearInterval(interval)
}, [playerRef, setCurrentTime])

useEffect(() => {
const handleScroll = () => {
setUserScrolling(true)

if (scrollTimeout.current) {
clearTimeout(scrollTimeout.current)
}

// Re-enable automatic scrolling after 1 second of no user scroll
scrollTimeout.current = setTimeout(() => {
setUserScrolling(false)
}, 1000)
}

const wrapper = wrapperRef.current

if (wrapper) {
wrapper.addEventListener('scroll', handleScroll)
}

return () => {
if (wrapper) {
wrapper.removeEventListener('scroll', handleScroll)
}
}
}, [])

useEffect(() => {
if (!userScrolling && activeRef.current) {
activeRef.current.scrollIntoView({
behavior: 'smooth',
block: 'center', // Centers the active paragraph
})
}
}, [currentTime, userScrolling])

return (
<Wrapper>
<Wrapper ref={wrapperRef}>
{transcriptData.map((i) => {
const start = secondsToMediaTime(i.start)
const end = secondsToMediaTime(i.end)

const isActive = i.start < currentTime && currentTime < i.end

return (
<Paragraph key={i.start}>
<Start>
{start}:{end}
</Start>
{i.words.map((word) => {
const isActive = word.start < currentTime && currentTime < word.end

return (
<Word key={`${word.start}`} className={clsx({ active: isActive })}>
{word.word}
</Word>
)
})}
<Paragraph
key={`${i.start}-${i.end}`}
ref={isActive ? activeRef : null}
className={clsx({ active: isActive })}
>
<Start>{start}</Start>
<Words>
<span>{i.text}</span>
</Words>
</Paragraph>
)
})}
</Wrapper>
)
}

const Paragraph = styled.div`
const Paragraph = styled(Flex)`
flex-direction: row;
align-items: flex-start;
font-size: 14px;
word-break: break-word;
padding: 8px 24px;
&.active {
background: ${colors.AI_HIGHLIGHT};
}
`

const Wrapper = styled.div`
Expand All @@ -88,12 +131,19 @@ const Wrapper = styled.div`
padding-right: 4px;
`

const Start = styled.span``
const Start = styled.span`
background: ${colors.lightBlue100};
color: ${colors.lightBlue500};
padding: 2px;
margin-right: 8px;
border-radius: 4px;
`

const Word = styled.span`
const Words = styled.div`
margin: 0 2px;
word-break: break-word;

&.active {
background: ${colors.lightBlue300};
background: ${colors.AI_HIGHLIGHT};
}
`
24 changes: 20 additions & 4 deletions src/components/mindset/components/Sidebar/Transcript/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { Viewer } from './Viewer'

export const Transcript = () => {
const { selectedEpisodeId } = useMindsetStore((s) => s)
const { playingTime, duration } = usePlayerStore((s) => s)
const { playerRef } = usePlayerStore((s) => s)
const [currentTime, setCurrentTime] = useState(0)

const [clips, setClips] = useState<NodeExtended[]>([])

Expand All @@ -32,6 +33,18 @@ export const Transcript = () => {
}
}, [selectedEpisodeId])

useEffect(() => {
const interval = setInterval(() => {
if (playerRef && setCurrentTime) {
const time = playerRef.getCurrentTime()

setCurrentTime(time)
}
}, 100)

return () => clearInterval(interval)
}, [playerRef, setCurrentTime])

return (
<Wrapper>
<Flex className="heading">Transcript</Flex>
Expand All @@ -40,9 +53,9 @@ export const Transcript = () => {

const [start, end] = timestamp
? (timestamp as string).split('-').map(Number) // Directly convert to numbers
: [0, duration]
: [0, 0]

if (start <= playingTime * 1000 && playingTime * 1000 < end) {
if (start <= currentTime * 1000 && currentTime * 1000 < end) {
// Multiply playingTime by 1000 to match millisecond format
return (
<TranscriptWrapper key={clip.ref_id} direction="row">
Expand All @@ -61,7 +74,7 @@ export const Transcript = () => {
const Wrapper = styled(Flex)`
.heading {
font-weight: 700;
font-size: 12px;
font-size: 16px;
margin-bottom: 16px;
}

Expand All @@ -71,9 +84,12 @@ const Wrapper = styled(Flex)`
padding: 24px;
overflow-y: auto;
flex: 1 1 100%;
max-height: 50%;
`

const TranscriptWrapper = styled(Flex)`
flex-wrap: wrap;
flex: 1 1 100%;
margin-left: -24px;
margin-right: -24px;
`
Loading