signal-desktop/ts/state/smart/CompositionRecordingDraft.tsx
2023-03-02 13:55:40 -07:00

156 lines
4.1 KiB
TypeScript

// 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}
/>
);
}