From 555e6836f67fae75d5fc7e83efbaf2511af03636 Mon Sep 17 00:00:00 2001 From: Delirium Date: Mon, 22 Apr 2024 14:38:18 +0200 Subject: [PATCH] feat ui: improve audio addon look and style (#2118) --- .../app/components/Client/client.module.css | 2 +- .../Player/ReplayPlayer/AudioPlayer.tsx | 136 ++++++++++++++---- .../Player/ReplayPlayer/PlayerBlockHeader.tsx | 4 - .../Session_/Player/Controls/Controls.tsx | 11 +- frontend/app/styles/reset.css | 2 +- 5 files changed, 119 insertions(+), 36 deletions(-) diff --git a/frontend/app/components/Client/client.module.css b/frontend/app/components/Client/client.module.css index 815b7e8d6..38539a5d1 100644 --- a/frontend/app/components/Client/client.module.css +++ b/frontend/app/components/Client/client.module.css @@ -41,7 +41,7 @@ margin-top: 10px; } - & input { + & input:not(.ant-input-number-input) { display: inline-block; width: 100%; border: $gray-light solid 1px; diff --git a/frontend/app/components/Session/Player/ReplayPlayer/AudioPlayer.tsx b/frontend/app/components/Session/Player/ReplayPlayer/AudioPlayer.tsx index b45aaecf7..7db06db3f 100644 --- a/frontend/app/components/Session/Player/ReplayPlayer/AudioPlayer.tsx +++ b/frontend/app/components/Session/Player/ReplayPlayer/AudioPlayer.tsx @@ -1,5 +1,6 @@ -import { MutedOutlined, SoundOutlined } from '@ant-design/icons'; -import { Button, Tooltip } from 'antd'; +import { MutedOutlined, SoundOutlined, CaretDownOutlined, ControlOutlined } from '@ant-design/icons'; +import { Button, Popover, InputNumber } from 'antd'; +import { Slider } from 'antd'; import { observer } from 'mobx-react-lite'; import React, { useRef, useState } from 'react'; @@ -8,8 +9,10 @@ import { PlayerContext } from '../../playerContext'; function DropdownAudioPlayer({ url }: { url: string }) { const { store } = React.useContext(PlayerContext); const [isVisible, setIsVisible] = useState(false); + const [volume, setVolume] = useState(0); const [delta, setDelta] = useState(0); - const [isMuted, setIsMuted] = useState(false); + const [deltaInputValue, setDeltaInputValue] = useState(0); + const [isMuted, setIsMuted] = useState(true); const lastPlayerTime = React.useRef(0); const audioRef = useRef(null); @@ -25,6 +28,34 @@ function DropdownAudioPlayer({ url }: { url: string }) { } }; + const toggleVisible = () => { + setIsVisible(!isVisible); + }; + + const handleDelta = (value: any) => { + setDeltaInputValue(parseFloat(value)) + } + + const onSync = () => { + setDelta(deltaInputValue) + } + const onCancel = () => { + setDeltaInputValue(0) + setIsVisible(false) + } + const onReset = () => { + setDelta(0) + setDeltaInputValue(0) + setIsVisible(false) + } + + const onVolumeChange = (value: number) => { + if (audioRef.current) { + audioRef.current.volume = value / 100; + } + setVolume(value); + }; + const handleSeek = (timeMs: number) => { if (audioRef.current) { audioRef.current.currentTime = (timeMs + delta) / 1000; @@ -38,11 +69,19 @@ function DropdownAudioPlayer({ url }: { url: string }) { }; React.useEffect(() => { - if (Math.abs(lastPlayerTime.current - time) > 1000) { + if (Math.abs(lastPlayerTime.current - time) >= 250) { handleSeek(time); } - lastPlayerTime.current = time; - }, [time]); + if (audioRef.current) { + if (audioRef.current.paused && playing) { + audioRef.current?.play(); + } + if (audioRef.current.muted !== isMuted) { + audioRef.current.muted = isMuted; + } + } + lastPlayerTime.current = time + delta; + }, [time, delta]); React.useEffect(() => { changePlaybackSpeed(speed); @@ -54,33 +93,80 @@ function DropdownAudioPlayer({ url }: { url: string }) { } else { audioRef.current?.pause(); } + const volume = audioRef.current?.volume ?? 0 + setVolume(volume * 100); }, [playing]); return ( -
- +
- +
+ } > - {isMuted ? : } - -
+
+ {isMuted ? : } +
+ +
+ +
+
+ + {isVisible ? ( +
+
+ +
Audio Track Synchronization
+
+ `${value}s`} + parser={(value) => value?.replace('s', '') as unknown as number} + stringMode + onChange={handleDelta} /> +
+ + + + +
+
+ ) : null} +
)} - - {session.audio ? : null}
diff --git a/frontend/app/components/Session_/Player/Controls/Controls.tsx b/frontend/app/components/Session_/Player/Controls/Controls.tsx index e03430715..0885d7c76 100644 --- a/frontend/app/components/Session_/Player/Controls/Controls.tsx +++ b/frontend/app/components/Session_/Player/Controls/Controls.tsx @@ -36,6 +36,7 @@ import { import { fetchSessions } from 'Duck/liveSearch'; import { Icon } from 'UI'; +import DropdownAudioPlayer from '../../../Session/Player/ReplayPlayer/AudioPlayer'; import ControlButton from './ControlButton'; import Timeline from './Timeline'; import PlayerControls from './components/PlayerControls'; @@ -179,6 +180,7 @@ function Controls(props: any) { toggleBottomTools={toggleBottomTools} bottomBlock={bottomBlock} disabled={disabled} + audioUrl={session.audio} /> )} @@ -201,6 +203,7 @@ interface IDevtoolsButtons { toggleBottomTools: (blockName: number) => void; bottomBlock: number; disabled: boolean; + audioUrl?: string; } const DevtoolsButtons = observer( @@ -209,6 +212,7 @@ const DevtoolsButtons = observer( toggleBottomTools, bottomBlock, disabled, + audioUrl, }: IDevtoolsButtons) => { const { aiSummaryStore } = useStore(); const { store, player } = React.useContext(PlayerContext); @@ -247,11 +251,7 @@ const DevtoolsButtons = observer( }; return ( <> - {isSaas ? ( - - ) : null} + {isSaas ? : null} @@ -349,6 +349,7 @@ const DevtoolsButtons = observer( label="Profiler" /> )} + {audioUrl ? : null} ); } diff --git a/frontend/app/styles/reset.css b/frontend/app/styles/reset.css index e1cace6ed..744203955 100644 --- a/frontend/app/styles/reset.css +++ b/frontend/app/styles/reset.css @@ -26,7 +26,7 @@ button { } textarea:focus, -input:focus { +input:not(.ant-input-number-input):focus { border: solid thin $teal !important; }