Merge branch 'develop' into pr2

This commit is contained in:
Reinaldo Neto 2023-08-28 19:17:25 -03:00 committed by GitHub
commit 5df1c1c1be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 187 additions and 97 deletions

View File

@ -555,7 +555,6 @@
"Enabled_E2E_Encryption_for_this_room": "enabled E2E encryption for this room",
"Disabled_E2E_Encryption_for_this_room": "disabled E2E encryption for this room",
"Teams": "Teams",
"No_team_channels_found": "No channels found",
"Team_not_found": "Team not found",
"Create_Team": "Create team",
"Team_Name": "Team name",
@ -744,5 +743,6 @@
"accept": "Accept",
"Incoming_call_from": "Incoming call from",
"Call_started": "Call started",
"Message_has_been_shared":"Message has been shared"
}
"Message_has_been_shared":"Message has been shared",
"No_channels_in_team": "No Channels on this team"
}

View File

@ -731,5 +731,6 @@
"Select": "Selecionar",
"Nickname": "Apelido",
"Bio": "Biografia",
"Message_has_been_shared":"Menssagem foi compartilhada"
"Message_has_been_shared":"Menssagem foi compartilhada",
"No_channels_in_team": "Nenhum canal nesta equipe"
}

View File

@ -133,7 +133,7 @@ export const colors = {
headerTintColor: '#f9f9f9',
headerTitleColor: '#f9f9f9',
headerSecondaryText: '#9297a2',
toastBackground: '#0C0D0F',
toastBackground: '#54585e',
videoBackground: '#1f2329',
favoriteBackground: '#ffbb00',
hideBackground: '#54585e',
@ -212,7 +212,7 @@ export const colors = {
headerTintColor: '#f9f9f9',
headerTitleColor: '#f9f9f9',
headerSecondaryText: '#b2b8c6',
toastBackground: '#0C0D0F',
toastBackground: '#54585e',
videoBackground: '#1f2329',
favoriteBackground: '#ffbb00',
hideBackground: '#54585e',

View File

@ -1,4 +1,31 @@
// 🚨🚨 48 settings after login. Pay attention not to reach 50 as that's the limit per request.
// DEPRECATED: This settings are deprecated and will be removed in the LTS only support
const deprecatedSettings = {
Jitsi_Enable_Teams: {
type: 'valueAsBoolean'
},
Jitsi_Enable_Channels: {
type: 'valuesAsBoolean'
},
Jitsi_Enabled: {
type: 'valueAsBoolean'
},
Jitsi_SSL: {
type: 'valueAsBoolean'
},
Jitsi_Domain: {
type: 'valueAsString'
},
Jitsi_Enabled_TokenAuth: {
type: 'valueAsBoolean'
},
Jitsi_URL_Room_Hash: {
type: 'valueAsBoolean'
},
Jitsi_URL_Room_Prefix: {
type: 'valueAsString'
}
};
export const defaultSettings = {
Accounts_AllowEmailChange: {
type: 'valueAsBoolean'
@ -93,24 +120,6 @@ export const defaultSettings = {
Livechat_request_comment_when_closing_conversation: {
type: 'valueAsBoolean'
},
Jitsi_Enabled: {
type: 'valueAsBoolean'
},
Jitsi_SSL: {
type: 'valueAsBoolean'
},
Jitsi_Domain: {
type: 'valueAsString'
},
Jitsi_Enabled_TokenAuth: {
type: 'valueAsBoolean'
},
Jitsi_URL_Room_Hash: {
type: 'valueAsBoolean'
},
Jitsi_URL_Room_Prefix: {
type: 'valueAsString'
},
Message_AllowDeleting: {
type: 'valueAsBoolean'
},
@ -201,12 +210,6 @@ export const defaultSettings = {
Accounts_AllowInvisibleStatusOption: {
type: 'valueAsString'
},
Jitsi_Enable_Teams: {
type: 'valueAsBoolean'
},
Jitsi_Enable_Channels: {
type: 'valuesAsBoolean'
},
Canned_Responses_Enable: {
type: 'valueAsBoolean'
},
@ -239,5 +242,9 @@ export const defaultSettings = {
},
Presence_broadcast_disabled: {
type: 'valueAsBoolean'
}
},
Omnichannel_call_provider: {
type: 'valueAsBoolean'
},
...deprecatedSettings
} as const;

View File

@ -0,0 +1,6 @@
import { TSettingsValues, TSupportedSettings } from '../../reducers/settings';
import { useAppSelector } from './useAppSelector';
export function useSetting(key: TSupportedSettings): TSettingsValues {
return useAppSelector(state => state.settings[key]) as TSettingsValues;
}

View File

@ -1,17 +1,16 @@
import { Camera } from 'expo-camera';
import React, { useEffect, useState } from 'react';
import React from 'react';
import { useActionSheet } from '../../../containers/ActionSheet';
import { SubscriptionType } from '../../../definitions';
import i18n from '../../../i18n';
import { getUserSelector } from '../../../selectors/login';
import { getSubscriptionByRoomId } from '../../database/services/Subscription';
import { compareServerVersion, showErrorAlert } from '../../methods/helpers';
import { handleAndroidBltPermission } from '../../methods/videoConf';
import { Services } from '../../services';
import { useAppSelector } from '../useAppSelector';
import { useSnaps } from '../useSnaps';
import StartACallActionSheet from './StartACallActionSheet';
import { useVideoConfCall } from './useVideoConfCall';
const availabilityErrors = {
NOT_CONFIGURED: 'video-conf-provider-not-configured',
@ -24,58 +23,44 @@ const handleErrors = (isAdmin: boolean, error: typeof availabilityErrors[keyof t
return showErrorAlert(i18n.t(`${error}-body`), i18n.t(`${error}-header`));
};
export const useVideoConf = (rid: string): { showInitCallActionSheet: () => Promise<void>; showCallOption: boolean } => {
const [showCallOption, setShowCallOption] = useState(false);
const serverVersion = useAppSelector(state => state.server.version);
const jitsiEnabled = useAppSelector(state => state.settings.Jitsi_Enabled);
const jitsiEnableTeams = useAppSelector(state => state.settings.Jitsi_Enable_Teams);
const jitsiEnableChannels = useAppSelector(state => state.settings.Jitsi_Enable_Channels);
export const useVideoConf = (
rid: string
): { showInitCallActionSheet: () => Promise<void>; callEnabled: boolean; disabledTooltip?: boolean } => {
const user = useAppSelector(state => getUserSelector(state));
const serverVersion = useAppSelector(state => state.server.version);
const { callEnabled, disabledTooltip } = useVideoConfCall(rid);
const [permission, requestPermission] = Camera.useCameraPermissions();
const isServer5OrNewer = compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '5.0.0');
const { showActionSheet } = useActionSheet();
const snaps = useSnaps(404);
const handleShowCallOption = async () => {
if (isServer5OrNewer) return setShowCallOption(true);
const room = await getSubscriptionByRoomId(rid);
if (room) {
const isJitsiDisabledForTeams = room.teamMain && !jitsiEnableTeams;
const isJitsiDisabledForChannels = !room.teamMain && (room.t === 'p' || room.t === 'c') && !jitsiEnableChannels;
if (room.t === SubscriptionType.DIRECT) return setShowCallOption(!!jitsiEnabled);
if (room.t === SubscriptionType.CHANNEL) return setShowCallOption(!isJitsiDisabledForChannels);
if (room.t === SubscriptionType.GROUP) return setShowCallOption(!isJitsiDisabledForTeams);
}
return setShowCallOption(false);
};
const isServer5OrNewer = compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '5.0.0');
const canInitAnCall = async () => {
if (isServer5OrNewer) {
try {
await Services.videoConferenceGetCapabilities();
return true;
} catch (error: any) {
const isAdmin = !!['admin'].find(role => user.roles?.includes(role));
switch (error?.error) {
case availabilityErrors.NOT_CONFIGURED:
return handleErrors(isAdmin, availabilityErrors.NOT_CONFIGURED);
case availabilityErrors.NOT_ACTIVE:
return handleErrors(isAdmin, availabilityErrors.NOT_ACTIVE);
case availabilityErrors.NO_APP:
return handleErrors(isAdmin, availabilityErrors.NO_APP);
default:
return handleErrors(isAdmin, availabilityErrors.NOT_CONFIGURED);
if (callEnabled) {
if (isServer5OrNewer) {
try {
await Services.videoConferenceGetCapabilities();
return true;
} catch (error: any) {
const isAdmin = !!user.roles?.includes('admin');
switch (error?.error) {
case availabilityErrors.NOT_CONFIGURED:
return handleErrors(isAdmin, availabilityErrors.NOT_CONFIGURED);
case availabilityErrors.NOT_ACTIVE:
return handleErrors(isAdmin, availabilityErrors.NOT_ACTIVE);
case availabilityErrors.NO_APP:
return handleErrors(isAdmin, availabilityErrors.NO_APP);
default:
return handleErrors(isAdmin, availabilityErrors.NOT_CONFIGURED);
}
}
}
return true;
}
return true;
return false;
};
const showInitCallActionSheet = async () => {
@ -92,9 +77,5 @@ export const useVideoConf = (rid: string): { showInitCallActionSheet: () => Prom
}
};
useEffect(() => {
handleShowCallOption();
}, []);
return { showInitCallActionSheet, showCallOption };
return { showInitCallActionSheet, callEnabled, disabledTooltip };
};

View File

@ -0,0 +1,68 @@
import { useEffect, useState } from 'react';
import { SubscriptionType } from '../../../definitions';
import { getUserSelector } from '../../../selectors/login';
import { getSubscriptionByRoomId } from '../../database/services/Subscription';
import { compareServerVersion, isReadOnly } from '../../methods/helpers';
import { useAppSelector } from '../useAppSelector';
import { usePermissions } from '../usePermissions';
import { useSetting } from '../useSetting';
import { isRoomFederated } from '../../methods';
export const useVideoConfCall = (rid: string): { callEnabled: boolean; disabledTooltip?: boolean } => {
const [callEnabled, setCallEnabled] = useState(false);
const [disabledTooltip, setDisabledTooltip] = useState(false);
// OLD SETTINGS
const jitsiEnabled = useSetting('Jitsi_Enabled');
const jitsiEnableTeams = useSetting('Jitsi_Enable_Teams');
const jitsiEnableChannels = useSetting('Jitsi_Enable_Channels');
// NEW SETTINGS
// Only disable video conf if the settings are explicitly FALSE - any falsy value counts as true
const enabledDMs = useSetting('VideoConf_Enable_DMs') !== false;
const enabledChannel = useSetting('VideoConf_Enable_Channels') !== false;
const enabledTeams = useSetting('VideoConf_Enable_Teams') !== false;
const enabledGroups = useSetting('VideoConf_Enable_Groups') !== false;
const enabledLiveChat = useSetting('Omnichannel_call_provider') === 'default-provider';
const serverVersion = useAppSelector(state => state.server.version);
const isServer5OrNewer = compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '5.0.0');
const [canStartCall] = usePermissions(['call-management'], rid);
const user = useAppSelector(state => getUserSelector(state));
const init = async () => {
const room = await getSubscriptionByRoomId(rid);
if (room) {
if (isServer5OrNewer) {
const isReadyOnly = await isReadOnly(room, user.username);
const ownUser = room.uids && room.uids.length === 1;
const enabled = enabledDMs || enabledChannel || enabledTeams || enabledGroups || enabledLiveChat;
const enableOption = enabled && canStartCall && (!user?.username || !room.muted?.includes(user.username));
const federated = isRoomFederated(room);
if (enableOption && !ownUser) {
if (federated || (room.ro && isReadyOnly)) {
setDisabledTooltip(true);
}
return setCallEnabled(true);
}
return;
}
// OLD SERVERS VERSIONS
const isJitsiDisabledForTeams = room.teamMain && !jitsiEnableTeams;
const isJitsiDisabledForChannels = !room.teamMain && (room.t === 'p' || room.t === 'c') && !jitsiEnableChannels;
if (room.t === SubscriptionType.DIRECT) return setCallEnabled(!!jitsiEnabled);
if (room.t === SubscriptionType.CHANNEL) return setCallEnabled(!isJitsiDisabledForChannels);
if (room.t === SubscriptionType.GROUP) return setCallEnabled(!isJitsiDisabledForTeams);
}
return setCallEnabled(false);
};
useEffect(() => {
init();
}, []);
return { callEnabled, disabledTooltip };
};

View File

@ -58,7 +58,8 @@ export const SUPPORTED_PERMISSIONS = [
'edit-livechat-room-customfields',
'view-canned-responses',
'mobile-upload-file',
'delete-own-message'
'delete-own-message',
'call-management'
] as const;
export async function setPermissions(): Promise<void> {

View File

@ -37,3 +37,4 @@ export * from './crashReport';
export * from './parseSettings';
export * from './subscribeRooms';
export * from './serializeAsciiUrl';
export * from './isRoomFederated';

View File

@ -0,0 +1,8 @@
import { ISubscription } from '../../definitions';
interface IRoomFederated extends ISubscription {
federated: true;
}
export const isRoomFederated = (room: ISubscription): room is IRoomFederated =>
'federated' in room && (room as any).federated === true;

View File

@ -4,9 +4,8 @@ import * as List from '../../../containers/List';
import { useVideoConf } from '../../../lib/hooks/useVideoConf';
export default function CallSection({ rid }: { rid: string }): React.ReactElement | null {
const { showCallOption, showInitCallActionSheet } = useVideoConf(rid);
if (showCallOption)
const { callEnabled, showInitCallActionSheet, disabledTooltip } = useVideoConf(rid);
if (callEnabled)
return (
<List.Section>
<List.Separator />
@ -16,6 +15,7 @@ export default function CallSection({ rid }: { rid: string }): React.ReactElemen
testID='room-actions-call'
left={() => <List.Icon name='phone' />}
showActionIndicator
disabled={disabledTooltip}
/>
<List.Separator />
</List.Section>

View File

@ -1109,7 +1109,7 @@ class RoomActionsView extends React.Component<IRoomActionsViewProps, IRoomAction
{teamId && isTeamRoom({ teamId, joined }) ? (
<>
<List.Item
title='Teams'
title='Channels'
onPress={() => {
logEvent(events.ROOM_GO_TEAM_CHANNELS);
if (isMasterDetail) {

View File

@ -16,20 +16,22 @@ function UserInfoButton({
iconName,
onPress,
label,
showIcon
showIcon,
enabled = true
}: {
danger?: boolean;
iconName: TIconsName;
onPress?: (prop: any) => void;
label: string;
showIcon?: boolean;
enabled?: boolean;
}): React.ReactElement | null {
const { colors } = useTheme();
const color = danger ? colors.dangerColor : colors.actionTintColor;
let color = danger ? colors.dangerColor : colors.actionTintColor;
if (!enabled) color = colors.auxiliaryText;
if (showIcon)
return (
<BorderlessButton testID={`room-info-view-${iconName}`} onPress={onPress} style={styles.roomButton}>
<BorderlessButton enabled={enabled} testID={`room-info-view-${iconName}`} onPress={onPress} style={styles.roomButton}>
<CustomIcon name={iconName} size={30} color={color} />
<Text style={[styles.roomButtonText, { color }]}>{label}</Text>
</BorderlessButton>
@ -38,11 +40,19 @@ function UserInfoButton({
}
export function CallButton({ rid, isDirect }: { rid: string; isDirect: boolean }): React.ReactElement | null {
const { showCallOption, showInitCallActionSheet } = useVideoConf(rid);
const { callEnabled, showInitCallActionSheet, disabledTooltip } = useVideoConf(rid);
const serverVersion = useAppSelector(state => state.server.version);
const greaterThanFive = compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '5.0.0');
const showIcon = greaterThanFive ? showCallOption : showCallOption && isDirect;
const showIcon = greaterThanFive ? callEnabled : callEnabled && isDirect;
return <UserInfoButton onPress={showInitCallActionSheet} iconName='phone' label={i18n.t('Call')} showIcon={showIcon} />;
return (
<UserInfoButton
enabled={!disabledTooltip}
onPress={showInitCallActionSheet}
iconName='phone'
label={i18n.t('Call')}
showIcon={showIcon}
/>
);
}

View File

@ -4,9 +4,16 @@ import * as HeaderButton from '../../../containers/HeaderButton';
import { useVideoConf } from '../../../lib/hooks/useVideoConf';
export default function HeaderCallButton({ rid }: { rid: string }): React.ReactElement | null {
const { showInitCallActionSheet, showCallOption } = useVideoConf(rid);
const { showInitCallActionSheet, callEnabled, disabledTooltip } = useVideoConf(rid);
if (showCallOption)
return <HeaderButton.Item iconName='phone' onPress={showInitCallActionSheet} testID='room-view-header-call' />;
if (callEnabled)
return (
<HeaderButton.Item
disabled={disabledTooltip}
iconName='phone'
onPress={showInitCallActionSheet}
testID='room-view-header-call'
/>
);
return null;
}

View File

@ -520,10 +520,10 @@ class TeamChannelsView extends React.Component<ITeamChannelsViewProps, ITeamChan
return <BackgroundContainer loading />;
}
if (isSearching && !search.length) {
return <BackgroundContainer text={searchText ? I18n.t('No_team_channels_found') : ''} />;
return <BackgroundContainer text={searchText ? I18n.t('No_channels_in_team') : ''} />;
}
if (!isSearching && !data.length) {
return <BackgroundContainer text={I18n.t('No_team_channels_found')} />;
return <BackgroundContainer text={I18n.t('No_channels_in_team')} />;
}
return (