feat(web): voice messages (record, send, playback)
Click-to-record (README §3.3's explicit 取消/发送 buttons), not the old
app's press-and-hold-with-swipe-to-cancel gesture -- the new design replaces
that touch gesture with plain buttons, a reasonable desktop-first
adaptation; the underlying MediaRecorder mechanics (audio/webm or
audio/mp4 depending on browser support, 24kbps, 2s minimum/10min maximum
duration) are ported as-is from the old app's audio-recorder.jsx.
- VoiceRecorder.tsx: recording UI + MediaRecorder lifecycle. Silently
discards (no send) recordings under MIN_DURATION, matching the old app.
Deliberately skips the `webm-duration-fix` package the old app pulled in
for Chrome's well-known missing-webm-duration-metadata bug -- this app's
own displayed duration comes from its own recording timer, not the file's
embedded metadata, so only a browser's native <audio> scrubber would be
affected, not anything this app actually shows.
- attachments.ts: sendVoice() -- inline base64 or upload-then-reference,
same size-based branch as images/files, Drafty.insertAudio's confirmed
{mime,val/ref,duration,size} shape.
- AttachmentPreview.tsx: AudioAttachment play/pause button + static
waveform (CSS repeating-gradient, not real waveform analysis) + duration.
Verified the failure path live (this sandbox blocks getUserMedia): the
recorder's error state shows a clear message and recovers cleanly back to
the normal composer with no crash. The actual record -> encode -> send ->
playback round trip could not be exercised in this environment and needs
a manual check with real microphone access.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
aa3e464b35
commit
03b8098b3c
@@ -2,7 +2,7 @@ import { Fragment, type ReactNode } from 'react';
|
||||
|
||||
import { Drafty, type DraftyContent } from 'tinode-sdk';
|
||||
|
||||
import { FileAttachment, ImageAttachment } from '@/features/messages/AttachmentPreview';
|
||||
import { AudioAttachment, FileAttachment, ImageAttachment } from '@/features/messages/AttachmentPreview';
|
||||
|
||||
/**
|
||||
* Bubble content renderer for the Drafty style tags this app currently sends/receives. Grown
|
||||
@@ -61,6 +61,8 @@ function formatNode(
|
||||
return <ImageAttachment key={key} data={data || {}} />;
|
||||
case 'EX':
|
||||
return <FileAttachment key={key} data={data || {}} />;
|
||||
case 'AU':
|
||||
return <AudioAttachment key={key} data={data || {}} />;
|
||||
case 'QQ':
|
||||
// Drafty.quote() has no `key`/`data` of its own (tinode.dev.js:2160-2168) -- it's a plain style
|
||||
// span wrapping mention(header,uid) + linebreak + body, all already rendered into `children`.
|
||||
|
||||
Reference in New Issue
Block a user