This commit is contained in:
GleidsonDaniel 2024-02-20 17:24:19 -03:00
parent ae753905e5
commit 775aa9137b
10 changed files with 237 additions and 212 deletions

View File

@ -96,6 +96,6 @@ export const VIDEO_CONF = createRequestTypes('VIDEO_CONF', [
'ACCEPT_CALL',
'SET_CALLING'
]);
export const TROUBLESHOOTING_NOTIFICATION = createRequestTypes('TROUBLESHOOTING_NOTIFICATION', ['REQUEST', 'SET']);
export const TROUBLESHOOTING_NOTIFICATION = createRequestTypes('TROUBLESHOOTING_NOTIFICATION', ['INIT', 'SET']);
export const SUPPORTED_VERSIONS = createRequestTypes('SUPPORTED_VERSIONS', ['SET']);
export const IN_APP_FEEDBACK = createRequestTypes('IN_APP_FEEDBACK', ['SET', 'REMOVE', 'CLEAR']);

View File

@ -7,9 +7,9 @@ type TSetTroubleshootingNotification = Action & { payload: Partial<ITroubleshoot
export type TActionTroubleshootingNotification = Action & TSetTroubleshootingNotification;
export function requestTroubleshootingNotification(): Action {
export function initTroubleshootingNotification(): Action {
return {
type: TROUBLESHOOTING_NOTIFICATION.REQUEST
type: TROUBLESHOOTING_NOTIFICATION.INIT
};
}

View File

@ -5,12 +5,18 @@ import I18n from '../../../i18n';
export const showErrorAlert = (message: string, title?: string, onPress = () => {}): void =>
Alert.alert(title || '', message, [{ text: 'OK', onPress }], { cancelable: true });
export const showErrorAlertWithEMessage = (e: any): void => {
const messageError =
e.data && e.data.error.includes('[error-too-many-requests]')
? I18n.t('error-too-many-requests', { seconds: e.data.error.replace(/\D/g, '') })
: e.data.errorType;
showErrorAlert(messageError);
export const showErrorAlertWithEMessage = (e: any, title?: string): void => {
let errorMessage: string = e?.data?.error;
if (errorMessage.includes('[error-too-many-requests]')) {
const seconds = errorMessage.replace(/\D/g, '');
errorMessage = I18n.t('error-too-many-requests', { seconds });
} else {
const errorKey = errorMessage;
errorMessage = I18n.isTranslated(errorKey) ? I18n.t(errorKey) : errorMessage;
}
showErrorAlert(errorMessage, title);
};
interface IShowConfirmationAlert {

View File

@ -13,7 +13,7 @@ interface IGenericAction extends Action {
type: string;
}
function* request() {
function* init() {
const serverVersion = yield* appSelector(state => state.server.version);
let deviceNotificationEnabled = false;
let defaultPushGateway = false;
@ -21,14 +21,22 @@ function* request() {
try {
const { authorizationStatus } = yield* call(notifee.getNotificationSettings);
deviceNotificationEnabled = authorizationStatus > AuthorizationStatus.DENIED;
const pushInfoResult = yield* call(pushInfo);
if (pushInfoResult.success) {
pushGatewayEnabled = pushInfoResult.pushGatewayEnabled;
defaultPushGateway = pushInfoResult.defaultPushGateway;
} catch (e) {
log(e);
}
try {
if (compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '6.5.0')) {
const pushInfoResult = yield* call(pushInfo);
if (pushInfoResult.success) {
pushGatewayEnabled = pushInfoResult.pushGatewayEnabled;
defaultPushGateway = pushInfoResult.defaultPushGateway;
}
}
} catch (e) {
log(e);
}
const issuesWithNotifications =
!deviceNotificationEnabled || (compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '6.6.0') && !pushGatewayEnabled);
yield put(
@ -42,5 +50,5 @@ function* request() {
}
export default function* root(): Generator {
yield takeLatest<IGenericAction>(TROUBLESHOOTING_NOTIFICATION.REQUEST, request);
yield takeLatest<IGenericAction>(TROUBLESHOOTING_NOTIFICATION.INIT, init);
}

View File

@ -0,0 +1,56 @@
import React from 'react';
import { Alert, StyleSheet, Text } from 'react-native';
import * as List from '../../../containers/List';
import i18n from '../../../i18n';
import { useAppSelector } from '../../../lib/hooks';
import { useTheme } from '../../../theme';
import sharedStyles from '../../Styles';
const WARNING_MINIMUM_VALUE = 70;
const WARNING_MAXIMUM_VALUE = 90;
export default function CommunityEditionPushQuota(): React.ReactElement | null {
const { colors } = useTheme();
const { consumptionPercentage, isCommunityEdition } = useAppSelector(state => ({
isCommunityEdition: state.troubleshootingNotification.isCommunityEdition,
consumptionPercentage: state.troubleshootingNotification.consumptionPercentage
}));
if (!isCommunityEdition) return null;
const percentage = `${Math.floor(consumptionPercentage)}%`;
let percentageColor = colors.statusFontOnSuccess;
if (consumptionPercentage > WARNING_MINIMUM_VALUE && consumptionPercentage < WARNING_MAXIMUM_VALUE) {
percentageColor = colors.statusFontOnWarning;
}
if (consumptionPercentage >= WARNING_MAXIMUM_VALUE) {
percentageColor = colors.statusFontOnDanger;
}
const alertWorkspaceConsumption = () => {
Alert.alert(i18n.t('Push_consumption_alert_title'), i18n.t('Push_consumption_alert_description'));
};
return (
<List.Section title='Community_edition_push_quota'>
<List.Separator />
<List.Item
title='Workspace_consumption'
testID='push-troubleshoot-view-workspace-consumption'
onPress={alertWorkspaceConsumption}
right={() => <Text style={[styles.pickerText, { color: percentageColor }]}>{percentage}</Text>}
/>
<List.Separator />
<List.Info info='Workspace_consumption_description' />
</List.Section>
);
}
const styles = StyleSheet.create({
pickerText: {
...sharedStyles.textRegular,
fontSize: 16
}
});

View File

@ -0,0 +1,50 @@
import notifee from '@notifee/react-native';
import React from 'react';
import { Linking } from 'react-native';
import * as List from '../../../containers/List';
import i18n from '../../../i18n';
import { useAppSelector } from '../../../lib/hooks';
import { isIOS, showErrorAlert } from '../../../lib/methods/helpers';
import { useTheme } from '../../../theme';
import CustomListSection from './CustomListSection';
export default function DeviceNotificationSettings(): React.ReactElement {
const { colors } = useTheme();
const { deviceNotificationEnabled } = useAppSelector(state => ({
deviceNotificationEnabled: state.troubleshootingNotification.deviceNotificationEnabled
}));
const goToNotificationSettings = () => {
if (isIOS) {
Linking.openURL('app-settings:');
} else {
notifee.openNotificationSettings();
}
};
const alertDeviceNotificationSettings = () => {
if (deviceNotificationEnabled) return;
showErrorAlert(
i18n.t('Device_notifications_alert_description'),
i18n.t('Device_notifications_alert_title'),
goToNotificationSettings
);
};
return (
<CustomListSection
title='Device_notification_settings'
statusColor={!deviceNotificationEnabled ? colors.userPresenceBusy : colors.userPresenceOnline}
>
<List.Separator />
<List.Item
title={!deviceNotificationEnabled ? 'Allow_push_notifications_for_rocket_chat' : 'Go_to_device_settings'}
onPress={alertDeviceNotificationSettings}
testID='push-troubleshoot-view-allow-push-notifications'
disabled={deviceNotificationEnabled}
/>
<List.Separator />
</CustomListSection>
);
}

View File

@ -1,64 +0,0 @@
import React from 'react';
import { StyleSheet, Text } from 'react-native';
import * as List from '../../../containers/List';
import { useTheme } from '../../../theme';
import sharedStyles from '../../Styles';
const styles = StyleSheet.create({
pickerText: {
...sharedStyles.textRegular,
fontSize: 16
}
});
type TPercentageState = 'success' | 'warning' | 'danger';
const DANGER_VALUE = 90;
const WARNING_MINIMUM_VALUE = 70;
const WARNING_MAXIMUM_VALUE = 90;
const getPercentageState = (value: number): TPercentageState => {
if (value > WARNING_MINIMUM_VALUE && value < WARNING_MAXIMUM_VALUE) {
return 'warning';
}
if (value >= DANGER_VALUE) {
return 'danger';
}
return 'success';
};
const ListPercentage = ({
value = 0,
title,
testID,
onPress
}: {
title: string;
testID: string;
value: number;
onPress: () => void;
}) => {
const { colors } = useTheme();
const percentage = `${Math.floor(value)}%`;
const percentageState = getPercentageState(value);
let percentageTextColor = colors.statusFontOnSuccess;
if (percentageState === 'warning') {
percentageTextColor = colors.statusFontOnWarning;
}
if (percentageState === 'danger') {
percentageTextColor = colors.statusFontOnDanger;
}
return (
<List.Item
title={title}
testID={testID}
onPress={onPress}
right={() => <Text style={[styles.pickerText, { color: percentageTextColor }]}>{percentage}</Text>}
/>
);
};
export default ListPercentage;

View File

@ -0,0 +1,25 @@
import React from 'react';
import { Linking } from 'react-native';
import * as List from '../../../containers/List';
import { useTheme } from '../../../theme';
export default function NotificationDelay(): React.ReactElement {
const { colors } = useTheme();
const openNotificationDocumentation = () => Linking.openURL('https://go.rocket.chat/i/push-notifications');
return (
<List.Section title='Notification_delay'>
<List.Separator />
<List.Item
title='Documentation'
onPress={openNotificationDocumentation}
right={() => <List.Icon size={32} name='new-window' color={colors.fontAnnotation} />}
testID='push-troubleshoot-view-notification-delay'
/>
<List.Separator />
<List.Info info='Notification_delay_description' />
</List.Section>
);
}

View File

@ -0,0 +1,65 @@
import React, { useState } from 'react';
import { Alert } from 'react-native';
import * as List from '../../../containers/List';
import i18n from '../../../i18n';
import { useAppSelector, usePermissions } from '../../../lib/hooks';
import { compareServerVersion, showErrorAlertWithEMessage } from '../../../lib/methods/helpers';
import { Services } from '../../../lib/services';
import { useTheme } from '../../../theme';
import CustomListSection from './CustomListSection';
export default function PushGatewayConnection(): React.ReactElement | null {
const [loading, setLoading] = useState(false);
const { colors } = useTheme();
const [testPushNotificationsPermission] = usePermissions(['test-push-notifications']);
const { defaultPushGateway, pushGatewayEnabled, serverVersion } = useAppSelector(state => ({
pushGatewayEnabled: state.troubleshootingNotification.pushGatewayEnabled,
defaultPushGateway: state.troubleshootingNotification.defaultPushGateway,
foreground: state.app.foreground,
serverVersion: state.server.version
}));
if (!compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '6.6.0')) return null;
const handleTestPushNotification = async () => {
setLoading(true);
try {
const result = await Services.pushTest();
if (result.success) {
Alert.alert(i18n.t('Test_push_notification'), i18n.t('Your_push_was_sent_to_s_devices', { s: result.tokensCount }));
}
} catch (error: any) {
showErrorAlertWithEMessage(error, i18n.t('Test_push_notification'));
}
setLoading(false);
};
let infoColor = 'Push_gateway_not_connected_description';
let statusColor = colors.userPresenceBusy;
if (pushGatewayEnabled) {
statusColor = colors.userPresenceOnline;
infoColor = 'Push_gateway_connected_description';
}
if (pushGatewayEnabled && !defaultPushGateway) {
statusColor = colors.badgeBackgroundLevel3;
infoColor = 'Custom_push_gateway_connected_description';
}
return (
<CustomListSection
title={!defaultPushGateway ? 'Custom_push_gateway_connection' : 'Push_gateway_connection'}
statusColor={statusColor}
>
<List.Separator />
<List.Item
title='Test_push_notification'
disabled={!pushGatewayEnabled || !testPushNotificationsPermission || loading}
onPress={handleTestPushNotification}
testID='push-troubleshoot-view-push-gateway-connection'
/>
<List.Separator />
<List.Info info={infoColor} />
</CustomListSection>
);
}

View File

@ -1,51 +1,30 @@
import { StackNavigationProp } from '@react-navigation/stack';
import React, { useEffect } from 'react';
import { Alert, Linking } from 'react-native';
import notifee from '@notifee/react-native';
import { useDispatch } from 'react-redux';
import { initTroubleshootingNotification } from '../../actions/troubleshootingNotification';
import * as List from '../../containers/List';
import SafeAreaView from '../../containers/SafeAreaView';
import StatusBar from '../../containers/StatusBar';
import I18n from '../../i18n';
import { useAppSelector } from '../../lib/hooks';
import { SettingsStackParamList } from '../../stacks/types';
import { useTheme } from '../../theme';
import CustomListSection from './components/CustomListSection';
import { compareServerVersion, isIOS, showErrorAlert } from '../../lib/methods/helpers';
import { requestTroubleshootingNotification } from '../../actions/troubleshootingNotification';
import { useAppSelector, usePermissions } from '../../lib/hooks';
import { Services } from '../../lib/services';
import ListPercentage from './components/ListPercentage';
import CommunityEditionPushQuota from './components/CommunityEditionPushQuota';
import DeviceNotificationSettings from './components/DeviceNotificationSettings';
import NotificationDelay from './components/NotificationDelay';
import PushGatewayConnection from './components/PushGatewayConnection';
interface IPushTroubleshootViewProps {
navigation: StackNavigationProp<SettingsStackParamList, 'PushTroubleshootView'>;
}
const PushTroubleshootView = ({ navigation }: IPushTroubleshootViewProps): JSX.Element => {
const { colors } = useTheme();
const dispatch = useDispatch();
const [testPushNotificationsPermission] = usePermissions(['test-push-notifications']);
const {
deviceNotificationEnabled,
defaultPushGateway,
pushGatewayEnabled,
consumptionPercentage,
isCommunityEdition,
foreground,
serverVersion
} = useAppSelector(state => ({
deviceNotificationEnabled: state.troubleshootingNotification.deviceNotificationEnabled,
pushGatewayEnabled: state.troubleshootingNotification.pushGatewayEnabled,
defaultPushGateway: state.troubleshootingNotification.defaultPushGateway,
foreground: state.app.foreground,
serverVersion: state.server.version,
isCommunityEdition: state.troubleshootingNotification.isCommunityEdition,
consumptionPercentage: state.troubleshootingNotification.consumptionPercentage
}));
const foreground = useAppSelector(state => state.app.foreground);
useEffect(() => {
if (foreground) {
dispatch(requestTroubleshootingNotification());
dispatch(initTroubleshootingNotification());
}
}, [dispatch, foreground]);
@ -55,114 +34,14 @@ const PushTroubleshootView = ({ navigation }: IPushTroubleshootViewProps): JSX.E
});
}, [navigation]);
const openNotificationDocumentation = async () => {
await Linking.openURL('https://go.rocket.chat/i/push-notifications');
};
const alertDeviceNotificationSettings = () => {
showErrorAlert(
I18n.t('Device_notifications_alert_description'),
I18n.t('Device_notifications_alert_title'),
goToNotificationSettings
);
};
const alertWorkspaceConsumption = () => {
Alert.alert(I18n.t('Push_consumption_alert_title'), I18n.t('Push_consumption_alert_description'));
};
const goToNotificationSettings = () => {
if (isIOS) {
Linking.openURL('app-settings:');
} else {
notifee.openNotificationSettings();
}
};
const handleTestPushNotification = async () => {
let message = '';
try {
const result = await Services.pushTest();
if (result.success) {
message = I18n.t('Your_push_was_sent_to_s_devices', { s: result.tokensCount });
}
} catch (error: any) {
message = I18n.isTranslated(error?.data?.errorType) ? I18n.t(error?.data?.errorType) : error?.data?.error;
} finally {
Alert.alert(I18n.t('Test_push_notification'), message);
}
};
let pushGatewayInfoDescription = 'Push_gateway_not_connected_description';
let pushGatewayStatusColor = colors.userPresenceBusy;
if (pushGatewayEnabled) {
pushGatewayStatusColor = colors.userPresenceOnline;
pushGatewayInfoDescription = 'Push_gateway_connected_description';
}
if (pushGatewayEnabled && !defaultPushGateway) {
pushGatewayStatusColor = colors.badgeBackgroundLevel3;
pushGatewayInfoDescription = 'Custom_push_gateway_connected_description';
}
return (
<SafeAreaView testID='push-troubleshoot-view'>
<StatusBar />
<List.Container testID='push-troubleshoot-view-list'>
<CustomListSection
title='Device_notification_settings'
statusColor={!deviceNotificationEnabled ? colors.userPresenceBusy : colors.userPresenceOnline}
>
<List.Separator />
<List.Item
title={!deviceNotificationEnabled ? 'Allow_push_notifications_for_rocket_chat' : 'Go_to_device_settings'}
onPress={!deviceNotificationEnabled ? alertDeviceNotificationSettings : undefined}
testID='push-troubleshoot-view-allow-push-notifications'
/>
<List.Separator />
</CustomListSection>
{isCommunityEdition ? (
<List.Section title='Community_edition_push_quota'>
<List.Separator />
<ListPercentage
title='Workspace_consumption'
onPress={alertWorkspaceConsumption}
testID='push-troubleshoot-view-workspace-consumption'
value={consumptionPercentage}
/>
<List.Separator />
<List.Info info='Workspace_consumption_description' />
</List.Section>
) : null}
{compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '6.6.0') ? (
<CustomListSection
title={!defaultPushGateway ? 'Custom_push_gateway_connection' : 'Push_gateway_connection'}
statusColor={pushGatewayStatusColor}
>
<List.Separator />
<List.Item
title='Test_push_notification'
disabled={!pushGatewayEnabled || !testPushNotificationsPermission}
onPress={handleTestPushNotification}
testID='push-troubleshoot-view-push-gateway-connection'
/>
<List.Separator />
<List.Info info={pushGatewayInfoDescription} />
</CustomListSection>
) : null}
<List.Section title='Notification_delay'>
<List.Separator />
<List.Item
title='Documentation'
onPress={openNotificationDocumentation}
right={() => <List.Icon size={32} name='new-window' color={colors.fontAnnotation} />}
testID='push-troubleshoot-view-notification-delay'
/>
<List.Separator />
<List.Info info='Notification_delay_description' />
</List.Section>
<DeviceNotificationSettings />
<CommunityEditionPushQuota />
<PushGatewayConnection />
<NotificationDelay />
</List.Container>
</SafeAreaView>
);