mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-25 22:38:56 +08:00
feat(core): dragging audio waveform to change seek time (#11730)
fix AF-2519
This commit is contained in:
@@ -124,24 +124,56 @@ export const AudioWaveform = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||||
|
const isDraggingRef = useRef(false);
|
||||||
|
|
||||||
// Handle click events for seeking
|
// Calculate progress from pointer position
|
||||||
const handleClick = useCallback(
|
const calculateProgress = useCallback((clientX: number) => {
|
||||||
(e: React.MouseEvent<HTMLDivElement>) => {
|
if (!containerRef.current) return 0;
|
||||||
if (!containerRef.current) return;
|
const rect = containerRef.current.getBoundingClientRect();
|
||||||
const rect = containerRef.current.getBoundingClientRect();
|
const x = clientX - rect.left;
|
||||||
const x = e.clientX - rect.left;
|
const availableWidth = rect.width - horizontalPadding * 2;
|
||||||
const availableWidth = rect.width - horizontalPadding * 2;
|
return clamp((x - horizontalPadding) / availableWidth, 0, 1);
|
||||||
const newProgress = Math.max(
|
}, []);
|
||||||
0,
|
|
||||||
Math.min(1, (x - horizontalPadding) / availableWidth)
|
// Handle pointer events for seeking
|
||||||
);
|
const handlePointerDown = useCallback(
|
||||||
|
(e: React.PointerEvent<HTMLDivElement>) => {
|
||||||
|
const newProgress = calculateProgress(e.clientX);
|
||||||
onManualSeek(newProgress);
|
onManualSeek(newProgress);
|
||||||
|
isDraggingRef.current = true;
|
||||||
|
e.preventDefault();
|
||||||
|
},
|
||||||
|
[calculateProgress, onManualSeek]
|
||||||
|
);
|
||||||
|
|
||||||
|
const stopPropagation = useCallback(
|
||||||
|
(e: React.PointerEvent<HTMLDivElement>) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
},
|
},
|
||||||
[onManualSeek]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Add and remove global event listeners
|
||||||
|
useEffect(() => {
|
||||||
|
const handlePointerMove = (e: PointerEvent) => {
|
||||||
|
if (!isDraggingRef.current) return;
|
||||||
|
const newProgress = calculateProgress(e.clientX);
|
||||||
|
onManualSeek(newProgress);
|
||||||
|
e.preventDefault();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePointerUp = () => {
|
||||||
|
isDraggingRef.current = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('pointermove', handlePointerMove);
|
||||||
|
window.addEventListener('pointerup', handlePointerUp);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('pointermove', handlePointerMove);
|
||||||
|
window.removeEventListener('pointerup', handlePointerUp);
|
||||||
|
};
|
||||||
|
}, [calculateProgress, onManualSeek]);
|
||||||
|
|
||||||
// Draw on resize
|
// Draw on resize
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const draw = () => {
|
const draw = () => {
|
||||||
@@ -173,11 +205,13 @@ export const AudioWaveform = ({
|
|||||||
<div
|
<div
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
className={styles.root}
|
className={styles.root}
|
||||||
onClick={handleClick}
|
onPointerDown={handlePointerDown}
|
||||||
|
onClick={stopPropagation}
|
||||||
role="slider"
|
role="slider"
|
||||||
aria-valuemin={0}
|
aria-valuemin={0}
|
||||||
aria-valuemax={100}
|
aria-valuemax={100}
|
||||||
aria-valuenow={progress * 100}
|
aria-valuenow={progress * 100}
|
||||||
|
draggable="false"
|
||||||
>
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<Skeleton />
|
<Skeleton />
|
||||||
|
|||||||
Reference in New Issue
Block a user