Voice notes drafts
This commit is contained in:
parent
356fb301e1
commit
99015d7b96
48 changed files with 2113 additions and 909 deletions
156
ts/state/smart/CompositionRecordingDraft.tsx
Normal file
156
ts/state/smart/CompositionRecordingDraft.tsx
Normal file
|
@ -0,0 +1,156 @@
|
|||
// Copyright 2023 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React, { useCallback } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { CompositionRecordingDraft } from '../../components/CompositionRecordingDraft';
|
||||
import type { AttachmentDraftType } from '../../types/Attachment';
|
||||
import {
|
||||
AudioPlayerContent,
|
||||
useAudioPlayerActions,
|
||||
} from '../ducks/audioPlayer';
|
||||
import { useComposerActions } from '../ducks/composer';
|
||||
import { selectAudioPlayerActive } from '../selectors/audioPlayer';
|
||||
import {
|
||||
getConversationByIdSelector,
|
||||
getSelectedConversationId,
|
||||
} from '../selectors/conversations';
|
||||
import { getIntl } from '../selectors/user';
|
||||
|
||||
export type SmartCompositionRecordingDraftProps = {
|
||||
voiceNoteAttachment: AttachmentDraftType;
|
||||
};
|
||||
|
||||
export function SmartCompositionRecordingDraft({
|
||||
voiceNoteAttachment,
|
||||
}: SmartCompositionRecordingDraftProps): JSX.Element {
|
||||
const i18n = useSelector(getIntl);
|
||||
const active = useSelector(selectAudioPlayerActive);
|
||||
const selectedConversationId = useSelector(getSelectedConversationId);
|
||||
const getConversationById = useSelector(getConversationByIdSelector);
|
||||
const {
|
||||
loadVoiceNoteDraftAudio,
|
||||
unloadMessageAudio,
|
||||
setIsPlaying,
|
||||
setPosition,
|
||||
} = useAudioPlayerActions();
|
||||
const { sendMultiMediaMessage, removeAttachment } = useComposerActions();
|
||||
|
||||
if (!selectedConversationId) {
|
||||
throw new Error('No selected conversation');
|
||||
}
|
||||
|
||||
const playbackRate =
|
||||
getConversationById(selectedConversationId)?.voiceNotePlaybackRate ?? 1;
|
||||
|
||||
const audioUrl = !voiceNoteAttachment.pending
|
||||
? voiceNoteAttachment.url
|
||||
: undefined;
|
||||
|
||||
const content = active?.content;
|
||||
|
||||
const draftActive =
|
||||
content && AudioPlayerContent.isDraft(content) && content.url === audioUrl
|
||||
? active
|
||||
: undefined;
|
||||
|
||||
const handlePlay = useCallback(
|
||||
(positionAsRatio?: number) => {
|
||||
if (!draftActive && audioUrl) {
|
||||
loadVoiceNoteDraftAudio({
|
||||
conversationId: selectedConversationId,
|
||||
url: audioUrl,
|
||||
startPosition: positionAsRatio ?? 0,
|
||||
playbackRate,
|
||||
});
|
||||
}
|
||||
if (draftActive) {
|
||||
if (positionAsRatio !== undefined) {
|
||||
setPosition(positionAsRatio);
|
||||
}
|
||||
if (!draftActive.playing) {
|
||||
setIsPlaying(true);
|
||||
}
|
||||
}
|
||||
},
|
||||
[
|
||||
draftActive,
|
||||
audioUrl,
|
||||
loadVoiceNoteDraftAudio,
|
||||
selectedConversationId,
|
||||
playbackRate,
|
||||
setPosition,
|
||||
setIsPlaying,
|
||||
]
|
||||
);
|
||||
|
||||
const handlePause = useCallback(() => {
|
||||
setIsPlaying(false);
|
||||
}, [setIsPlaying]);
|
||||
|
||||
const handleSend = useCallback(() => {
|
||||
if (selectedConversationId) {
|
||||
sendMultiMediaMessage(selectedConversationId, {
|
||||
draftAttachments: [voiceNoteAttachment],
|
||||
});
|
||||
}
|
||||
}, [selectedConversationId, sendMultiMediaMessage, voiceNoteAttachment]);
|
||||
|
||||
const handleCancel = useCallback(() => {
|
||||
unloadMessageAudio();
|
||||
if (selectedConversationId && voiceNoteAttachment.path) {
|
||||
removeAttachment(selectedConversationId, voiceNoteAttachment.path);
|
||||
}
|
||||
}, [
|
||||
removeAttachment,
|
||||
selectedConversationId,
|
||||
unloadMessageAudio,
|
||||
voiceNoteAttachment.path,
|
||||
]);
|
||||
|
||||
const handleScrub = useCallback(
|
||||
(positionAsRatio: number) => {
|
||||
// if scrubbing when audio not loaded
|
||||
if (!draftActive && audioUrl) {
|
||||
loadVoiceNoteDraftAudio({
|
||||
conversationId: selectedConversationId,
|
||||
url: audioUrl,
|
||||
startPosition: positionAsRatio,
|
||||
playbackRate,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// if scrubbing when audio is loaded
|
||||
if (draftActive) {
|
||||
setPosition(positionAsRatio);
|
||||
|
||||
if (draftActive?.playing) {
|
||||
setIsPlaying(true);
|
||||
}
|
||||
}
|
||||
},
|
||||
[
|
||||
audioUrl,
|
||||
draftActive,
|
||||
loadVoiceNoteDraftAudio,
|
||||
playbackRate,
|
||||
selectedConversationId,
|
||||
setIsPlaying,
|
||||
setPosition,
|
||||
]
|
||||
);
|
||||
|
||||
return (
|
||||
<CompositionRecordingDraft
|
||||
i18n={i18n}
|
||||
audioUrl={audioUrl}
|
||||
active={draftActive}
|
||||
onCancel={handleCancel}
|
||||
onSend={handleSend}
|
||||
onPlay={handlePlay}
|
||||
onPause={handlePause}
|
||||
onScrub={handleScrub}
|
||||
/>
|
||||
);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue