diff --git a/app/definitions/ISubscription.ts b/app/definitions/ISubscription.ts index a5a044e6a..c6b0e5f57 100644 --- a/app/definitions/ISubscription.ts +++ b/app/definitions/ISubscription.ts @@ -111,9 +111,10 @@ export interface ISubscription { uploads: RelationModified; } -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 diff --git a/app/i18n/locales/en.json b/app/i18n/locales/en.json index 074192f9b..e5bf1b504 100644 --- a/app/i18n/locales/en.json +++ b/app/i18n/locales/en.json @@ -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" } diff --git a/app/i18n/locales/pt-BR.json b/app/i18n/locales/pt-BR.json index 0fedb4ed9..2becbd580 100644 --- a/app/i18n/locales/pt-BR.json +++ b/app/i18n/locales/pt-BR.json @@ -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.", diff --git a/app/lib/constants/colors.ts b/app/lib/constants/colors.ts index daf1f588b..4231b0145 100644 --- a/app/lib/constants/colors.ts +++ b/app/lib/constants/colors.ts @@ -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 } diff --git a/app/lib/methods/getSettings.ts b/app/lib/methods/getSettings.ts index c3c9cd9bb..a0db49385 100644 --- a/app/lib/methods/getSettings.ts +++ b/app/lib/methods/getSettings.ts @@ -160,7 +160,8 @@ export async function getSettings(): Promise { /* 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 { 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); diff --git a/app/stacks/InsideStack.tsx b/app/stacks/InsideStack.tsx index 56374a36e..a53606ff9 100644 --- a/app/stacks/InsideStack.tsx +++ b/app/stacks/InsideStack.tsx @@ -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 = () => { + @@ -153,6 +155,7 @@ const ProfileStackNavigator = () => { + ); @@ -169,6 +172,7 @@ const SettingsStackNavigator = () => { > + diff --git a/app/stacks/MasterDetailStack/index.tsx b/app/stacks/MasterDetailStack/index.tsx index 163d963cd..3bf55d4e3 100644 --- a/app/stacks/MasterDetailStack/index.tsx +++ b/app/stacks/MasterDetailStack/index.tsx @@ -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) => { + ); diff --git a/app/stacks/MasterDetailStack/types.ts b/app/stacks/MasterDetailStack/types.ts index 1d778b108..dd76559cc 100644 --- a/app/stacks/MasterDetailStack/types.ts +++ b/app/stacks/MasterDetailStack/types.ts @@ -196,6 +196,7 @@ export type ModalStackParamList = { SecurityPrivacyView: undefined; MediaAutoDownloadView: undefined; E2EEncryptionSecurityView: undefined; + PushTroubleshootView: undefined; }; export type MasterDetailInsideStackParamList = { diff --git a/app/stacks/types.ts b/app/stacks/types.ts index 32715c662..99688992e 100644 --- a/app/stacks/types.ts +++ b/app/stacks/types.ts @@ -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 = { diff --git a/app/views/PushTroubleshootView/components/CustomListSection.tsx b/app/views/PushTroubleshootView/components/CustomListSection.tsx new file mode 100644 index 000000000..8bf02c3f9 --- /dev/null +++ b/app/views/PushTroubleshootView/components/CustomListSection.tsx @@ -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; +}) => ( + +
+ {statusColor ? : null} + +); + +const CustomListSection = ({ children, title, translateTitle, statusColor }: ICustomListSection) => ( + + {title ? : null} + {children} + +); + +export default CustomListSection; diff --git a/app/views/PushTroubleshootView/components/ListPercentage.tsx b/app/views/PushTroubleshootView/components/ListPercentage.tsx new file mode 100644 index 000000000..e0c23184a --- /dev/null +++ b/app/views/PushTroubleshootView/components/ListPercentage.tsx @@ -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 ( + {percentage}} + /> + ); +}; + +export default ListPercentage; diff --git a/app/views/PushTroubleshootView/index.tsx b/app/views/PushTroubleshootView/index.tsx new file mode 100644 index 000000000..f27b22f28 --- /dev/null +++ b/app/views/PushTroubleshootView/index.tsx @@ -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; +} + +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 ( + + + + + + + + + + {isCommunityEdition ? ( + + + + + + + ) : null} + + + + + + + + + + + } + testID='push-troubleshoot-view-notification-delay' + /> + + + + + + ); +}; + +export default PushTroubleshootView; diff --git a/app/views/RoomsListView/index.tsx b/app/views/RoomsListView/index.tsx index 736c9f6c3..897d7fd1f 100644 --- a/app/views/RoomsListView/index.tsx +++ b/app/views/RoomsListView/index.tsx @@ -442,6 +442,11 @@ class RoomsListView extends React.Component , headerRight: () => ( + {canCreateRoom ? ( ) : null} @@ -744,6 +749,15 @@ class RoomsListView extends React.Component { + 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;