mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2025-12-30 03:12:29 +00:00
feat(prejoin) add unsafe room name warning
This commit is contained in:
@@ -870,9 +870,11 @@
|
||||
"lookGood": "Your microphone is working properly",
|
||||
"or": "or",
|
||||
"premeeting": "Pre meeting",
|
||||
"proceedAnyway": "Proceed anyway",
|
||||
"screenSharingError": "Screen sharing error:",
|
||||
"showScreen": "Enable pre meeting screen",
|
||||
"startWithPhone": "Start with phone audio",
|
||||
"unsafeRoomConsent": "I understand the risks, I want to join the meeting",
|
||||
"videoOnlyError": "Video error:",
|
||||
"videoTrackError": "Could not create video track.",
|
||||
"viewAllNumbers": "view all numbers"
|
||||
@@ -974,8 +976,14 @@
|
||||
"security": {
|
||||
"about": "You can add a $t(lockRoomPassword) to your meeting. Participants will need to provide the $t(lockRoomPassword) before they are allowed to join the meeting.",
|
||||
"aboutReadOnly": "Moderator participants can add a $t(lockRoomPassword) to the meeting. Participants will need to provide the $t(lockRoomPassword) before they are allowed to join the meeting.",
|
||||
"insecureRoomNameWarning": "The room name is unsafe. Unwanted participants may join your conference. Consider securing your meeting using the security button.",
|
||||
"title": "Security Options"
|
||||
"insecureRoomNameWarningNative": "The room name is unsafe. Unwanted participants may join your meeting. {{recommendAction}} Learn more about securing you meeting ",
|
||||
"insecureRoomNameWarningWeb": "The room name is unsafe. Unwanted participants may join your meeting. {{recommendAction}} Learn more about securing you meeting <a href=\"{{securityUrl}}\" rel=\"security\" target=\"_blank\">here</a>.",
|
||||
"title": "Security Options",
|
||||
"unsafeRoomActions": {
|
||||
"meeting": "Consider securing your meeting using the security button.",
|
||||
"prejoin": "Consider using a more unique meeting name.",
|
||||
"welcome": "Consider using a more unique meeting name, or pick one of the suggestions."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"audio": "Audio",
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
import { connect, disconnect, setLocationURL } from '../base/connection/actions';
|
||||
import { loadConfig } from '../base/lib-jitsi-meet/functions.native';
|
||||
import { createDesiredLocalTracks } from '../base/tracks/actions';
|
||||
import isInsecureRoomName from '../base/util/isInsecureRoomName';
|
||||
import { parseURLParams } from '../base/util/parseURLParams';
|
||||
import {
|
||||
appendURLParam,
|
||||
@@ -136,6 +137,11 @@ export function appNavigate(uri?: string, options: IReloadNowOptions = {}) {
|
||||
dispatch(setRoom(room));
|
||||
|
||||
if (room) {
|
||||
if (isInsecureRoomName(room)) {
|
||||
navigateRoot(screen.unsafeRoomWarning);
|
||||
|
||||
return;
|
||||
}
|
||||
dispatch(createDesiredLocalTracks());
|
||||
dispatch(clearNotifications());
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import '../base/devices/reducer';
|
||||
import '../base/premeeting/reducer';
|
||||
import '../base/tooltip/reducer';
|
||||
import '../e2ee/reducer';
|
||||
import '../face-landmarks/reducer';
|
||||
|
||||
@@ -20,6 +20,7 @@ import { ILoggingState } from '../base/logging/reducer';
|
||||
import { IMediaState } from '../base/media/reducer';
|
||||
import { INetInfoState } from '../base/net-info/reducer';
|
||||
import { IParticipantsState } from '../base/participants/reducer';
|
||||
import { IPreMeetingState } from '../base/premeeting/types';
|
||||
import { IResponsiveUIState } from '../base/responsive-ui/reducer';
|
||||
import { ISettingsState } from '../base/settings/reducer';
|
||||
import { ISoundsState } from '../base/sounds/reducer';
|
||||
@@ -110,6 +111,7 @@ export interface IReduxState {
|
||||
'features/base/net-info': INetInfoState;
|
||||
'features/base/no-src-data': INoSrcDataState;
|
||||
'features/base/participants': IParticipantsState;
|
||||
'features/base/premeeting': IPreMeetingState;
|
||||
'features/base/responsive-ui': IResponsiveUIState;
|
||||
'features/base/settings': ISettingsState;
|
||||
'features/base/sounds': ISoundsState;
|
||||
|
||||
@@ -408,6 +408,7 @@ export interface IConfig {
|
||||
legalUrls?: {
|
||||
helpCentre: string;
|
||||
privacy: string;
|
||||
security: string;
|
||||
terms: string;
|
||||
};
|
||||
liveStreaming?: {
|
||||
|
||||
9
react/features/base/premeeting/actionTypes.ts
Normal file
9
react/features/base/premeeting/actionTypes.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Type for setting the user's consent for unsafe room joining.
|
||||
*
|
||||
* {
|
||||
* type: SET_UNSAFE_ROOM_CONSENT,
|
||||
* consent: boolean
|
||||
* }
|
||||
*/
|
||||
export const SET_UNSAFE_ROOM_CONSENT = 'SET_UNSAFE_ROOM_CONSENT'
|
||||
17
react/features/base/premeeting/actions.web.ts
Normal file
17
react/features/base/premeeting/actions.web.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { SET_UNSAFE_ROOM_CONSENT } from './actionTypes';
|
||||
|
||||
/**
|
||||
* Sets the consent of the user for joining the unsafe room.
|
||||
*
|
||||
* @param {boolean} consent - The user's consent.
|
||||
* @returns {{
|
||||
* type: SET_UNSAFE_ROOM_CONSENT,
|
||||
* consent: boolean
|
||||
* }}
|
||||
*/
|
||||
export function setUnsafeRoomConsent(consent: boolean) {
|
||||
return {
|
||||
type: SET_UNSAFE_ROOM_CONSENT,
|
||||
consent
|
||||
};
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
|
||||
import ConnectionStatus from './ConnectionStatus';
|
||||
import Preview from './Preview';
|
||||
import UnsafeRoomWarning from './UnsafeRoomWarning';
|
||||
|
||||
interface IProps {
|
||||
|
||||
@@ -56,6 +57,11 @@ interface IProps {
|
||||
*/
|
||||
showDeviceStatus: boolean;
|
||||
|
||||
/**
|
||||
* If should show unsafe room warning when joining.
|
||||
*/
|
||||
showUnsafeRoomWarning?: boolean;
|
||||
|
||||
/**
|
||||
* The 'Skip prejoin' button to be rendered (if any).
|
||||
*/
|
||||
@@ -161,6 +167,7 @@ const PreMeetingScreen = ({
|
||||
children,
|
||||
className,
|
||||
showDeviceStatus,
|
||||
showUnsafeRoomWarning,
|
||||
skipPrejoinButton,
|
||||
title,
|
||||
videoMuted,
|
||||
@@ -191,6 +198,7 @@ const PreMeetingScreen = ({
|
||||
{children}
|
||||
{_buttons.length && <Toolbox toolbarButtons = { _buttons } />}
|
||||
{skipPrejoinButton}
|
||||
{showUnsafeRoomWarning && <UnsafeRoomWarning />}
|
||||
{showDeviceStatus && <DeviceStatus />}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { IReduxState } from '../../../../app/types';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
import Checkbox from '../../../ui/components/web/Checkbox';
|
||||
import getUnsafeRoomText from '../../../util/getUnsafeRoomText.web';
|
||||
import { setUnsafeRoomConsent } from '../../actions.web';
|
||||
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
warning: {
|
||||
backgroundColor: theme.palette.warning01,
|
||||
color: theme.palette.text04,
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
padding: theme.spacing(3),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
marginBottom: theme.spacing(3)
|
||||
},
|
||||
consent: {
|
||||
padding: `0 ${theme.spacing(3)}`,
|
||||
'@media (max-width: 720px)': {
|
||||
marginBottom: theme.spacing(3)
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const UnsafeRoomWarning = () => {
|
||||
const { t } = useTranslation();
|
||||
const { classes } = useStyles();
|
||||
const dispatch = useDispatch();
|
||||
const { unsafeRoomConsent } = useSelector((state: IReduxState) => state['features/base/premeeting']);
|
||||
const toggleConsent = useCallback(
|
||||
() => dispatch(setUnsafeRoomConsent(!unsafeRoomConsent))
|
||||
, [ unsafeRoomConsent, dispatch ]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className = { classes.warning }>
|
||||
{getUnsafeRoomText(t, 'prejoin')}
|
||||
</div>
|
||||
<Checkbox
|
||||
checked = { unsafeRoomConsent }
|
||||
className = { classes.consent }
|
||||
label = { t('prejoin.unsafeRoomConsent') }
|
||||
onChange = { toggleConsent } />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default UnsafeRoomWarning;
|
||||
33
react/features/base/premeeting/reducer.web.ts
Normal file
33
react/features/base/premeeting/reducer.web.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import ReducerRegistry from '../redux/ReducerRegistry';
|
||||
|
||||
import { SET_UNSAFE_ROOM_CONSENT } from './actionTypes';
|
||||
import { IPreMeetingState } from './types';
|
||||
|
||||
|
||||
const DEFAULT_STATE: IPreMeetingState = {
|
||||
unsafeRoomConsent: false
|
||||
};
|
||||
|
||||
/**
|
||||
* Listen for actions which changes the state of known and used devices.
|
||||
*
|
||||
* @param {IDevicesState} state - The Redux state of the feature features/base/devices.
|
||||
* @param {Object} action - Action object.
|
||||
* @param {string} action.type - Type of action.
|
||||
* @returns {IPreMeetingState}
|
||||
*/
|
||||
ReducerRegistry.register<IPreMeetingState>(
|
||||
'features/base/premeeting',
|
||||
(state = DEFAULT_STATE, action): IPreMeetingState => {
|
||||
switch (action.type) {
|
||||
case SET_UNSAFE_ROOM_CONSENT: {
|
||||
return {
|
||||
...state,
|
||||
unsafeRoomConsent: action.consent
|
||||
};
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
});
|
||||
|
||||
3
react/features/base/premeeting/types.ts
Normal file
3
react/features/base/premeeting/types.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export interface IPreMeetingState {
|
||||
unsafeRoomConsent?: boolean;
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactElement } from 'react';
|
||||
|
||||
import { HIDE_TOOLTIP, SHOW_TOOLTIP } from './actionTypes';
|
||||
|
||||
/**
|
||||
@@ -7,7 +9,7 @@ import { HIDE_TOOLTIP, SHOW_TOOLTIP } from './actionTypes';
|
||||
* Used as unique identifier for tooltip.
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function showTooltip(content: string) {
|
||||
export function showTooltip(content: string | ReactElement) {
|
||||
return {
|
||||
type: SHOW_TOOLTIP,
|
||||
content
|
||||
@@ -21,7 +23,7 @@ export function showTooltip(content: string) {
|
||||
* Used as unique identifier for tooltip.
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function hideTooltip(content: string) {
|
||||
export function hideTooltip(content: string | ReactElement) {
|
||||
return {
|
||||
type: HIDE_TOOLTIP,
|
||||
content
|
||||
|
||||
@@ -16,7 +16,7 @@ const ANIMATION_DURATION = 0.2;
|
||||
interface IProps {
|
||||
children: ReactElement;
|
||||
containerClassName?: string;
|
||||
content: string;
|
||||
content: string | ReactElement;
|
||||
position?: TOOLTIP_POSITION;
|
||||
}
|
||||
|
||||
|
||||
@@ -167,6 +167,7 @@ export const font = {
|
||||
|
||||
export const shape = {
|
||||
borderRadius: 6,
|
||||
circleRadius: 50,
|
||||
boxShadow: 'inset 0px -1px 0px rgba(255, 255, 255, 0.15)'
|
||||
};
|
||||
|
||||
|
||||
1
react/features/base/util/contants.ts
Normal file
1
react/features/base/util/contants.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const SECURITY_URL = 'https://jitsi.org/security/';
|
||||
31
react/features/base/util/getUnsafeRoomText.native.ts
Normal file
31
react/features/base/util/getUnsafeRoomText.native.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
import { Text } from 'react-native';
|
||||
|
||||
|
||||
import { IReduxState } from '../../app/types';
|
||||
import Link from '../react/components/native/Link';
|
||||
import BaseTheme from '../ui/components/BaseTheme.native';
|
||||
|
||||
import { SECURITY_URL } from './contants';
|
||||
|
||||
/**
|
||||
* Gets the unsafe room text for the given context.
|
||||
*
|
||||
* @param {IReduxState} state - The redux state.
|
||||
* @param {Function} t - The translation function.
|
||||
* @param {'meeting'|'prejoin'|'welcome'} context - The given context of the warining.
|
||||
* @returns {Text}
|
||||
*/
|
||||
export default function getUnsafeRoomText(state: IReduxState, t: Function, context: 'meeting' | 'prejoin' | 'welcome') {
|
||||
const securityUrl = state['features/base/config'].legalUrls?.security ?? SECURITY_URL;
|
||||
const link = React.createElement(Link, {
|
||||
url: securityUrl,
|
||||
children: 'here',
|
||||
style: { color: BaseTheme.palette.action01 } });
|
||||
|
||||
const options = {
|
||||
recommendAction: t(`security.unsafeRoomActions.${context}`)
|
||||
};
|
||||
|
||||
return React.createElement(Text, { children: [ t('security.insecureRoomNameWarningNative', options), link, '.' ] });
|
||||
}
|
||||
20
react/features/base/util/getUnsafeRoomText.web.ts
Normal file
20
react/features/base/util/getUnsafeRoomText.web.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { translateToHTML } from '../i18n/functions';
|
||||
|
||||
import { SECURITY_URL } from './contants';
|
||||
|
||||
/**
|
||||
* Gets the unsafe room text for the given context.
|
||||
*
|
||||
* @param {Function} t - The translation function.
|
||||
* @param {'meeting'|'prejoin'|'welcome'} context - The given context of the warining.
|
||||
* @returns {string}
|
||||
*/
|
||||
export default function getUnsafeRoomText(t: Function, context: 'meeting' | 'prejoin' | 'welcome') {
|
||||
const securityUrl = APP.store.getState()['features/base/config'].legalUrls?.security ?? SECURITY_URL;
|
||||
const options = {
|
||||
recommendAction: t(`security.unsafeRoomActions.${context}`),
|
||||
securityUrl
|
||||
};
|
||||
|
||||
return translateToHTML(t, 'security.insecureRoomNameWarningWeb', options);
|
||||
}
|
||||
@@ -1,17 +1,22 @@
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import ExpandedLabel, { IProps as AbstractProps } from '../../../base/label/components/native/ExpandedLabel';
|
||||
import getUnsafeRoomText from '../../../base/util/getUnsafeRoomText.native';
|
||||
|
||||
import { INSECURE_ROOM_NAME_LABEL_COLOR } from './styles';
|
||||
|
||||
type Props = AbstractProps & WithTranslation;
|
||||
interface IProps extends AbstractProps, WithTranslation {
|
||||
getUnsafeRoomTextFn: Function;
|
||||
}
|
||||
|
||||
/**
|
||||
* A react {@code Component} that implements an expanded label as tooltip-like
|
||||
* component to explain the meaning of the {@code InsecureRoomNameExpandedLabel}.
|
||||
*/
|
||||
class InsecureRoomNameExpandedLabel extends ExpandedLabel<Props> {
|
||||
class InsecureRoomNameExpandedLabel extends ExpandedLabel<IProps> {
|
||||
/**
|
||||
* Returns the color this expanded label should be rendered with.
|
||||
*
|
||||
@@ -27,8 +32,20 @@ class InsecureRoomNameExpandedLabel extends ExpandedLabel<Props> {
|
||||
* @returns {string}
|
||||
*/
|
||||
_getLabel() {
|
||||
return this.props.t('security.insecureRoomNameWarning');
|
||||
return this.props.getUnsafeRoomTextFn(this.props.t);
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(InsecureRoomNameExpandedLabel);
|
||||
/**
|
||||
* Maps part of the Redux state to the props of this component.
|
||||
*
|
||||
* @param {Object} state - The Redux state.
|
||||
* @returns {IProps}
|
||||
*/
|
||||
function _mapStateToProps(state: IReduxState) {
|
||||
return {
|
||||
getUnsafeRoomTextFn: (t: Function) => getUnsafeRoomText(state, t, 'meeting')
|
||||
};
|
||||
}
|
||||
|
||||
export default translate(connect(_mapStateToProps)(InsecureRoomNameExpandedLabel));
|
||||
@@ -6,6 +6,7 @@ import { IconExclamationTriangle } from '../../../base/icons/svg';
|
||||
import Label from '../../../base/label/components/web/Label';
|
||||
import { COLORS } from '../../../base/label/constants';
|
||||
import Tooltip from '../../../base/tooltip/components/Tooltip';
|
||||
import getUnsafeRoomText from '../../../base/util/getUnsafeRoomText.web';
|
||||
import AbstractInsecureRoomNameLabel, { _mapStateToProps } from '../AbstractInsecureRoomNameLabel';
|
||||
|
||||
/**
|
||||
@@ -20,7 +21,7 @@ class InsecureRoomNameLabel extends AbstractInsecureRoomNameLabel {
|
||||
_render() {
|
||||
return (
|
||||
<Tooltip
|
||||
content = { this.props.t('security.insecureRoomNameWarning') }
|
||||
content = { getUnsafeRoomText(this.props.t, 'meeting') }
|
||||
position = 'bottom'>
|
||||
<Label
|
||||
color = { COLORS.red }
|
||||
|
||||
@@ -7,6 +7,9 @@ import { connect } from 'react-redux';
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import DialInSummary from '../../../invite/components/dial-in-summary/native/DialInSummary';
|
||||
import Prejoin from '../../../prejoin/components/native/Prejoin';
|
||||
import UnsafeRoomWarning from '../../../prejoin/components/native/UnsafeRoomWarning';
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore
|
||||
import WelcomePage from '../../../welcome/components/WelcomePage';
|
||||
import { isWelcomePageEnabled } from '../../../welcome/functions';
|
||||
import { _ROOT_NAVIGATION_READY } from '../actionTypes';
|
||||
@@ -18,6 +21,7 @@ import {
|
||||
dialInSummaryScreenOptions,
|
||||
navigationContainerTheme,
|
||||
preJoinScreenOptions,
|
||||
unsafeMeetingScreenOptions,
|
||||
welcomeScreenOptions
|
||||
} from '../screenOptions';
|
||||
|
||||
@@ -88,6 +92,10 @@ const RootNavigationContainer = ({ dispatch, isWelcomePageAvailable }: IProps) =
|
||||
component = { Prejoin }
|
||||
name = { screen.preJoin }
|
||||
options = { preJoinScreenOptions } />
|
||||
<RootStack.Screen
|
||||
component = { UnsafeRoomWarning }
|
||||
name = { screen.unsafeRoomWarning }
|
||||
options = { unsafeMeetingScreenOptions } />
|
||||
<RootStack.Screen
|
||||
component = { ConferenceNavigationContainer }
|
||||
name = { screen.conference.root }
|
||||
|
||||
@@ -45,5 +45,6 @@ export const screen = {
|
||||
privacy: 'Privacy',
|
||||
terms: 'Terms'
|
||||
}
|
||||
}
|
||||
},
|
||||
unsafeRoomWarning: 'Unsafe Room Warning'
|
||||
};
|
||||
|
||||
@@ -196,6 +196,11 @@ export const preJoinScreenOptions = {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Screen options for pre-join screen.
|
||||
*/
|
||||
export const unsafeMeetingScreenOptions = preJoinScreenOptions;
|
||||
|
||||
/**
|
||||
* Screen options for conference navigation container screen.
|
||||
*/
|
||||
|
||||
112
react/features/prejoin/components/native/UnsafeRoomWarning.tsx
Normal file
112
react/features/prejoin/components/native/UnsafeRoomWarning.tsx
Normal file
@@ -0,0 +1,112 @@
|
||||
import React, { useCallback, useLayoutEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Platform, StyleProp, Text, TextStyle, View, ViewStyle } from 'react-native';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { appNavigate } from '../../../app/actions.native';
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { getConferenceName } from '../../../base/conference/functions';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconCloseLarge, IconWarning } from '../../../base/icons/svg';
|
||||
import JitsiScreen from '../../../base/modal/components/JitsiScreen';
|
||||
import { ASPECT_RATIO_NARROW } from '../../../base/responsive-ui/constants';
|
||||
import Button from '../../../base/ui/components/native/Button';
|
||||
import { BUTTON_TYPES } from '../../../base/ui/constants.native';
|
||||
import getUnsafeRoomText from '../../../base/util/getUnsafeRoomText.native';
|
||||
import HeaderNavigationButton from '../../../mobile/navigation/components/HeaderNavigationButton';
|
||||
import { navigateRoot } from '../../../mobile/navigation/rootNavigationContainerRef';
|
||||
import { screen } from '../../../mobile/navigation/routes';
|
||||
import { IPrejoinProps } from '../../types';
|
||||
|
||||
import { preJoinStyles as styles } from './styles';
|
||||
|
||||
const UnsafeRoomWarning: React.FC<IPrejoinProps> = ({ navigation }: IPrejoinProps) => {
|
||||
const dispatch = useDispatch();
|
||||
const { t } = useTranslation();
|
||||
const roomName = useSelector((state: IReduxState) => getConferenceName(state));
|
||||
const aspectRatio = useSelector(
|
||||
(state: IReduxState) => state['features/base/responsive-ui']?.aspectRatio
|
||||
);
|
||||
const unsafeRoomText = useSelector((state: IReduxState) => getUnsafeRoomText(state, t, 'prejoin'));
|
||||
|
||||
const goBack = useCallback(() => {
|
||||
dispatch(appNavigate(undefined));
|
||||
|
||||
return true;
|
||||
}, [ dispatch ]);
|
||||
|
||||
const onProceed = useCallback(() => {
|
||||
navigateRoot(screen.preJoin);
|
||||
|
||||
return true;
|
||||
}, [ dispatch ]);
|
||||
|
||||
const headerLeft = () => {
|
||||
if (Platform.OS === 'ios') {
|
||||
return (
|
||||
<HeaderNavigationButton
|
||||
label = { t('dialog.close') }
|
||||
onPress = { goBack } />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<HeaderNavigationButton
|
||||
onPress = { goBack }
|
||||
src = { IconCloseLarge } />
|
||||
);
|
||||
};
|
||||
|
||||
useLayoutEffect(() => {
|
||||
navigation.setOptions({
|
||||
headerLeft,
|
||||
headerTitle: t('prejoin.joinMeeting')
|
||||
});
|
||||
}, [ navigation ]);
|
||||
|
||||
let unsafeRoomContentContainer;
|
||||
|
||||
if (aspectRatio === ASPECT_RATIO_NARROW) {
|
||||
unsafeRoomContentContainer = styles.unsafeRoomContentContainer;
|
||||
} else {
|
||||
unsafeRoomContentContainer = styles.unsafeRoomContentContainerWide;
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<JitsiScreen
|
||||
addBottomPadding = { false }
|
||||
safeAreaInsets = { [ 'right' ] }
|
||||
style = { styles.unsafeRoomWarningContainer } >
|
||||
<View style = { styles.displayRoomNameBackdrop as StyleProp<TextStyle> }>
|
||||
<Text
|
||||
numberOfLines = { 1 }
|
||||
style = { styles.preJoinRoomName as StyleProp<TextStyle> }>
|
||||
{ roomName }
|
||||
</Text>
|
||||
</View>
|
||||
<View style = { unsafeRoomContentContainer as StyleProp<ViewStyle> }>
|
||||
<View style = { styles.warningIconWrapper as StyleProp<ViewStyle> }>
|
||||
<Icon
|
||||
src = { IconWarning }
|
||||
style = { styles.warningIcon } />
|
||||
</View>
|
||||
|
||||
<Text
|
||||
dataDetectorType = 'link'
|
||||
style = { styles.warningText as StyleProp<TextStyle> }>
|
||||
{ unsafeRoomText }
|
||||
</Text>
|
||||
<Button
|
||||
accessibilityLabel = 'prejoin.proceedAnyway'
|
||||
disabled = { false }
|
||||
labelKey = 'prejoin.proceedAnyway'
|
||||
onClick = { onProceed }
|
||||
style = { styles.joinButton }
|
||||
type = { BUTTON_TYPES.SECONDARY } />
|
||||
</View>
|
||||
</JitsiScreen>
|
||||
);
|
||||
};
|
||||
|
||||
export default UnsafeRoomWarning;
|
||||
@@ -23,7 +23,8 @@ export const preJoinStyles = {
|
||||
},
|
||||
|
||||
contentWrapper: {
|
||||
flex: 1
|
||||
flex: 1,
|
||||
flexDirection: 'row'
|
||||
},
|
||||
|
||||
contentWrapperWide: {
|
||||
@@ -97,7 +98,53 @@ export const preJoinStyles = {
|
||||
paddingHorizontal: BaseTheme.spacing[3],
|
||||
paddingVertical: BaseTheme.spacing[1],
|
||||
position: 'absolute',
|
||||
width: 243,
|
||||
maxWidth: 243,
|
||||
zIndex: 1
|
||||
},
|
||||
unsafeRoomWarningContainer: {
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
backgroundColor: BaseTheme.palette.ui01,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
color: 'white'
|
||||
},
|
||||
unsafeRoomContentContainer: {
|
||||
justifySelf: 'center',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
paddingHorizontal: BaseTheme.spacing[4]
|
||||
},
|
||||
|
||||
unsafeRoomContentContainerWide: {
|
||||
alignItems: 'center',
|
||||
justifySelf: 'center',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
marginLeft: BaseTheme.spacing[7],
|
||||
paddingHorizontal: BaseTheme.spacing[6]
|
||||
},
|
||||
|
||||
warningText: {
|
||||
...BaseTheme.typography.bodyLongRegularLarge,
|
||||
color: BaseTheme.palette.text01,
|
||||
textAlign: 'center',
|
||||
marginBottom: BaseTheme.spacing[4]
|
||||
},
|
||||
warningIconWrapper: {
|
||||
backgroundColor: BaseTheme.palette.warning01,
|
||||
borderRadius: BaseTheme.shape.circleRadius,
|
||||
padding: BaseTheme.spacing[4],
|
||||
marginBottom: BaseTheme.spacing[4],
|
||||
zIndex: 0
|
||||
|
||||
},
|
||||
warningIcon: {
|
||||
color: BaseTheme.palette.ui01,
|
||||
fontSize: 40
|
||||
}
|
||||
};
|
||||
|
||||
@@ -20,6 +20,7 @@ import { getLocalJitsiVideoTrack } from '../../../base/tracks/functions.web';
|
||||
import Button from '../../../base/ui/components/web/Button';
|
||||
import Input from '../../../base/ui/components/web/Input';
|
||||
import { BUTTON_TYPES } from '../../../base/ui/constants.any';
|
||||
import isInsecureRoomName from '../../../base/util/isInsecureRoomName';
|
||||
import {
|
||||
joinConference as joinConferenceAction,
|
||||
joinConferenceWithoutAudio as joinConferenceWithoutAudioAction,
|
||||
@@ -107,6 +108,16 @@ interface IProps {
|
||||
*/
|
||||
showErrorOnJoin: boolean;
|
||||
|
||||
/**
|
||||
* If should show unsafe room warning when joining.
|
||||
*/
|
||||
showUnsafeRoomWarning: boolean;
|
||||
|
||||
/**
|
||||
* Whether the user has approved to join a room with unsafe name.
|
||||
*/
|
||||
unsafeRoomConsent?: boolean;
|
||||
|
||||
/**
|
||||
* Updates settings.
|
||||
*/
|
||||
@@ -195,6 +206,8 @@ const Prejoin = ({
|
||||
showCameraPreview,
|
||||
showDialog,
|
||||
showErrorOnJoin,
|
||||
showUnsafeRoomWarning,
|
||||
unsafeRoomConsent,
|
||||
updateSettings: dispatchUpdateSettings,
|
||||
videoTrack
|
||||
}: IProps) => {
|
||||
@@ -353,6 +366,7 @@ const Prejoin = ({
|
||||
return (
|
||||
<PreMeetingScreen
|
||||
showDeviceStatus = { deviceStatusVisible }
|
||||
showUnsafeRoomWarning = { showUnsafeRoomWarning }
|
||||
title = { t('prejoin.joinMeeting') }
|
||||
videoMuted = { !showCameraPreview }
|
||||
videoTrack = { videoTrack }>
|
||||
@@ -405,7 +419,7 @@ const Prejoin = ({
|
||||
ariaDropDownLabel = { t('prejoin.joinWithoutAudio') }
|
||||
ariaLabel = { t('prejoin.joinMeeting') }
|
||||
ariaPressed = { showJoinByPhoneButtons }
|
||||
disabled = { joiningInProgress }
|
||||
disabled = { joiningInProgress || (showUnsafeRoomWarning && !unsafeRoomConsent) }
|
||||
hasOptions = { hasExtraJoinButtons }
|
||||
onClick = { onJoinButtonClick }
|
||||
onOptionsClick = { onOptionsClick }
|
||||
@@ -439,6 +453,9 @@ function mapStateToProps(state: IReduxState) {
|
||||
const showErrorOnJoin = isDisplayNameRequired(state) && !name;
|
||||
const { id: participantId } = getLocalParticipant(state) ?? {};
|
||||
const { joiningInProgress } = state['features/prejoin'];
|
||||
const { room } = state['features/base/conference'];
|
||||
const { enableInsecureRoomNameWarning = false } = state['features/base/config'];
|
||||
const { unsafeRoomConsent } = state['features/base/premeeting'];
|
||||
|
||||
return {
|
||||
canEditDisplayName: isPrejoinDisplayNameVisible(state),
|
||||
@@ -452,6 +469,8 @@ function mapStateToProps(state: IReduxState) {
|
||||
showCameraPreview: !isVideoMutedByUser(state),
|
||||
showDialog: isJoinByPhoneDialogVisible(state),
|
||||
showErrorOnJoin,
|
||||
showUnsafeRoomWarning: isInsecureRoomName(room) && enableInsecureRoomNameWarning,
|
||||
unsafeRoomConsent,
|
||||
videoTrack: getLocalJitsiVideoTrack(state)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import BaseTheme from '../../base/ui/components/BaseTheme.native';
|
||||
import Button from '../../base/ui/components/native/Button';
|
||||
import Input from '../../base/ui/components/native/Input';
|
||||
import { BUTTON_TYPES } from '../../base/ui/constants.native';
|
||||
import getUnsafeRoomText from '../../base/util/getUnsafeRoomText.native';
|
||||
import WelcomePageTabs
|
||||
from '../../mobile/navigation/components/welcome/components/WelcomePageTabs';
|
||||
|
||||
@@ -33,6 +34,11 @@ import styles from './styles.native';
|
||||
|
||||
interface IProps extends AbstractProps {
|
||||
|
||||
/**
|
||||
* Function for getting the unsafe room text.
|
||||
*/
|
||||
getUnsafeRoomTextFn: Function;
|
||||
|
||||
/**
|
||||
* Default prop for navigating between screen components(React Navigation).
|
||||
*/
|
||||
@@ -151,7 +157,7 @@ class WelcomePage extends AbstractWelcomePage<IProps> {
|
||||
src = { IconWarning }
|
||||
style = { styles.insecureRoomNameWarningIcon } />
|
||||
<Text style = { styles.insecureRoomNameWarningText }>
|
||||
{ this.props.t('security.insecureRoomNameWarning') }
|
||||
{ this.props.getUnsafeRoomTextFn(this.props.t) }
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
@@ -399,9 +405,10 @@ class WelcomePage extends AbstractWelcomePage<IProps> {
|
||||
*/
|
||||
function _mapStateToProps(state: IReduxState) {
|
||||
return {
|
||||
..._abstractMapStateToProps(state)
|
||||
..._abstractMapStateToProps(state),
|
||||
|
||||
// _reducedUI: state['features/base/responsive-ui'].reducedUI
|
||||
getUnsafeRoomTextFn: (t: Function) => getUnsafeRoomText(state, t, 'welcome')
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import { translate, translateToHTML } from '../../base/i18n/functions';
|
||||
import Icon from '../../base/icons/components/Icon';
|
||||
import { IconWarning } from '../../base/icons/svg';
|
||||
import Watermarks from '../../base/react/components/web/Watermarks';
|
||||
import getUnsafeRoomText from '../../base/util/getUnsafeRoomText.web';
|
||||
import CalendarList from '../../calendar-sync/components/CalendarList.web';
|
||||
import RecentList from '../../recent-list/components/RecentList.web';
|
||||
import SettingsButton from '../../settings/components/web/SettingsButton';
|
||||
@@ -294,7 +295,7 @@ class WelcomePage extends AbstractWelcomePage<IProps> {
|
||||
<div className = 'insecure-room-name-warning'>
|
||||
<Icon src = { IconWarning } />
|
||||
<span>
|
||||
{ this.props.t('security.insecureRoomNameWarning') }
|
||||
{ getUnsafeRoomText(this.props.t, 'welcome') }
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -197,7 +197,7 @@ export default {
|
||||
},
|
||||
|
||||
insecureRoomNameWarningText: {
|
||||
color: BaseTheme.palette.warning02,
|
||||
color: BaseTheme.palette.text01,
|
||||
flex: 1
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user