fix(audio): corrige redownload de áudio + move botão de velocidade antes do waveform

1. MessageArea: handleRedownloadMedia usava selectedChat?.instanceId (undefined
   no formato legado) — substituído por instance_name ?? instanceId. O clique
   em 'Toque para baixar áudio' agora chama o backend corretamente.

2. MessageBubble/AudioBubble: botão de velocidade (1×/1.5×/2×) movido para
   entre o botão play e as barras do waveform, conforme layout do WhatsApp.
   A linha inferior agora exibe apenas o tempo decorrido.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
VPS 4 Deploy Agent
2026-05-12 03:19:45 +02:00
parent 5b3259d705
commit 634426ed15
2 changed files with 15 additions and 14 deletions
@@ -61,10 +61,11 @@ const MessageArea: React.FC<MessageAreaProps> = ({
// ── Re-download de mídia não baixada ───────────────────────────────────── // ── Re-download de mídia não baixada ─────────────────────────────────────
const handleRedownloadMedia = useCallback(async (msg: Message) => { const handleRedownloadMedia = useCallback(async (msg: Message) => {
const instanceId = selectedChat?.instanceId // selectedChat no formato legado usa instance_name (não instanceId)
const instanceId = selectedChat?.instance_name ?? selectedChat?.instanceId
if (!instanceId || !msg.id) return if (!instanceId || !msg.id) return
await mediaApi.redownload(instanceId, String(msg.id)) await mediaApi.redownload(instanceId, String(msg.id))
}, [selectedChat?.instanceId]) }, [selectedChat?.instance_name, selectedChat?.instanceId])
const mediaMessages = messages.filter(m => m.type === 'image' || m.type === 'video') const mediaMessages = messages.filter(m => m.type === 'image' || m.type === 'video')
const handleInternalScroll = useCallback(() => { const handleInternalScroll = useCallback(() => {
@@ -123,7 +123,15 @@ const AudioBubble: React.FC<AudioBubbleProps> = ({ msg, fullMediaUrl, isOut, Tim
)} )}
</button> </button>
{/* Waveform + meta */} {/* Speed — antes do waveform, alinhado ao centro vertical */}
<button
onClick={cycleSpeed}
className="text-[11px] font-bold text-[#667781] hover:text-[#111b21] transition-colors leading-none shrink-0 w-7 text-center"
>
{speed === 1 ? '1×' : speed === 1.5 ? '1.5×' : '2×'}
</button>
{/* Waveform + tempo */}
<div className="flex-1 flex flex-col gap-1 min-w-0"> <div className="flex-1 flex flex-col gap-1 min-w-0">
<div className="flex items-end gap-[2px] h-7"> <div className="flex items-end gap-[2px] h-7">
{waveHeights.map((h, i) => ( {waveHeights.map((h, i) => (
@@ -137,17 +145,9 @@ const AudioBubble: React.FC<AudioBubbleProps> = ({ msg, fullMediaUrl, isOut, Tim
/> />
))} ))}
</div> </div>
<div className="flex items-center justify-between"> <span className="text-[11px] text-[#667781] tabular-nums leading-none">
<span className="text-[11px] text-[#667781] tabular-nums leading-none"> {currentTime > 0 ? formatTime(currentTime) : formatTime(duration)}
{currentTime > 0 ? formatTime(currentTime) : formatTime(duration)} </span>
</span>
<button
onClick={cycleSpeed}
className="text-[11px] font-bold text-[#667781] hover:text-[#111b21] transition-colors leading-none"
>
{speed === 1 ? '1×' : speed === 1.5 ? '1.5×' : '2×'}
</button>
</div>
</div> </div>
</div> </div>
{TimestampRow} {TimestampRow}