diff --git a/android/app/build.gradle b/android/app/build.gradle index e6c65008c..fc2f40982 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -144,6 +144,7 @@ android { } dependencies { + compile project(':react-native-audio') compile project(":reactnativekeyboardinput") compile project(':react-native-splash-screen') compile project(':react-native-video') diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 494507756..0137ae666 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -7,6 +7,7 @@ + diff --git a/android/app/src/main/java/com/rocketchatrn/MainApplication.java b/android/app/src/main/java/com/rocketchatrn/MainApplication.java index 986de10f3..051a8fdc7 100644 --- a/android/app/src/main/java/com/rocketchatrn/MainApplication.java +++ b/android/app/src/main/java/com/rocketchatrn/MainApplication.java @@ -17,6 +17,7 @@ import com.dieam.reactnativepushnotification.ReactNativePushNotificationPackage; import com.brentvatne.react.ReactVideoPackage; import com.remobile.toast.RCTToastPackage; import com.wix.reactnativekeyboardinput.KeyboardInputPackage; +import com.rnim.rn.audio.ReactNativeAudioPackage; import java.util.Arrays; import java.util.List; @@ -44,6 +45,7 @@ public class MainApplication extends Application implements ReactApplication { new ReactVideoPackage(), new SplashScreenReactPackage(), new RCTToastPackage(), + new ReactNativeAudioPackage(), new KeyboardInputPackage(MainApplication.this), new RocketChatNativePackage() ); diff --git a/android/gradle.properties b/android/gradle.properties index d94d12020..55422fd77 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -17,4 +17,4 @@ # org.gradle.parallel=true android.useDeprecatedNdk=true -VERSIONCODE=999999999 +# VERSIONCODE=999999999 diff --git a/android/settings.gradle b/android/settings.gradle index 236de741b..5c628bbf4 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,4 +1,6 @@ rootProject.name = 'RocketChatRN' +include ':react-native-audio' +project(':react-native-audio').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-audio/android') include ':reactnativekeyboardinput' project(':reactnativekeyboardinput').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-keyboard-input/lib/android') include ':react-native-splash-screen' diff --git a/app/containers/MessageBox/Recording.js b/app/containers/MessageBox/Recording.js new file mode 100644 index 000000000..10e32b898 --- /dev/null +++ b/app/containers/MessageBox/Recording.js @@ -0,0 +1,127 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { View, SafeAreaView, Platform, PermissionsAndroid, Text } from 'react-native'; +import { AudioRecorder, AudioUtils } from 'react-native-audio'; +import Icon from 'react-native-vector-icons/MaterialIcons'; +import styles from './styles'; + +export const _formatTime = function(seconds) { + let minutes = Math.floor(seconds / 60); + seconds %= 60; + if (minutes < 10) { minutes = `0${ minutes }`; } + if (seconds < 10) { seconds = `0${ seconds }`; } + return `${ minutes }:${ seconds }`; +}; + +export default class extends React.PureComponent { + static propTypes = { + onFinish: PropTypes.func.isRequired + } + + static async permission() { + if (Platform.OS !== 'android') { + return true; + } + + const rationale = { + title: 'Microphone Permission', + message: 'Rocket Chat needs access to your microphone so you can send audio message.' + }; + + const result = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.RECORD_AUDIO, rationale); + return result === true || result === PermissionsAndroid.RESULTS.GRANTED; + } + + constructor() { + super(); + + this.recordingCanceled = false; + this.state = { + currentTime: '00:00' + }; + } + + componentDidMount() { + const audioPath = `${ AudioUtils.CachesDirectoryPath }/${ Date.now() }.aac`; + + AudioRecorder.prepareRecordingAtPath(audioPath, { + SampleRate: 22050, + Channels: 1, + AudioQuality: 'Low', + AudioEncoding: 'aac' + }); + + AudioRecorder.onProgress = (data) => { + this.setState({ + currentTime: _formatTime(Math.floor(data.currentTime)) + }); + }; + // + AudioRecorder.onFinished = (data) => { + if (!this.recordingCanceled && Platform.OS === 'ios') { + this._finishRecording(data.status === 'OK', data.audioFileURL); + } + }; + AudioRecorder.startRecording(); + } + + _finishRecording(didSucceed, filePath) { + if (!didSucceed) { + return this.props.onFinish && this.props.onFinish(didSucceed); + } + + const path = filePath.startsWith('file://') ? filePath.split('file://')[1] : filePath; + const fileInfo = { + type: 'audio/aac', + store: 'Uploads', + path + }; + return this.props.onFinish && this.props.onFinish(fileInfo); + } + + finishAudioMessage = async() => { + try { + const filePath = await AudioRecorder.stopRecording(); + if (Platform.OS === 'android') { + this._finishRecording(true, filePath); + } + } catch (err) { + this._finishRecording(false); + console.error(err); + } + } + + cancelAudioMessage = async() => { + this.recordingCanceled = true; + await AudioRecorder.stopRecording(); + return this._finishRecording(false); + } + + render() { + return ( + + + + {this.state.currentTime} + + + ); + } +} diff --git a/app/containers/MessageBox/index.js b/app/containers/MessageBox/index.js index 45886561f..93678f99e 100644 --- a/app/containers/MessageBox/index.js +++ b/app/containers/MessageBox/index.js @@ -6,6 +6,7 @@ import ImagePicker from 'react-native-image-picker'; import { connect } from 'react-redux'; import { emojify } from 'react-emojione'; import { KeyboardAccessoryView } from 'react-native-keyboard-input'; + import { userTyping, layoutAnimation } from '../../actions/room'; import RocketChat from '../../lib/rocketchat'; import { editRequest, editCancel, clearInput } from '../../actions/messages'; @@ -15,8 +16,10 @@ import database from '../../lib/realm'; import Avatar from '../Avatar'; import CustomEmoji from '../EmojiPicker/CustomEmoji'; import { emojis } from '../../emojis'; +import Recording from './Recording'; import './EmojiKeyboard'; + const MENTIONS_TRACKING_TYPE_USERS = '@'; const MENTIONS_TRACKING_TYPE_EMOJIS = ':'; @@ -57,7 +60,7 @@ export default class MessageBox extends React.PureComponent { mentions: [], showMentionsContainer: false, showEmojiKeyboard: false, - trackingType: '' + recording: false }; this.users = []; this.rooms = []; @@ -138,16 +141,23 @@ export default class MessageBox extends React.PureComponent { accessibilityTraits='button' onPress={() => this.submit(this.state.text)} />); - } else { - icons.push( this.addFile()} - />); + return icons; } + icons.push( this.recordAudioMessage()} + />); + icons.push( this.addFile()} + />); return icons; } @@ -188,9 +198,25 @@ export default class MessageBox extends React.PureComponent { showEmojiKeyboard: true }); } + + async recordAudioMessage() { + const recording = await Recording.permission(); + this.setState({ recording }); + } + + finishAudioMessage = async(fileInfo) => { + if (fileInfo) { + RocketChat.sendFileMessage(this.props.rid, fileInfo); + } + this.setState({ + recording: false + }); + } + closeEmoji() { this.setState({ showEmojiKeyboard: false }); } + submit(message) { this.setState({ text: '' }); this.closeEmoji(); @@ -446,6 +472,9 @@ export default class MessageBox extends React.PureComponent { ); renderContent() { + if (this.state.recording) { + return (); + } return ( [ this.renderMentions(), diff --git a/app/containers/message/Audio.js b/app/containers/message/Audio.js index df17fa11c..d9db162a2 100644 --- a/app/containers/message/Audio.js +++ b/app/containers/message/Audio.js @@ -83,7 +83,7 @@ export default class Audio extends React.PureComponent { } onLoad(data) { - this.setState({ duration: data.duration }); + this.setState({ duration: data.duration > 0 ? data.duration : 0 }); } onProgress(data) { diff --git a/app/lib/realm.js b/app/lib/realm.js index dde3ab765..5f7d7621d 100644 --- a/app/lib/realm.js +++ b/app/lib/realm.js @@ -267,6 +267,9 @@ class DB { deleteAll(...args) { return this.database.write(() => this.database.deleteAll(...args)); } + delete(...args) { + return this.database.delete(...args); + } write(...args) { return this.database.write(...args); } diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index d1df2baa9..9d8890f8b 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -519,10 +519,16 @@ const RocketChat = { return call('sendFileMessage', rid, null, data, msg); }, async sendFileMessage(rid, fileInfo, data) { - const placeholder = RocketChat.getMessage(rid, 'Sending an image'); + const placeholder = RocketChat.getMessage(rid, 'Sending a file'); try { - const result = await RocketChat._ufsCreate({ ...fileInfo, rid }); + if (!data) { + data = await RNFetchBlob.wrap(fileInfo.path); + const fileStat = await RNFetchBlob.fs.stat(fileInfo.path); + fileInfo.size = fileStat.size; + fileInfo.name = fileStat.filename; + } + const result = await RocketChat._ufsCreate({ ...fileInfo, rid }); await RNFetchBlob.fetch('POST', result.url, { 'Content-Type': 'application/octet-stream' }, data); @@ -539,10 +545,14 @@ const RocketChat = { } catch (e) { return e; } finally { - database.write(() => { - const msg = database.objects('messages').filtered('_id = $0', placeholder._id); - database.delete(msg); - }); + try { + database.write(() => { + const msg = database.objects('messages').filtered('_id = $0', placeholder._id); + database.delete(msg); + }); + } catch (e) { + console.error(e); + } } }, async getRooms() { diff --git a/ios/RocketChatRN.xcodeproj/project.pbxproj b/ios/RocketChatRN.xcodeproj/project.pbxproj index 58e3e6371..3b7d702e7 100644 --- a/ios/RocketChatRN.xcodeproj/project.pbxproj +++ b/ios/RocketChatRN.xcodeproj/project.pbxproj @@ -5,7 +5,6 @@ }; objectVersion = 46; objects = { - /* Begin PBXBuildFile section */ 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; }; 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; }; @@ -47,6 +46,7 @@ 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; 647660C6B6A340C7BD4D1099 /* EvilIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A18EFC3B0CFE40E0918A8F0C /* EvilIcons.ttf */; }; 70A8D9B456894EFFAF027CAB /* FontAwesome.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7A30DA4B2D474348824CD05B /* FontAwesome.ttf */; }; + 74815BBCB91147C08C8F7B3D /* libRNAudio.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1142E3442BA94B19BCF52814 /* libRNAudio.a */; }; 77C35F50C01C43668188886C /* libRNVectorIcons.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A0EEFAF8AB14F5B9E796CDD /* libRNVectorIcons.a */; }; 7A430E4F20238C46008F55BC /* libRCTCustomInputController.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A430E1E20238C02008F55BC /* libRCTCustomInputController.a */; }; 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; @@ -334,6 +334,27 @@ remoteGlobalIDString = 58B5119B1A9E6C1200147676; remoteInfo = RCTText; }; + A9A6C934204DD556006B7D9D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = EBF21BDC1FC498900052F4D5; + remoteInfo = jsinspector; + }; + A9A6C936204DD556006B7D9D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = EBF21BFA1FC4989A0052F4D5; + remoteInfo = "jsinspector-tvOS"; + }; + A9A6C944204DD557006B7D9D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C21010507E5B4B37BA0E4C9D /* RNAudio.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 42F559BA1CFC90C400DC3F84; + remoteInfo = RNAudio; + }; B810DF90203B10490010C331 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4019A5E1911B4C61944FBCEC /* SafariViewManager.xcodeproj */; @@ -431,6 +452,7 @@ 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 00E356F21AD99517003FC87E /* RocketChatRNTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RocketChatRNTests.m; sourceTree = ""; }; 06BB44DD4855498082A744AD /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; + 1142E3442BA94B19BCF52814 /* libRNAudio.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNAudio.a; sourceTree = ""; }; 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = ""; }; 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = ""; }; 13B07F961A680F5B00A75B9A /* RocketChatRN.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RocketChatRN.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -474,6 +496,7 @@ B8971BAC202A091D0000D245 /* KeyboardTrackingView.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = KeyboardTrackingView.xcodeproj; path = "../node_modules/react-native-keyboard-tracking-view/lib/KeyboardTrackingView.xcodeproj"; sourceTree = ""; }; B8C682611FD84CEF003A12C8 /* icomoon.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = icomoon.ttf; path = ../resources/fonts/icomoon.ttf; sourceTree = ""; }; BAAE4B947F5D44959F0A9D5A /* libRNZeroconf.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNZeroconf.a; sourceTree = ""; }; + C21010507E5B4B37BA0E4C9D /* RNAudio.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNAudio.xcodeproj; path = "../node_modules/react-native-audio/ios/RNAudio.xcodeproj"; sourceTree = ""; }; C23AEF1D9EBE4A38A1A6B97B /* RNSVG.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNSVG.xcodeproj; path = "../node_modules/react-native-svg/ios/RNSVG.xcodeproj"; sourceTree = ""; }; DA50CE47374C4C35BE6D9D58 /* libRNSVG.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNSVG.a; sourceTree = ""; }; DC6EE17B5550465E98C70FF0 /* Entypo.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Entypo.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Entypo.ttf"; sourceTree = ""; }; @@ -520,6 +543,7 @@ 8ECBD927DDAC4987B98E102E /* libRCTVideo.a in Frameworks */, 0F026E58B8A6427D9A204D89 /* libSplashScreen.a in Frameworks */, 2C800DF680F8451599E80AF1 /* libSafariViewManager.a in Frameworks */, + 74815BBCB91147C08C8F7B3D /* libRNAudio.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -653,6 +677,8 @@ 3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */, 3DAD3EAD1DF850E9000B6D8A /* libjschelpers.a */, 3DAD3EAF1DF850E9000B6D8A /* libjschelpers.a */, + A9A6C935204DD556006B7D9D /* libjsinspector.a */, + A9A6C937204DD556006B7D9D /* libjsinspector-tvOS.a */, 607D610D1F325B7E00F639C4 /* libthird-party.a */, 607D610F1F325B7E00F639C4 /* libthird-party.a */, 607D61111F325B7E00F639C4 /* libdouble-conversion.a */, @@ -756,6 +782,7 @@ AD0379F2BCE84C968538CDAF /* RCTVideo.xcodeproj */, 30FCE1B6376C423E94C9FBB0 /* SplashScreen.xcodeproj */, 4019A5E1911B4C61944FBCEC /* SafariViewManager.xcodeproj */, + C21010507E5B4B37BA0E4C9D /* RNAudio.xcodeproj */, ); name = Libraries; sourceTree = ""; @@ -795,6 +822,14 @@ name = Products; sourceTree = ""; }; + A9A6C941204DD556006B7D9D /* Products */ = { + isa = PBXGroup; + children = ( + A9A6C945204DD557006B7D9D /* libRNAudio.a */, + ); + name = Products; + sourceTree = ""; + }; AF5E16F0398347E6A80C8CBE /* Resources */ = { isa = PBXGroup; children = ( @@ -850,6 +885,7 @@ 20CE3E407E0D4D9E8C9885F2 /* libRCTVideo.a */, B2607FA180F14E6584301101 /* libSplashScreen.a */, 1D3BB00B9ABF44EA9BD71318 /* libSafariViewManager.a */, + 1142E3442BA94B19BCF52814 /* libRNAudio.a */, ); name = "Recovered References"; sourceTree = ""; @@ -1075,6 +1111,10 @@ ProductGroup = 607D60ED1F325B7D00F639C4 /* Products */; ProjectRef = 5A8684E7C27E426C9206E980 /* RealmReact.xcodeproj */; }, + { + ProductGroup = A9A6C941204DD556006B7D9D /* Products */; + ProjectRef = C21010507E5B4B37BA0E4C9D /* RNAudio.xcodeproj */; + }, { ProductGroup = B8E79A881F3CCC6C005B464F /* Products */; ProjectRef = 4CD38E4891ED4601B7481448 /* RNFetchBlob.xcodeproj */; @@ -1367,6 +1407,27 @@ remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + A9A6C935204DD556006B7D9D /* libjsinspector.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libjsinspector.a; + remoteRef = A9A6C934204DD556006B7D9D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + A9A6C937204DD556006B7D9D /* libjsinspector-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libjsinspector-tvOS.a"; + remoteRef = A9A6C936204DD556006B7D9D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + A9A6C945204DD557006B7D9D /* libRNAudio.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRNAudio.a; + remoteRef = A9A6C944204DD557006B7D9D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; B810DF91203B10490010C331 /* libSafariViewManager.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -1618,6 +1679,7 @@ "$(SRCROOT)/../node_modules/react-native-video/ios", "$(SRCROOT)/../node_modules/react-native-splash-screen/ios", "$(SRCROOT)/../node_modules/react-native-safari-view", + "$(SRCROOT)/../node_modules/react-native-audio/ios", ); INFOPLIST_FILE = RocketChatRNTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -1630,6 +1692,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1659,6 +1722,7 @@ "$(SRCROOT)/../node_modules/react-native-video/ios", "$(SRCROOT)/../node_modules/react-native-splash-screen/ios", "$(SRCROOT)/../node_modules/react-native-safari-view", + "$(SRCROOT)/../node_modules/react-native-audio/ios", ); INFOPLIST_FILE = RocketChatRNTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -1671,6 +1735,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1705,6 +1770,7 @@ "$(SRCROOT)/../node_modules/react-native-video/ios", "$(SRCROOT)/../node_modules/react-native-splash-screen/ios", "$(SRCROOT)/../node_modules/react-native-safari-view", + "$(SRCROOT)/../node_modules/react-native-audio/ios", ); INFOPLIST_FILE = RocketChatRN/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1744,6 +1810,7 @@ "$(SRCROOT)/../node_modules/react-native-video/ios", "$(SRCROOT)/../node_modules/react-native-splash-screen/ios", "$(SRCROOT)/../node_modules/react-native-safari-view", + "$(SRCROOT)/../node_modules/react-native-audio/ios", ); INFOPLIST_FILE = RocketChatRN/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1786,6 +1853,7 @@ "$(SRCROOT)/../node_modules/react-native-video/ios", "$(SRCROOT)/../node_modules/react-native-splash-screen/ios", "$(SRCROOT)/../node_modules/react-native-safari-view", + "$(SRCROOT)/../node_modules/react-native-audio/ios", ); INFOPLIST_FILE = "RocketChatRN-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1797,6 +1865,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1836,6 +1905,7 @@ "$(SRCROOT)/../node_modules/react-native-video/ios", "$(SRCROOT)/../node_modules/react-native-splash-screen/ios", "$(SRCROOT)/../node_modules/react-native-safari-view", + "$(SRCROOT)/../node_modules/react-native-audio/ios", ); INFOPLIST_FILE = "RocketChatRN-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1847,6 +1917,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1882,6 +1953,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.RocketChatRN-tvOSTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1913,6 +1985,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.RocketChatRN-tvOSTests"; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/ios/RocketChatRN/Info.plist b/ios/RocketChatRN/Info.plist index e17929b79..0fca665fc 100644 --- a/ios/RocketChatRN/Info.plist +++ b/ios/RocketChatRN/Info.plist @@ -22,6 +22,8 @@ ???? CFBundleVersion 100 + NSMicrophoneUsageDescription + This app uses the microphone to record audio message. ITSAppUsesNonExemptEncryption LSRequiresIPhoneOS diff --git a/package-lock.json b/package-lock.json index 0059f8a70..20ddb63e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13575,6 +13575,11 @@ "prop-types": "15.6.1" } }, + "react-native-audio": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/react-native-audio/-/react-native-audio-4.0.0.tgz", + "integrity": "sha512-wJWiXgJk8vFfZPSP4wC9NaCquv2wYOb+K76oPytYxJlRGplKrtD9JY0bIkXp7jbIIDubj3yebb5f8xpYhirIpg==" + }, "react-native-compat": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/react-native-compat/-/react-native-compat-1.0.0.tgz", @@ -13875,9 +13880,9 @@ } }, "react-navigation": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/react-navigation/-/react-navigation-1.2.1.tgz", - "integrity": "sha512-3TblYWMqu8nvihXHP5x0nxktLuAz1uLiGZaAX3YobX8aGIWxPdSrPS9PGAoSkSalMG3BtGEwUKYqH2RSY1pi3A==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/react-navigation/-/react-navigation-1.4.0.tgz", + "integrity": "sha512-jm9dYLARRq7T7AQ4MKNsl+ZAFnHwl+UIl7be4grBnPycJJrjXVmpng/GqTjeRfNHjzKhXO/mXWKuAoOW1SiO4A==", "requires": { "clamp": "1.0.1", "hoist-non-react-statics": "2.5.0", diff --git a/package.json b/package.json index 141801f34..7aab8db1a 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "react-native-action-button": "^2.8.3", "react-native-actionsheet": "^2.3.0", "react-native-animatable": "^1.2.4", + "react-native-audio": "^4.0.0", "react-native-easy-markdown": "git+https://github.com/diegolmello/react-native-easy-markdown.git", "react-native-fetch-blob": "^0.10.8", "react-native-image-picker": "^0.26.7",