Feat: web app dark mode (#14732)
This commit is contained in:
@@ -1,7 +1,13 @@
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { t } from 'i18next'
|
||||
import styles from './AudioPlayer.module.css'
|
||||
import {
|
||||
RiPauseCircleFill,
|
||||
RiPlayLargeFill,
|
||||
} from '@remixicon/react'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { Theme } from '@/types/app'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type AudioPlayerProps = {
|
||||
src: string
|
||||
@@ -18,6 +24,7 @@ const AudioPlayer: React.FC<AudioPlayerProps> = ({ src }) => {
|
||||
const [hasStartedPlaying, setHasStartedPlaying] = useState(false)
|
||||
const [hoverTime, setHoverTime] = useState(0)
|
||||
const [isAudioAvailable, setIsAudioAvailable] = useState(true)
|
||||
const { theme } = useAppContext()
|
||||
|
||||
useEffect(() => {
|
||||
const audio = audioRef.current
|
||||
@@ -230,11 +237,11 @@ const AudioPlayer: React.FC<AudioPlayerProps> = ({ src }) => {
|
||||
let color
|
||||
|
||||
if (index * barWidth <= playedWidth)
|
||||
color = '#296DFF'
|
||||
color = theme === Theme.light ? '#296DFF' : '#84ABFF'
|
||||
else if ((index * barWidth / width) * duration <= hoverTime)
|
||||
color = 'rgba(21,90,239,.40)'
|
||||
color = theme === Theme.light ? 'rgba(21,90,239,.40)' : 'rgba(200, 206, 218, 0.28)'
|
||||
else
|
||||
color = 'rgba(21,90,239,.20)'
|
||||
color = theme === Theme.light ? 'rgba(21,90,239,.20)' : 'rgba(200, 206, 218, 0.14)'
|
||||
|
||||
const barHeight = value * height
|
||||
const rectX = index * barWidth
|
||||
@@ -253,7 +260,7 @@ const AudioPlayer: React.FC<AudioPlayerProps> = ({ src }) => {
|
||||
ctx.fillRect(rectX, rectY, rectWidth, rectHeight)
|
||||
}
|
||||
})
|
||||
}, [currentTime, duration, hoverTime, waveformData])
|
||||
}, [currentTime, duration, hoverTime, theme, waveformData])
|
||||
|
||||
useEffect(() => {
|
||||
drawWaveform()
|
||||
@@ -279,40 +286,32 @@ const AudioPlayer: React.FC<AudioPlayerProps> = ({ src }) => {
|
||||
}, [duration])
|
||||
|
||||
return (
|
||||
<div className={styles.audioPlayer}>
|
||||
<div className='flex items-end gap-2 h-9 min-w-[240px] max-w-[420px] p-2 bg-components-chat-input-audio-bg-alt backdrop-blur-sm rounded-[10px] border border-components-panel-border-subtle shadow-xs'>
|
||||
<audio ref={audioRef} src={src} preload="auto"/>
|
||||
<button className={styles.playButton} onClick={togglePlay} disabled={!isAudioAvailable}>
|
||||
<button className='shrink-0 inline-flex items-center justify-center border-none text-text-accent hover:text-text-accent-secondary transition-all cursor-pointer disabled:text-components-button-primary-bg-disabled' onClick={togglePlay} disabled={!isAudioAvailable}>
|
||||
{isPlaying
|
||||
? (
|
||||
<svg viewBox="0 0 24 24" width="16" height="16">
|
||||
<rect x="7" y="6" width="3" height="12" rx="1.5" ry="1.5"/>
|
||||
<rect x="15" y="6" width="3" height="12" rx="1.5" ry="1.5"/>
|
||||
</svg>
|
||||
<RiPauseCircleFill className='w-5 h-5' />
|
||||
)
|
||||
: (
|
||||
<svg viewBox="0 0 24 24" width="16" height="16">
|
||||
<path d="M8 5v14l11-7z" fill="currentColor"/>
|
||||
</svg>
|
||||
<RiPlayLargeFill className='w-5 h-5' />
|
||||
)}
|
||||
</button>
|
||||
<div className={isAudioAvailable ? styles.audioControls : styles.audioControls_disabled} hidden={!isAudioAvailable}>
|
||||
<div className={styles.progressBarContainer}>
|
||||
<div className={cn(isAudioAvailable && 'grow')} hidden={!isAudioAvailable}>
|
||||
<div className='h-8 flex items-center justify-center'>
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className={styles.waveform}
|
||||
className='relative grow h-6 w-full flex items-center justify-center cursor-pointer'
|
||||
onClick={handleCanvasInteraction}
|
||||
onMouseMove={handleMouseMove}
|
||||
onMouseDown={handleCanvasInteraction}
|
||||
/>
|
||||
{/* <div className={styles.currentTime} style={{ left: `${(currentTime / duration) * 81}%`, bottom: '29px' }}>
|
||||
{formatTime(currentTime)}
|
||||
</div> */}
|
||||
<div className={styles.timeDisplay}>
|
||||
<span className={styles.duration}>{formatTime(duration)}</span>
|
||||
<div className='inline-flex items-center justify-center min-w-[50px] text-text-accent-secondary system-xs-medium'>
|
||||
<span className='px-0.5 py-1 rounded-[10px]'>{formatTime(duration)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.source_unavailable} hidden={isAudioAvailable}>{t('common.operation.audioSourceUnavailable')}</div>
|
||||
<div className='absolute top-0 left-0 w-full h-full flex items-center justify-center text-text-quaternary' hidden={isAudioAvailable}>{t('common.operation.audioSourceUnavailable')}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user