[IMPROVE] Disable Jitsi native module on Android (#4708)
* temp: disable jitsi on android * update props and subscription * add open intent * add request permissions * disable react-native-jitsi-meet on android and separate implementations * fix ios * fix import alias * revert android manifest indentation * add catch to method * return comment * remove is iOS * fix queries * remove unused data * webview audio * fix android permissions * fix audio android * change how to open jitsi app * remove loading * update close logic
This commit is contained in:
parent
057ca8afac
commit
a8b3a3b7de
|
@ -2,7 +2,7 @@ module.exports = {
|
|||
settings: {
|
||||
'import/resolver': {
|
||||
node: {
|
||||
extensions: ['.ts', '.tsx', '.js', '.ios.js', '.android.js', '.native.js']
|
||||
extensions: ['.ts', '.tsx', '.js', '.ios.js', '.android.js', '.native.js', '.ios.tsx', '.android.tsx']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -357,9 +357,6 @@ dependencies {
|
|||
playImplementation project(':@react-native-firebase_app')
|
||||
playImplementation project(':@react-native-firebase_analytics')
|
||||
playImplementation project(':@react-native-firebase_crashlytics')
|
||||
implementation(project(':react-native-jitsi-meet')) { // https://github.com/skrafft/react-native-jitsi-meet#side-note
|
||||
exclude group: 'com.facebook.react',module:'react-native-svg'
|
||||
}
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
|
||||
//noinspection GradleDynamicVersion
|
||||
|
|
|
@ -5,6 +5,12 @@
|
|||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.VIDEO_CAPTURE" />
|
||||
<uses-permission android:name="android.permission.AUDIO_CAPTURE" />
|
||||
|
||||
<application
|
||||
android:name="chat.rocket.reactnative.MainApplication"
|
||||
android:allowBackup="false"
|
||||
|
@ -14,6 +20,7 @@
|
|||
android:requestLegacyExternalStorage="true"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/BootTheme"
|
||||
android:hardwareAccelerated="true"
|
||||
tools:replace="android:allowBackup">
|
||||
<activity
|
||||
android:name="chat.rocket.reactnative.MainActivity"
|
||||
|
@ -69,5 +76,10 @@
|
|||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
<queries>
|
||||
<package android:name="org.jitsi.meet" />
|
||||
<intent>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
</intent>
|
||||
</queries>
|
||||
</manifest>
|
||||
|
|
|
@ -26,8 +26,6 @@ buildscript {
|
|||
kotlinVersion = '1.6.10'
|
||||
supportLibVersion = "28.0.0"
|
||||
libre_build = !(isPlay.toBoolean())
|
||||
jitsi_url = "https://github.com/RocketChat/jitsi-maven-repository/raw/master/releases"
|
||||
jitsi_version = "3.7.0"
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
@ -68,9 +66,6 @@ allprojects {
|
|||
url "$rootDir/../node_modules/detox/Detox-android"
|
||||
}
|
||||
|
||||
maven {
|
||||
url jitsi_url
|
||||
}
|
||||
mavenCentral {
|
||||
content {
|
||||
excludeGroup "com.facebook.react"
|
||||
|
|
|
@ -1,14 +1,22 @@
|
|||
import navigation from '../navigation/appNavigation';
|
||||
import openLink from './helpers/openLink';
|
||||
import { Services } from '../services';
|
||||
import log from './helpers/log';
|
||||
import { showErrorAlert } from './helpers';
|
||||
import { PermissionsAndroid } from 'react-native';
|
||||
|
||||
import i18n from '../../i18n';
|
||||
import navigation from '../navigation/appNavigation';
|
||||
import { Services } from '../services';
|
||||
import { isAndroid, showErrorAlert } from './helpers';
|
||||
import log from './helpers/log';
|
||||
import openLink from './helpers/openLink';
|
||||
|
||||
export const videoConfJoin = async (callId: string, cam: boolean) => {
|
||||
try {
|
||||
const result = await Services.videoConferenceJoin(callId, cam);
|
||||
if (result.success) {
|
||||
if (isAndroid) {
|
||||
await PermissionsAndroid.requestMultiple([
|
||||
PermissionsAndroid.PERMISSIONS.CAMERA,
|
||||
PermissionsAndroid.PERMISSIONS.RECORD_AUDIO
|
||||
]);
|
||||
}
|
||||
const { url, providerName } = result;
|
||||
if (providerName === 'jitsi') {
|
||||
navigation.navigate('JitsiMeetView', { url, onlyAudio: !cam, videoConf: true });
|
||||
|
|
|
@ -80,6 +80,7 @@ import {
|
|||
ProfileStackParamList,
|
||||
SettingsStackParamList
|
||||
} from './types';
|
||||
import { isIOS } from '../lib/methods/helpers';
|
||||
|
||||
// ChatsStackNavigator
|
||||
const ChatsStack = createStackNavigator<ChatsStackParamList>();
|
||||
|
@ -135,7 +136,11 @@ const ChatsStackNavigator = () => {
|
|||
<ChatsStack.Screen name='QueueListView' component={QueueListView} />
|
||||
<ChatsStack.Screen name='CannedResponsesListView' component={CannedResponsesListView} />
|
||||
<ChatsStack.Screen name='CannedResponseDetail' component={CannedResponseDetail} />
|
||||
<ChatsStack.Screen name='JitsiMeetView' component={JitsiMeetView} options={{ headerShown: false }} />
|
||||
<ChatsStack.Screen
|
||||
name='JitsiMeetView'
|
||||
component={JitsiMeetView}
|
||||
options={{ headerShown: false, animationEnabled: isIOS }}
|
||||
/>
|
||||
</ChatsStack.Navigator>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -73,6 +73,7 @@ import {
|
|||
MasterDetailInsideStackParamList,
|
||||
ModalStackParamList
|
||||
} from './types';
|
||||
import { isIOS } from '../../lib/methods/helpers';
|
||||
|
||||
// ChatsStackNavigator
|
||||
const ChatsStack = createStackNavigator<MasterDetailChatsStackParamList>();
|
||||
|
@ -222,7 +223,11 @@ const InsideStackNavigator = React.memo(() => {
|
|||
<InsideStack.Screen name='ModalStackNavigator' component={ModalStackNavigator} options={{ headerShown: false }} />
|
||||
<InsideStack.Screen name='AttachmentView' component={AttachmentView} />
|
||||
<InsideStack.Screen name='ModalBlockView' component={ModalBlockView} options={ModalBlockView.navigationOptions} />
|
||||
<InsideStack.Screen name='JitsiMeetView' component={JitsiMeetView} options={{ headerShown: false }} />
|
||||
<InsideStack.Screen
|
||||
name='JitsiMeetView'
|
||||
component={JitsiMeetView}
|
||||
options={{ headerShown: false, animationEnabled: isIOS }}
|
||||
/>
|
||||
<InsideStack.Screen name='ShareView' component={ShareView} />
|
||||
</InsideStack.Navigator>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
import React from 'react';
|
||||
import { BackHandler, NativeEventSubscription } from 'react-native';
|
||||
import BackgroundTimer from 'react-native-background-timer';
|
||||
import { isAppInstalled, openAppWithUri } from 'react-native-send-intent';
|
||||
import WebView from 'react-native-webview';
|
||||
import { WebViewMessage, WebViewNavigation } from 'react-native-webview/lib/WebViewTypes';
|
||||
|
||||
import { IBaseScreen } from '../definitions';
|
||||
import { events, logEvent } from '../lib/methods/helpers/log';
|
||||
import { Services } from '../lib/services';
|
||||
import { ChatsStackParamList } from '../stacks/types';
|
||||
import { withTheme } from '../theme';
|
||||
|
||||
const JITSI_INTENT = 'org.jitsi.meet';
|
||||
|
||||
type TJitsiMeetViewProps = IBaseScreen<ChatsStackParamList, 'JitsiMeetView'>;
|
||||
|
||||
class JitsiMeetView extends React.Component<TJitsiMeetViewProps> {
|
||||
private rid: string;
|
||||
private url: string;
|
||||
private videoConf: boolean;
|
||||
private jitsiTimeout: number | null;
|
||||
private backHandler!: NativeEventSubscription;
|
||||
|
||||
constructor(props: TJitsiMeetViewProps) {
|
||||
super(props);
|
||||
this.rid = props.route.params?.rid;
|
||||
this.url = props.route.params?.url;
|
||||
this.videoConf = !!props.route.params?.videoConf;
|
||||
this.jitsiTimeout = null;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { route, navigation } = this.props;
|
||||
isAppInstalled(JITSI_INTENT)
|
||||
.then(function (isInstalled) {
|
||||
if (isInstalled) {
|
||||
const callUrl = route.params.url.replace(/^https?:\/\//, '').split('#')[0];
|
||||
openAppWithUri(`intent://${callUrl}#Intent;scheme=${JITSI_INTENT};package=${JITSI_INTENT};end`)
|
||||
.then(() => navigation.pop())
|
||||
.catch(() => {});
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
this.onConferenceJoined();
|
||||
this.backHandler = BackHandler.addEventListener('hardwareBackPress', () => true);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
logEvent(this.videoConf ? events.LIVECHAT_VIDEOCONF_TERMINATE : events.JM_CONFERENCE_TERMINATE);
|
||||
if (this.jitsiTimeout && !this.videoConf) {
|
||||
BackgroundTimer.clearInterval(this.jitsiTimeout);
|
||||
this.jitsiTimeout = null;
|
||||
BackgroundTimer.stopBackgroundTimer();
|
||||
}
|
||||
this.backHandler.remove();
|
||||
}
|
||||
|
||||
// Jitsi Update Timeout needs to be called every 10 seconds to make sure
|
||||
// call is not ended and is available to web users.
|
||||
onConferenceJoined = () => {
|
||||
logEvent(this.videoConf ? events.LIVECHAT_VIDEOCONF_JOIN : events.JM_CONFERENCE_JOIN);
|
||||
if (this.rid && !this.videoConf) {
|
||||
Services.updateJitsiTimeout(this.rid).catch((e: unknown) => console.log(e));
|
||||
if (this.jitsiTimeout) {
|
||||
BackgroundTimer.clearInterval(this.jitsiTimeout);
|
||||
BackgroundTimer.stopBackgroundTimer();
|
||||
this.jitsiTimeout = null;
|
||||
}
|
||||
this.jitsiTimeout = BackgroundTimer.setInterval(() => {
|
||||
Services.updateJitsiTimeout(this.rid).catch((e: unknown) => console.log(e));
|
||||
}, 10000);
|
||||
}
|
||||
};
|
||||
|
||||
onNavigationStateChange = (webViewState: WebViewNavigation | WebViewMessage) => {
|
||||
const { navigation, route } = this.props;
|
||||
const jitsiRoomId = route.params.url
|
||||
?.split(/^https?:\/\//)[1]
|
||||
?.split('#')[0]
|
||||
?.split('/')[1];
|
||||
if ((jitsiRoomId && !webViewState.url.includes(jitsiRoomId)) || webViewState.url.includes('close')) {
|
||||
navigation.pop();
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<WebView
|
||||
source={{ uri: `${this.url}&config.disableDeepLinking=true` }}
|
||||
onMessage={({ nativeEvent }) => this.onNavigationStateChange(nativeEvent)}
|
||||
onNavigationStateChange={this.onNavigationStateChange}
|
||||
style={{ flex: 1 }}
|
||||
javaScriptEnabled
|
||||
domStorageEnabled
|
||||
mediaPlaybackRequiresUserAction={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme(JitsiMeetView);
|
|
@ -0,0 +1,5 @@
|
|||
import React from 'react';
|
||||
|
||||
declare const JitsiMeetView: React.SFC<>;
|
||||
|
||||
export default JitsiMeetView;
|
|
@ -1,17 +1,16 @@
|
|||
import React from 'react';
|
||||
import { BackHandler, StyleSheet } from 'react-native';
|
||||
import JitsiMeet, { JitsiMeetView as RNJitsiMeetView } from 'react-native-jitsi-meet';
|
||||
import { StyleSheet } from 'react-native';
|
||||
import BackgroundTimer from 'react-native-background-timer';
|
||||
import JitsiMeet, { JitsiMeetView as RNJitsiMeetView } from 'react-native-jitsi-meet';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { getUserSelector } from '../selectors/login';
|
||||
import ActivityIndicator from '../containers/ActivityIndicator';
|
||||
import RCActivityIndicator from '../containers/ActivityIndicator';
|
||||
import { IApplicationState, IBaseScreen, IUser } from '../definitions';
|
||||
import { events, logEvent } from '../lib/methods/helpers/log';
|
||||
import { isAndroid, isIOS } from '../lib/methods/helpers';
|
||||
import { withTheme } from '../theme';
|
||||
import { ChatsStackParamList } from '../stacks/types';
|
||||
import { IApplicationState, IUser, IBaseScreen } from '../definitions';
|
||||
import { Services } from '../lib/services';
|
||||
import { getUserSelector } from '../selectors/login';
|
||||
import { ChatsStackParamList } from '../stacks/types';
|
||||
import { withTheme } from '../theme';
|
||||
|
||||
const formatUrl = (url: string, baseUrl: string, uriSize: number, avatarAuthURLFragment: string) =>
|
||||
`${baseUrl}/avatar/${url}?format=png&width=${uriSize}&height=${uriSize}${avatarAuthURLFragment}`;
|
||||
|
@ -60,20 +59,14 @@ class JitsiMeetView extends React.Component<IJitsiMeetViewProps, IJitsiMeetViewS
|
|||
const { userInfo } = this.state;
|
||||
|
||||
setTimeout(() => {
|
||||
const onlyAudio = route.params?.onlyAudio ?? false;
|
||||
if (onlyAudio) {
|
||||
JitsiMeet.audioCall(this.url, userInfo);
|
||||
} else {
|
||||
JitsiMeet.call(this.url, userInfo);
|
||||
}
|
||||
this.setState({ loading: false });
|
||||
}, 1000);
|
||||
|
||||
if (isIOS) {
|
||||
setTimeout(() => {
|
||||
const onlyAudio = route.params?.onlyAudio ?? false;
|
||||
if (onlyAudio) {
|
||||
JitsiMeet.audioCall(this.url, userInfo);
|
||||
} else {
|
||||
JitsiMeet.call(this.url, userInfo);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
BackHandler.addEventListener('hardwareBackPress', () => null);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
|
@ -83,16 +76,8 @@ class JitsiMeetView extends React.Component<IJitsiMeetViewProps, IJitsiMeetViewS
|
|||
this.jitsiTimeout = null;
|
||||
BackgroundTimer.stopBackgroundTimer();
|
||||
}
|
||||
BackHandler.removeEventListener('hardwareBackPress', () => null);
|
||||
if (isIOS) {
|
||||
JitsiMeet.endCall();
|
||||
}
|
||||
}
|
||||
|
||||
endCall = () => {
|
||||
JitsiMeet.endCall();
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
onConferenceWillJoin = () => {
|
||||
this.setState({ loading: false });
|
||||
|
@ -117,8 +102,8 @@ class JitsiMeetView extends React.Component<IJitsiMeetViewProps, IJitsiMeetViewS
|
|||
};
|
||||
|
||||
onConferenceTerminated = () => {
|
||||
logEvent(this.videoConf ? events.LIVECHAT_VIDEOCONF_TERMINATE : events.JM_CONFERENCE_TERMINATE);
|
||||
const { navigation } = this.props;
|
||||
logEvent(this.videoConf ? events.LIVECHAT_VIDEOCONF_TERMINATE : events.JM_CONFERENCE_TERMINATE);
|
||||
// fix to go back when the call ends
|
||||
setTimeout(() => {
|
||||
JitsiMeet.endCall();
|
||||
|
@ -127,10 +112,8 @@ class JitsiMeetView extends React.Component<IJitsiMeetViewProps, IJitsiMeetViewS
|
|||
};
|
||||
|
||||
render() {
|
||||
const { userInfo, loading } = this.state;
|
||||
const { route } = this.props;
|
||||
const onlyAudio = route.params?.onlyAudio ?? false;
|
||||
const options = isAndroid ? { url: this.url, userInfo, audioOnly: onlyAudio } : null;
|
||||
const { loading } = this.state;
|
||||
|
||||
return (
|
||||
<>
|
||||
<RNJitsiMeetView
|
||||
|
@ -138,9 +121,9 @@ class JitsiMeetView extends React.Component<IJitsiMeetViewProps, IJitsiMeetViewS
|
|||
onConferenceTerminated={this.onConferenceTerminated}
|
||||
onConferenceJoined={this.onConferenceJoined}
|
||||
style={StyleSheet.absoluteFill}
|
||||
options={options}
|
||||
options={null}
|
||||
/>
|
||||
{loading ? <ActivityIndicator /> : null}
|
||||
{loading ? <RCActivityIndicator absolute size='large' /> : null}
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -118,6 +118,7 @@
|
|||
"react-native-safe-area-context": "3.2.0",
|
||||
"react-native-screens": "3.13.1",
|
||||
"react-native-scrollable-tab-view": "ptomasroos/react-native-scrollable-tab-view",
|
||||
"react-native-send-intent": "^1.3.0",
|
||||
"react-native-simple-crypto": "RocketChat/react-native-simple-crypto#0.5.1",
|
||||
"react-native-skeleton-placeholder": "^5.2.3",
|
||||
"react-native-slowlog": "^1.0.2",
|
||||
|
|
|
@ -14,6 +14,11 @@ module.exports = {
|
|||
platforms: {
|
||||
android: null
|
||||
}
|
||||
},
|
||||
'react-native-jitsi-meet': {
|
||||
platforms: {
|
||||
android: null
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -17330,6 +17330,11 @@ react-native-scrollable-tab-view@ptomasroos/react-native-scrollable-tab-view:
|
|||
prop-types "^15.6.0"
|
||||
react-timer-mixin "^0.13.3"
|
||||
|
||||
react-native-send-intent@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/react-native-send-intent/-/react-native-send-intent-1.3.0.tgz#d8c7898827da1b8b10e25a645ce6802d1a0b440c"
|
||||
integrity sha512-ODTX7BHITFxdcAL0K2iHfa3qVYnqG8GPcv1NbLBNC1DyCaOSJiiGtVH6Kc5YBqzQ8+1pV9uN5nfQ5wyFgiq74g==
|
||||
|
||||
react-native-simple-crypto@RocketChat/react-native-simple-crypto#0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://codeload.github.com/RocketChat/react-native-simple-crypto/tar.gz/dcf6eef5359c739d521371918e13a73f2ea6cb42"
|
||||
|
|
Loading…
Reference in New Issue