Rocket.Chat.ReactNative/app/containers/MessageBox/RecordAudio.tsx

256 lines
8.0 KiB
TypeScript
Raw Normal View History

import React from 'react';
import { Text, View } from 'react-native';
import { Audio, InterruptionModeAndroid, InterruptionModeIOS } from 'expo-av';
import { BorderlessButton } from 'react-native-gesture-handler';
import { getInfoAsync } from 'expo-file-system';
import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake';
import styles from './styles';
import I18n from '../../i18n';
import { themes } from '../../lib/constants';
import { CustomIcon } from '../CustomIcon';
import { events, logEvent } from '../../lib/methods/helpers/log';
import { TSupportedThemes } from '../../theme';
interface IMessageBoxRecordAudioProps {
theme: TSupportedThemes;
permissionToUpload: boolean;
recordingCallback: Function;
onFinish: Function;
onStart: Function;
}
const RECORDING_EXTENSION = '.aac';
const RECORDING_SETTINGS = {
android: {
// Settings related to audio encoding.
extension: RECORDING_EXTENSION,
outputFormat: Audio.RECORDING_OPTION_ANDROID_OUTPUT_FORMAT_AAC_ADTS,
audioEncoder: Audio.RECORDING_OPTION_ANDROID_AUDIO_ENCODER_AAC,
// Settings related to audio quality.
sampleRate: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.android.sampleRate,
numberOfChannels: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.android.numberOfChannels,
bitRate: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.android.bitRate
},
ios: {
// Settings related to audio encoding.
extension: RECORDING_EXTENSION,
audioQuality: Audio.RECORDING_OPTION_IOS_AUDIO_QUALITY_MEDIUM,
outputFormat: Audio.RECORDING_OPTION_IOS_OUTPUT_FORMAT_MPEG4AAC,
// Settings related to audio quality.
sampleRate: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.ios.sampleRate,
numberOfChannels: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.ios.numberOfChannels,
bitRate: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.ios.bitRate
},
web: {}
};
const RECORDING_MODE = {
allowsRecordingIOS: true,
playsInSilentModeIOS: true,
staysActiveInBackground: true,
shouldDuckAndroid: true,
playThroughEarpieceAndroid: false,
interruptionModeIOS: InterruptionModeIOS.DoNotMix,
interruptionModeAndroid: InterruptionModeAndroid.DoNotMix
};
const formatTime = function (time: number) {
const minutes = Math.floor(time / 60);
const seconds = time % 60;
const min = minutes < 10 ? `0${minutes}` : minutes;
const sec = seconds < 10 ? `0${seconds}` : seconds;
return `${min}:${sec}`;
};
export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAudioProps, any> {
private isRecorderBusy: boolean;
private recording!: Audio.Recording;
private LastDuration: number;
constructor(props: IMessageBoxRecordAudioProps) {
super(props);
this.isRecorderBusy = false;
this.LastDuration = 0;
this.state = {
isRecording: false,
isRecorderActive: false,
recordingDurationMillis: 0
};
}
componentDidUpdate() {
const { recordingCallback } = this.props;
const { isRecorderActive } = this.state;
recordingCallback(isRecorderActive);
}
componentWillUnmount() {
if (this.recording) {
this.cancelRecordingAudio();
}
}
get duration() {
const { recordingDurationMillis } = this.state;
return formatTime(Math.floor(recordingDurationMillis / 1000));
}
get GetLastDuration() {
return formatTime(Math.floor(this.LastDuration / 1000));
}
isRecordingPermissionGranted = async () => {
try {
const permission = await Audio.getPermissionsAsync();
if (permission.status === 'granted') {
return true;
}
await Audio.requestPermissionsAsync();
} catch {
// Do nothing
}
return false;
};
onRecordingStatusUpdate = (status: Audio.RecordingStatus) => {
this.setState({
isRecording: status.isRecording,
recordingDurationMillis: status.durationMillis
});
this.LastDuration = status.durationMillis;
};
startRecordingAudio = async () => {
const { onStart } = this.props;
onStart();
[NEW] Log events from Room, Settings and Edit status (#2206) * Create method to track user event to isolate the logic to improve future refactoring * Track Onboarding view * Track NewServer view * Refactor track method due to firebase already send the current screen * Track default login and all the oAuth options * Track default sign up in RegisterView * Change trackUserEvent signature and update all the files * Track the remaining login services * track add server, change server and search * Track SidebarView and refactor to use react-navigation * Track profile events and handle exceptions * Track create channel flux * Track send message to user via NewMessageView * Track create direct message flux * Handle failure of create channel and group in the saga * Track create discussion flux * Track navigate to directory and its actions * Track read, favorite and hide a channel, handling its errors * Track all channels sorting and grouping * Resolve requests to improve the importing logs and events * Remove unused events file * Remove unused events file * log proposed Room events * Log proposed Message actions events * Log EditStatus proposed events * Log Settings proposed events * Leave a bugsnag breadcrumb when logging an event * Move all logEvent to the top of code block and log remaining fail events * Move all the non-logic-dependent logEvent to the top of code block * Move all non-logic and non-data dependent logEvent to the top of code block * Improve the logging of sidebar events * Improve events from onboarding and newserver * Improve events from login and register view, and log enter with apple * Improve NewMessageView events * Improve CreateChannel events * Improve CreateDiscussion and SelectedUsers create group events * Improve RoomsList events and log trivial events * Improve ProfileView events * Remove single line function body for the sidebarNavigate * Improve SettingsView events * Log more events from ScreenLockConfigView * Navigate to Status and AdminPanel View using the defined sidebarNavigate method * Improve StatusView events * Improve RoomView events Co-authored-by: Diego Mello <diegolmello@gmail.com>
2020-07-30 19:51:13 +00:00
logEvent(events.ROOM_AUDIO_RECORD);
if (!this.isRecorderBusy) {
this.isRecorderBusy = true;
this.LastDuration = 0;
try {
const canRecord = await this.isRecordingPermissionGranted();
if (canRecord) {
await Audio.setAudioModeAsync(RECORDING_MODE);
this.setState({ isRecorderActive: true });
this.recording = new Audio.Recording();
await this.recording.prepareToRecordAsync(RECORDING_SETTINGS);
this.recording.setOnRecordingStatusUpdate(this.onRecordingStatusUpdate);
await this.recording.startAsync();
activateKeepAwake();
} else {
await Audio.requestPermissionsAsync();
}
} catch (error) {
[NEW] Log events from Room, Settings and Edit status (#2206) * Create method to track user event to isolate the logic to improve future refactoring * Track Onboarding view * Track NewServer view * Refactor track method due to firebase already send the current screen * Track default login and all the oAuth options * Track default sign up in RegisterView * Change trackUserEvent signature and update all the files * Track the remaining login services * track add server, change server and search * Track SidebarView and refactor to use react-navigation * Track profile events and handle exceptions * Track create channel flux * Track send message to user via NewMessageView * Track create direct message flux * Handle failure of create channel and group in the saga * Track create discussion flux * Track navigate to directory and its actions * Track read, favorite and hide a channel, handling its errors * Track all channels sorting and grouping * Resolve requests to improve the importing logs and events * Remove unused events file * Remove unused events file * log proposed Room events * Log proposed Message actions events * Log EditStatus proposed events * Log Settings proposed events * Leave a bugsnag breadcrumb when logging an event * Move all logEvent to the top of code block and log remaining fail events * Move all the non-logic-dependent logEvent to the top of code block * Move all non-logic and non-data dependent logEvent to the top of code block * Improve the logging of sidebar events * Improve events from onboarding and newserver * Improve events from login and register view, and log enter with apple * Improve NewMessageView events * Improve CreateChannel events * Improve CreateDiscussion and SelectedUsers create group events * Improve RoomsList events and log trivial events * Improve ProfileView events * Remove single line function body for the sidebarNavigate * Improve SettingsView events * Log more events from ScreenLockConfigView * Navigate to Status and AdminPanel View using the defined sidebarNavigate method * Improve StatusView events * Improve RoomView events Co-authored-by: Diego Mello <diegolmello@gmail.com>
2020-07-30 19:51:13 +00:00
logEvent(events.ROOM_AUDIO_RECORD_F);
}
this.isRecorderBusy = false;
}
};
finishRecordingAudio = async () => {
[NEW] Log events from Room, Settings and Edit status (#2206) * Create method to track user event to isolate the logic to improve future refactoring * Track Onboarding view * Track NewServer view * Refactor track method due to firebase already send the current screen * Track default login and all the oAuth options * Track default sign up in RegisterView * Change trackUserEvent signature and update all the files * Track the remaining login services * track add server, change server and search * Track SidebarView and refactor to use react-navigation * Track profile events and handle exceptions * Track create channel flux * Track send message to user via NewMessageView * Track create direct message flux * Handle failure of create channel and group in the saga * Track create discussion flux * Track navigate to directory and its actions * Track read, favorite and hide a channel, handling its errors * Track all channels sorting and grouping * Resolve requests to improve the importing logs and events * Remove unused events file * Remove unused events file * log proposed Room events * Log proposed Message actions events * Log EditStatus proposed events * Log Settings proposed events * Leave a bugsnag breadcrumb when logging an event * Move all logEvent to the top of code block and log remaining fail events * Move all the non-logic-dependent logEvent to the top of code block * Move all non-logic and non-data dependent logEvent to the top of code block * Improve the logging of sidebar events * Improve events from onboarding and newserver * Improve events from login and register view, and log enter with apple * Improve NewMessageView events * Improve CreateChannel events * Improve CreateDiscussion and SelectedUsers create group events * Improve RoomsList events and log trivial events * Improve ProfileView events * Remove single line function body for the sidebarNavigate * Improve SettingsView events * Log more events from ScreenLockConfigView * Navigate to Status and AdminPanel View using the defined sidebarNavigate method * Improve StatusView events * Improve RoomView events Co-authored-by: Diego Mello <diegolmello@gmail.com>
2020-07-30 19:51:13 +00:00
logEvent(events.ROOM_AUDIO_FINISH);
if (!this.isRecorderBusy) {
const { onFinish } = this.props;
this.isRecorderBusy = true;
try {
await this.recording.stopAndUnloadAsync();
const fileURI = this.recording.getURI();
const fileData = await getInfoAsync(fileURI as string);
const fileInfo = {
name: `${Date.now()}.aac`,
mime: 'audio/aac',
type: 'audio/aac',
store: 'Uploads',
path: fileURI,
size: fileData.exists ? fileData.size : null
};
onFinish(fileInfo);
} catch (error) {
[NEW] Log events from Room, Settings and Edit status (#2206) * Create method to track user event to isolate the logic to improve future refactoring * Track Onboarding view * Track NewServer view * Refactor track method due to firebase already send the current screen * Track default login and all the oAuth options * Track default sign up in RegisterView * Change trackUserEvent signature and update all the files * Track the remaining login services * track add server, change server and search * Track SidebarView and refactor to use react-navigation * Track profile events and handle exceptions * Track create channel flux * Track send message to user via NewMessageView * Track create direct message flux * Handle failure of create channel and group in the saga * Track create discussion flux * Track navigate to directory and its actions * Track read, favorite and hide a channel, handling its errors * Track all channels sorting and grouping * Resolve requests to improve the importing logs and events * Remove unused events file * Remove unused events file * log proposed Room events * Log proposed Message actions events * Log EditStatus proposed events * Log Settings proposed events * Leave a bugsnag breadcrumb when logging an event * Move all logEvent to the top of code block and log remaining fail events * Move all the non-logic-dependent logEvent to the top of code block * Move all non-logic and non-data dependent logEvent to the top of code block * Improve the logging of sidebar events * Improve events from onboarding and newserver * Improve events from login and register view, and log enter with apple * Improve NewMessageView events * Improve CreateChannel events * Improve CreateDiscussion and SelectedUsers create group events * Improve RoomsList events and log trivial events * Improve ProfileView events * Remove single line function body for the sidebarNavigate * Improve SettingsView events * Log more events from ScreenLockConfigView * Navigate to Status and AdminPanel View using the defined sidebarNavigate method * Improve StatusView events * Improve RoomView events Co-authored-by: Diego Mello <diegolmello@gmail.com>
2020-07-30 19:51:13 +00:00
logEvent(events.ROOM_AUDIO_FINISH_F);
}
this.setState({ isRecording: false, isRecorderActive: false, recordingDurationMillis: 0 });
deactivateKeepAwake();
this.isRecorderBusy = false;
}
};
cancelRecordingAudio = async () => {
[NEW] Log events from Room, Settings and Edit status (#2206) * Create method to track user event to isolate the logic to improve future refactoring * Track Onboarding view * Track NewServer view * Refactor track method due to firebase already send the current screen * Track default login and all the oAuth options * Track default sign up in RegisterView * Change trackUserEvent signature and update all the files * Track the remaining login services * track add server, change server and search * Track SidebarView and refactor to use react-navigation * Track profile events and handle exceptions * Track create channel flux * Track send message to user via NewMessageView * Track create direct message flux * Handle failure of create channel and group in the saga * Track create discussion flux * Track navigate to directory and its actions * Track read, favorite and hide a channel, handling its errors * Track all channels sorting and grouping * Resolve requests to improve the importing logs and events * Remove unused events file * Remove unused events file * log proposed Room events * Log proposed Message actions events * Log EditStatus proposed events * Log Settings proposed events * Leave a bugsnag breadcrumb when logging an event * Move all logEvent to the top of code block and log remaining fail events * Move all the non-logic-dependent logEvent to the top of code block * Move all non-logic and non-data dependent logEvent to the top of code block * Improve the logging of sidebar events * Improve events from onboarding and newserver * Improve events from login and register view, and log enter with apple * Improve NewMessageView events * Improve CreateChannel events * Improve CreateDiscussion and SelectedUsers create group events * Improve RoomsList events and log trivial events * Improve ProfileView events * Remove single line function body for the sidebarNavigate * Improve SettingsView events * Log more events from ScreenLockConfigView * Navigate to Status and AdminPanel View using the defined sidebarNavigate method * Improve StatusView events * Improve RoomView events Co-authored-by: Diego Mello <diegolmello@gmail.com>
2020-07-30 19:51:13 +00:00
logEvent(events.ROOM_AUDIO_CANCEL);
if (!this.isRecorderBusy) {
this.isRecorderBusy = true;
try {
await this.recording.stopAndUnloadAsync();
} catch (error) {
[NEW] Log events from Room, Settings and Edit status (#2206) * Create method to track user event to isolate the logic to improve future refactoring * Track Onboarding view * Track NewServer view * Refactor track method due to firebase already send the current screen * Track default login and all the oAuth options * Track default sign up in RegisterView * Change trackUserEvent signature and update all the files * Track the remaining login services * track add server, change server and search * Track SidebarView and refactor to use react-navigation * Track profile events and handle exceptions * Track create channel flux * Track send message to user via NewMessageView * Track create direct message flux * Handle failure of create channel and group in the saga * Track create discussion flux * Track navigate to directory and its actions * Track read, favorite and hide a channel, handling its errors * Track all channels sorting and grouping * Resolve requests to improve the importing logs and events * Remove unused events file * Remove unused events file * log proposed Room events * Log proposed Message actions events * Log EditStatus proposed events * Log Settings proposed events * Leave a bugsnag breadcrumb when logging an event * Move all logEvent to the top of code block and log remaining fail events * Move all the non-logic-dependent logEvent to the top of code block * Move all non-logic and non-data dependent logEvent to the top of code block * Improve the logging of sidebar events * Improve events from onboarding and newserver * Improve events from login and register view, and log enter with apple * Improve NewMessageView events * Improve CreateChannel events * Improve CreateDiscussion and SelectedUsers create group events * Improve RoomsList events and log trivial events * Improve ProfileView events * Remove single line function body for the sidebarNavigate * Improve SettingsView events * Log more events from ScreenLockConfigView * Navigate to Status and AdminPanel View using the defined sidebarNavigate method * Improve StatusView events * Improve RoomView events Co-authored-by: Diego Mello <diegolmello@gmail.com>
2020-07-30 19:51:13 +00:00
logEvent(events.ROOM_AUDIO_CANCEL_F);
}
this.setState({ isRecording: false, isRecorderActive: false, recordingDurationMillis: 0 });
deactivateKeepAwake();
this.isRecorderBusy = false;
}
};
render() {
const { theme, permissionToUpload } = this.props;
const { isRecording, isRecorderActive } = this.state;
if (!permissionToUpload) {
return null;
}
if (!isRecording && !isRecorderActive) {
return (
<BorderlessButton onPress={this.startRecordingAudio} style={styles.actionButton} testID='messagebox-send-audio'>
<View accessible accessibilityLabel={I18n.t('Send_audio_message')} accessibilityRole='button'>
<CustomIcon name='microphone' size={24} color={themes[theme].auxiliaryTintColor} />
</View>
</BorderlessButton>
);
}
if (!isRecording && isRecorderActive) {
return (
<View style={styles.recordingContent}>
<View style={styles.textArea}>
<BorderlessButton onPress={this.cancelRecordingAudio} style={styles.actionButton}>
<View accessible accessibilityLabel={I18n.t('Cancel_recording')} accessibilityRole='button'>
<CustomIcon size={24} color={themes[theme].dangerColor} name='delete' />
</View>
</BorderlessButton>
<Text style={[styles.recordingDurationText, { color: themes[theme].titleText }]}>{this.GetLastDuration}</Text>
</View>
<BorderlessButton onPress={this.finishRecordingAudio} style={styles.actionButton}>
<View accessible accessibilityLabel={I18n.t('Finish_recording')} accessibilityRole='button'>
<CustomIcon size={24} color={themes[theme].tintColor} name='send-filled' />
</View>
</BorderlessButton>
</View>
);
}
return (
<View style={styles.recordingContent}>
<View style={styles.textArea}>
<BorderlessButton onPress={this.cancelRecordingAudio} style={styles.actionButton}>
<View accessible accessibilityLabel={I18n.t('Cancel_recording')} accessibilityRole='button'>
<CustomIcon size={24} color={themes[theme].dangerColor} name='delete' />
</View>
</BorderlessButton>
<Text style={[styles.recordingDurationText, { color: themes[theme].titleText }]}>{this.duration}</Text>
<CustomIcon size={24} color={themes[theme].dangerColor} name='record' />
</View>
<BorderlessButton onPress={this.finishRecordingAudio} style={styles.actionButton}>
<View accessible accessibilityLabel={I18n.t('Finish_recording')} accessibilityRole='button'>
<CustomIcon size={24} color={themes[theme].tintColor} name='send-filled' />
</View>
</BorderlessButton>
</View>
);
}
}