feat: troubleshoot notification (#5198)

* navigation done

* create the icon inside roomslistview, navigation to push troubleshot and layout push troubleshoot

* custom header

* fix the rooms list view header icon

* layout done

* update the pt-br i18n

* tweak on colors
This commit is contained in:
Reinaldo Neto 2023-09-28 17:32:01 -03:00 committed by GitHub
parent 37c58eb3ba
commit d2d6fb8b4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 314 additions and 9 deletions

View File

@ -111,9 +111,10 @@ export interface ISubscription {
uploads: RelationModified<TUploadModel>;
}
export type TSubscriptionModel = ISubscription & Model & {
asPlain: () => ISubscription;
};
export type TSubscriptionModel = ISubscription &
Model & {
asPlain: () => ISubscription;
};
export type TSubscription = TSubscriptionModel | ISubscription;
// https://github.com/RocketChat/Rocket.Chat/blob/a88a96fcadd925b678ff27ada37075e029f78b5e/definition/ISubscription.ts#L8

View File

@ -743,11 +743,31 @@
"accept": "Accept",
"Incoming_call_from": "Incoming call from",
"Call_started": "Call started",
"Message_has_been_shared":"Message has been shared",
"No_channels_in_team": "No Channels on this team",
"Push_Troubleshooting": "Push Troubleshooting",
"Device_notification_settings": "Device notification settings",
"Allow_push_notifications_for_rocket_chat": "Allow push notifications for Rocket.Chat",
"Go_to_device_settings": "Go to device settings",
"Community_edition_push_quota": "Community Edition push quota",
"Workspace_consumption": "Workspace consumption",
"Workspace_consumption_description": "There's a set amount of push of allowed push notifications per month",
"Push_gateway_connection": "Push Gateway Connection",
"Custom_push_gateway_connection": "Custom Gateway Connection",
"Test_push_notification": "Test push notification",
"Push_gateway_connected_description": "Send a push notification to yourself to check if the gateway is working",
"Push_gateway_not_connected_description": "We're not able to connect to the push gateway. If this issue persists please check with your workspace administrator.",
"Custom_push_gateway_connected_description": "Your workspace uses a custom push notification gateway. Check with your workspace administrator for any issues.",
"Notification_delay": "Notification delay",
"Documentation": "Documentation",
"Notification_delay_description": "There are factors that can contribute to delayed notifications. Learn more in Rocket.Chat's docs.",
"Device_notifications_alert_title": "Notifications disabled",
"Device_notifications_alert_description": "Please go to your settings app and enable notifications for Rocket.Chat",
"Push_consumption_alert_title": "You can be limitless",
"Push_consumption_alert_description":"Talk to your workspace administrator about upgrading, and forget about notification limits!",
"Jitsi_may_require_authentication": "Jitsi may require authentication",
"Jitsi_authentication_before_making_calls_admin": "Jitsi may require authentication before making calls. To learn more about their policies, visit the Jitsi website. You can also update the default app for video calls in the preferences.",
"Jitsi_authentication_before_making_calls": "Jitsi may require authentication before making calls. To learn more about their policies, visit the Jitsi website.",
"Jitsi_authentication_before_making_calls_ask_admin": "If you believe there are problems with Jitsi and its authentication, ask a workspace administrator for help.",
"Continue": "Continue",
"Message_has_been_shared": "Message has been shared",
"No_channels_in_team": "No Channels on this team"
"Continue": "Continue"
}

View File

@ -726,8 +726,28 @@
"Select": "Selecionar",
"Nickname": "Apelido",
"Bio": "Biografia",
"Message_has_been_shared":"Menssagem foi compartilhada",
"Message_has_been_shared":"Mensagem foi compartilhada",
"No_channels_in_team": "Nenhum canal nesta equipe",
"Push_Troubleshooting": "Solucionar Problemas de Push",
"Device_notification_settings": "Configurações de notificações do dispositivo",
"Allow_push_notifications_for_rocket_chat": "Permitir notificações push para o Rocket.Chat",
"Go_to_device_settings": "Ir para configurações do dispositivo",
"Community_edition_push_quota": "Cota de notificações push Community Edition",
"Workspace_consumption": "Consumo do Workspace",
"Workspace_consumption_description": "Existe uma quantidade definida de notificações push permitidas por mês.",
"Push_gateway_connection": "Conexão com o Gateway de Push",
"Custom_push_gateway_connection": "Conexão Personalizada com o Gateway",
"Test_push_notification": "Testar notificação push",
"Push_gateway_connected_description": "Envie uma notificação push para si mesmo para verificar se o gateway está funcionando.",
"Push_gateway_not_connected_description": "Não conseguimos conectar ao gateway de push. Se esse problema persistir, por favor, verifique com o administrador do seu workspace.",
"Custom_push_gateway_connected_description": "Seu workspace utiliza um gateway de notificação push personalizado. Verifique com o administrador do seu workspace se há algum problema.",
"Notification_delay": "Atraso de notificação",
"Documentation": "Documentação",
"Notification_delay_description": "Existem fatores que podem contribuir para atrasos nas notificações. Saiba mais na documentação do Rocket.Chat.",
"Device_notifications_alert_title": "Notificações desativadas",
"Device_notifications_alert_description": "Por favor, vá para o aplicativo de configurações e habilite as notificações para o Rocket.Chat.",
"Push_consumption_alert_title": "Você pode ser ilimitado",
"Push_consumption_alert_description": "Converse com o administrador do seu workspace sobre uma atualização e esqueça os limites de notificação!",
"Jitsi_may_requires_authentication": "Jitsi pode exigir autenticação",
"Jitsi_authentication_before_making_calls_admin": "Jitsi pode exigir autenticação antes de fazer chamadas. Para saber mais sobre as políticas deles, visite o site do Jitsi. Você também pode atualizar o aplicativo padrão para chamadas de vídeo nas preferências.",
"Jitsi_authentication_before_making_calls": "Jitsi pode exigir autenticação antes de fazer chamadas. Para saber mais sobre suas políticas, visite o site do Jitsi.",

View File

@ -102,6 +102,12 @@ export const colors = {
statusBackgroundWarning: '#FFECAD',
statusFontOnWarning: '#B88D00',
overlayColor: '#1F2329B2',
fontAnnotation: '#9EA2A8',
userPresenceBusy: '#D40C26',
userPresenceOnline: '#148660',
badgeBackgroundLevel3: '#F38C39',
statusFontOnDanger: '#9B1325',
statusFontOnSuccess: '#148660',
...mentions,
...callButtons
},
@ -181,6 +187,12 @@ export const colors = {
statusBackgroundWarning: '#FFECAD',
statusFontOnWarning: '#B88D00',
overlayColor: '#1F2329B2',
fontAnnotation: '#9EA2A8',
userPresenceBusy: '#D40C26',
userPresenceOnline: '#148660',
badgeBackgroundLevel3: '#F38C39',
statusFontOnDanger: '#9B1325',
statusFontOnSuccess: '#148660',
...mentions,
...callButtons
},
@ -260,6 +272,12 @@ export const colors = {
statusBackgroundWarning: '#FFECAD',
statusFontOnWarning: '#B88D00',
overlayColor: '#1F2329B2',
fontAnnotation: '#9EA2A8',
userPresenceBusy: '#D40C26',
userPresenceOnline: '#148660',
badgeBackgroundLevel3: '#F38C39',
statusFontOnDanger: '#9B1325',
statusFontOnSuccess: '#148660',
...mentions,
...callButtons
}

View File

@ -160,7 +160,8 @@ export async function getSettings(): Promise<void> {
/* eslint-disable no-await-in-loop */
const response = await fetch(
`${sdk.current.client.host}/api/v1/settings.public?query={"_id":{"$in":${JSON.stringify(settingsParams)}}}
&offset=${offset}`);
&offset=${offset}`
);
const result = await response.json();
@ -172,7 +173,7 @@ export async function getSettings(): Promise<void> {
settings = [...settings, ...result.settings];
remaining = result.total - settings.length;
/* eslint-enable no-await-in-loop */
} while(remaining > 0);
} while (remaining > 0);
const data: IData[] = settings;
const filteredSettings: IPreparedSettings[] = _prepareSettings(data);

View File

@ -41,6 +41,7 @@ import DisplayPrefsView from '../views/DisplayPrefsView';
// Settings Stack
import SettingsView from '../views/SettingsView';
import SecurityPrivacyView from '../views/SecurityPrivacyView';
import PushTroubleshootView from '../views/PushTroubleshootView';
import E2EEncryptionSecurityView from '../views/E2EEncryptionSecurityView';
import LanguageView from '../views/LanguageView';
import ThemeView from '../views/ThemeView';
@ -116,6 +117,7 @@ const ChatsStackNavigator = () => {
<ChatsStack.Screen name='AutoTranslateView' component={AutoTranslateView} />
<ChatsStack.Screen name='DirectoryView' component={DirectoryView} options={DirectoryView.navigationOptions} />
<ChatsStack.Screen name='NotificationPrefView' component={NotificationPrefView} />
<ChatsStack.Screen name='PushTroubleshootView' component={PushTroubleshootView} />
<ChatsStack.Screen name='ForwardLivechatView' component={ForwardLivechatView} />
<ChatsStack.Screen name='CloseLivechatView' component={CloseLivechatView} />
<ChatsStack.Screen name='LivechatEditView' component={LivechatEditView} options={LivechatEditView.navigationOptions} />
@ -153,6 +155,7 @@ const ProfileStackNavigator = () => {
<ProfileStack.Screen name='UserPreferencesView' component={UserPreferencesView} />
<ProfileStack.Screen name='ChangeAvatarView' component={ChangeAvatarView} />
<ProfileStack.Screen name='UserNotificationPrefView' component={UserNotificationPrefView} />
<ProfileStack.Screen name='PushTroubleshootView' component={PushTroubleshootView} />
<ProfileStack.Screen name='PickerView' component={PickerView} />
</ProfileStack.Navigator>
);
@ -169,6 +172,7 @@ const SettingsStackNavigator = () => {
>
<SettingsStack.Screen name='SettingsView' component={SettingsView} />
<SettingsStack.Screen name='SecurityPrivacyView' component={SecurityPrivacyView} />
<SettingsStack.Screen name='PushTroubleshootView' component={PushTroubleshootView} />
<SettingsStack.Screen name='E2EEncryptionSecurityView' component={E2EEncryptionSecurityView} />
<SettingsStack.Screen name='LanguageView' component={LanguageView} />
<SettingsStack.Screen name='ThemeView' component={ThemeView} />

View File

@ -26,6 +26,7 @@ import MessagesView from '../../views/MessagesView';
import AutoTranslateView from '../../views/AutoTranslateView';
import DirectoryView from '../../views/DirectoryView';
import NotificationPrefView from '../../views/NotificationPreferencesView';
import PushTroubleshootView from '../../views/PushTroubleshootView';
import ForwardLivechatView from '../../views/ForwardLivechatView';
import ForwardMessageView from '../../views/ForwardMessageView';
import CloseLivechatView from '../../views/CloseLivechatView';
@ -184,6 +185,7 @@ const ModalStackNavigator = React.memo(({ navigation }: INavigation) => {
<ModalStack.Screen name='SecurityPrivacyView' component={SecurityPrivacyView} />
<ModalStack.Screen name='MediaAutoDownloadView' component={MediaAutoDownloadView} />
<ModalStack.Screen name='E2EEncryptionSecurityView' component={E2EEncryptionSecurityView} />
<ModalStack.Screen name='PushTroubleshootView' component={PushTroubleshootView} />
</ModalStack.Navigator>
</ModalContainer>
);

View File

@ -196,6 +196,7 @@ export type ModalStackParamList = {
SecurityPrivacyView: undefined;
MediaAutoDownloadView: undefined;
E2EEncryptionSecurityView: undefined;
PushTroubleshootView: undefined;
};
export type MasterDetailInsideStackParamList = {

View File

@ -116,6 +116,7 @@ export type ChatsStackParamList = {
rid: string;
room: TSubscriptionModel;
};
PushTroubleshootView: undefined;
CloseLivechatView: {
rid: string;
departmentId?: string;
@ -177,6 +178,7 @@ export type ProfileStackParamList = {
ProfileView: undefined;
UserPreferencesView: undefined;
UserNotificationPrefView: undefined;
PushTroubleshootView: undefined;
ChangeAvatarView: {
context: TChangeAvatarViewContext;
titleHeader?: string;
@ -196,6 +198,7 @@ export type SettingsStackParamList = {
ProfileView: undefined;
DisplayPrefsView: undefined;
MediaAutoDownloadView: undefined;
PushTroubleshootView: undefined;
};
export type AdminPanelStackParamList = {

View File

@ -0,0 +1,52 @@
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { Header } from '../../../containers/List';
const styles = StyleSheet.create({
container: {
marginBottom: 16
},
headerContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center'
},
statusContainer: {
width: 10,
height: 10,
borderRadius: 5,
marginRight: 12
}
});
interface ICustomListSection {
children: (React.ReactElement | null)[] | React.ReactElement | null;
title: string;
translateTitle?: boolean;
statusColor?: string;
}
const CustomHeader = ({
title,
translateTitle,
statusColor
}: {
title: string;
translateTitle?: boolean;
statusColor?: string;
}) => (
<View style={styles.headerContainer}>
<Header {...{ title, translateTitle }} />
{statusColor ? <View style={[styles.statusContainer, { backgroundColor: statusColor }]} /> : null}
</View>
);
const CustomListSection = ({ children, title, translateTitle, statusColor }: ICustomListSection) => (
<View style={styles.container}>
{title ? <CustomHeader {...{ title, translateTitle, statusColor }} /> : null}
{children}
</View>
);
export default CustomListSection;

View File

@ -0,0 +1,47 @@
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
}
});
const ListPercentage = ({
value = 0,
title,
testID,
onPress
}: {
title: string;
testID: string;
value: number;
onPress: () => void;
}) => {
const { colors } = useTheme();
const percentage = `${Math.floor(value)}%`;
let percentageTextColor = colors.statusFontOnSuccess;
if (value > 70 && value < 90) {
percentageTextColor = colors.statusFontOnWarning;
}
if (value >= 90) {
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,122 @@
import { StackNavigationProp } from '@react-navigation/stack';
import React, { useEffect } from 'react';
import { Alert, Linking } from 'react-native';
import * as List from '../../containers/List';
import SafeAreaView from '../../containers/SafeAreaView';
import StatusBar from '../../containers/StatusBar';
import I18n from '../../i18n';
import { SettingsStackParamList } from '../../stacks/types';
import { useTheme } from '../../theme';
import CustomListSection from './components/CustomListSection';
import ListPercentage from './components/ListPercentage';
interface IPushTroubleshootViewProps {
navigation: StackNavigationProp<SettingsStackParamList, 'PushTroubleshootView'>;
}
const PushTroubleshootView = ({ navigation }: IPushTroubleshootViewProps): JSX.Element => {
const deviceNotificationEnabled = false;
const isCommunityEdition = true;
const isPushGatewayConnected = true;
const isCustomPushGateway = true;
const consumptionPercentage = 50;
const { colors } = useTheme();
useEffect(() => {
navigation.setOptions({
title: I18n.t('Push_Troubleshooting')
});
}, [navigation]);
const openNotificationDocumentation = async () => {
await Linking.openURL('https://docs.rocket.chat/use-rocket.chat/rocket.chat-mobile/push-notifications');
};
const alertDeviceNotificationSettings = () => {
Alert.alert(I18n.t('Device_notifications_alert_title'), I18n.t('Device_notifications_alert_description'));
};
const alertWorkspaceConsumption = () => {
Alert.alert(I18n.t('Push_consumption_alert_title'), I18n.t('Push_consumption_alert_description'));
};
const handleTestPushNotification = () => {
// do nothing
};
let pushGatewayInfoDescription = 'Push_gateway_not_connected_description';
let pushGatewayStatusColor = colors.userPresenceBusy;
if (isPushGatewayConnected) {
pushGatewayStatusColor = colors.userPresenceOnline;
pushGatewayInfoDescription = 'Push_gateway_connected_description';
}
if (isPushGatewayConnected && isCustomPushGateway) {
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}
<CustomListSection
title={isCustomPushGateway ? 'Custom_push_gateway_connection' : 'Push_gateway_connection'}
statusColor={pushGatewayStatusColor}
>
<List.Separator />
<List.Item
title='Test_push_notification'
disabled={!isPushGatewayConnected}
onPress={handleTestPushNotification}
testID='push-troubleshoot-view-push-gateway-connection'
/>
<List.Separator />
<List.Info info={pushGatewayInfoDescription} />
</CustomListSection>
<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>
</List.Container>
</SafeAreaView>
);
};
export default PushTroubleshootView;

View File

@ -442,6 +442,11 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
headerTitle: () => <RoomsListHeaderView />,
headerRight: () => (
<HeaderButton.Container>
<HeaderButton.Item
iconName='notification-disabled'
onPress={this.goPushTroubleshoot}
testID='rooms-list-view-push-troubleshoot'
/>
{canCreateRoom ? (
<HeaderButton.Item iconName='create' onPress={this.goToNewMessage} testID='rooms-list-view-create-channel' />
) : null}
@ -744,6 +749,15 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
}
};
goPushTroubleshoot = () => {
const { navigation, isMasterDetail } = this.props;
if (isMasterDetail) {
navigation.navigate('ModalStackNavigator', { screen: 'PushTroubleshootView' });
} else {
navigation.navigate('PushTroubleshootView');
}
};
goQueue = () => {
logEvent(events.RL_GO_QUEUE);
const { navigation, isMasterDetail, inquiryEnabled } = this.props;