MM-39711 - Gekidou Settings Push Notification functionality (#6373)

* adding nav hooks

* added save button

* capturing value from OptionItem

* notification - saving in progress

* tested API

* corrections after review

* Update en.json

* Update notification_push.tsx

* ts fixes

* minor improvement

Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
This commit is contained in:
Avinash Lingaloo
2022-06-14 10:35:50 +04:00
committed by GitHub
parent bfffa0e10a
commit 9370a9c54e
6 changed files with 103 additions and 40 deletions

View File

@@ -6,14 +6,16 @@ import withObservables from '@nozbe/with-observables';
import {observeConfigBooleanValue} from '@queries/servers/system';
import {observeIsCRTEnabled} from '@queries/servers/thread';
import {observeCurrentUser} from '@queries/servers/user';
import {WithDatabaseArgs} from '@typings/database/database';
import NotificationPush from './notification_push';
const enhanced = withObservables([], ({database}: WithDatabaseArgs) => {
return {
sendPushNotifications: observeConfigBooleanValue(database, 'SendPushNotifications'),
currentUser: observeCurrentUser(database),
isCRTEnabled: observeIsCRTEnabled(database),
sendPushNotifications: observeConfigBooleanValue(database, 'SendPushNotifications'),
};
});

View File

@@ -1,17 +1,26 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useState} from 'react';
import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {useIntl} from 'react-intl';
import {ScrollView} from 'react-native';
import {Edge, SafeAreaView} from 'react-native-safe-area-context';
import {updateMe} from '@actions/remote/user';
import {useServerUrl} from '@context/server';
import {useTheme} from '@context/theme';
import useAndroidHardwareBackHandler from '@hooks/android_back_handler';
import useNavButtonPressed from '@hooks/navigation_button_pressed';
import {popTopScreen, setButtons} from '@screens/navigation';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {getNotificationProps} from '@utils/user';
import MobileSendPush from './push_send';
import MobilePushStatus from './push_status';
import MobilePushThread from './push_thread';
import type UserModel from '@typings/database/models/servers/user';
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
container: {
@@ -27,31 +36,78 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
},
};
});
const edges: Edge[] = ['left', 'right'];
const SAVE_NOTIF_BUTTON_ID = 'SAVE_NOTIF_BUTTON_ID';
type NotificationMobileProps = {
componentId: string;
currentUser: UserModel;
isCRTEnabled: boolean;
sendPushNotifications: boolean;
};
const NotificationPush = ({isCRTEnabled, sendPushNotifications}: NotificationMobileProps) => {
const theme = useTheme();
const [pushStatus, setPushStatus] = useState<PushStatus>('online');
const [pushPref, setPushPref] = useState<PushStatus>('online');
const [pushThread, setPushThreadPref] = useState<PushStatus>('online');
const NotificationPush = ({componentId, currentUser, isCRTEnabled, sendPushNotifications}: NotificationMobileProps) => {
const serverUrl = useServerUrl();
const notifyProps = useMemo(() => getNotificationProps(currentUser), [currentUser.notifyProps]);
const [pushSend, setPushSend] = useState<PushStatus>(notifyProps.push);
const [pushStatus, setPushStatus] = useState<PushStatus>(notifyProps.push_status);
const [pushThread, setPushThreadPref] = useState<PushStatus>(notifyProps?.push_threads || 'all');
const intl = useIntl();
const theme = useTheme();
const styles = getStyleSheet(theme);
const setMobilePushStatus = (status: PushStatus) => {
setPushStatus(status);
};
const onMobilePushThreadChanged = useCallback(() => {
setPushThreadPref(pushThread === 'all' ? 'mention' : 'all');
}, [pushThread]);
const setMobilePushPref = (status: PushStatus) => {
setPushPref(status);
};
const saveButton = useMemo(() => {
return {
id: SAVE_NOTIF_BUTTON_ID,
enabled: false,
showAsAction: 'always' as const,
testID: 'notification_settings.save.button',
color: theme.sidebarHeaderTextColor,
text: intl.formatMessage({id: 'settings.save', defaultMessage: 'Save'}),
};
}, [theme.sidebarHeaderTextColor]);
const onMobilePushThreadChanged = (status: PushStatus) => {
setPushThreadPref(status);
};
const close = useCallback(() => popTopScreen(componentId), [componentId]);
const saveNotificationSettings = useCallback(() => {
const notify_props = {...notifyProps, push: pushSend, push_status: pushStatus, push_threads: pushThread};
updateMe(serverUrl, {notify_props} as unknown as UserNotifyProps);
close();
}, [serverUrl, notifyProps, pushSend, pushStatus, pushThread, close]);
useEffect(() => {
const p = pushSend !== notifyProps.push;
const pT = pushThread !== notifyProps.push_threads;
const pS = pushStatus !== notifyProps.push_status;
const enabled = p || pT || pS;
const buttons = {
rightButtons: [{
...saveButton,
enabled,
}],
};
setButtons(componentId, buttons);
}, [
componentId,
notifyProps,
pushSend,
pushStatus,
pushThread,
]);
useNavButtonPressed(SAVE_NOTIF_BUTTON_ID, componentId, saveNotificationSettings, [saveNotificationSettings]);
useAndroidHardwareBackHandler(componentId, close);
return (
<SafeAreaView
@@ -65,20 +121,20 @@ const NotificationPush = ({isCRTEnabled, sendPushNotifications}: NotificationMob
alwaysBounceVertical={false}
>
<MobileSendPush
pushStatus={pushSend}
sendPushNotifications={sendPushNotifications}
pushStatus={pushPref}
setMobilePushPref={setMobilePushPref}
setMobilePushPref={setPushSend}
/>
{isCRTEnabled && pushPref === 'mention' && (
{isCRTEnabled && pushSend === 'mention' && (
<MobilePushThread
pushThread={pushThread}
onMobilePushThreadChanged={onMobilePushThreadChanged}
/>
)}
{sendPushNotifications && pushPref !== 'none' && (
{sendPushNotifications && pushSend !== 'none' && (
<MobilePushStatus
pushStatus={pushStatus}
setMobilePushStatus={setMobilePushStatus}
setMobilePushStatus={setPushStatus}
/>
)}
</ScrollView>

View File

@@ -1,7 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import React, {useCallback} from 'react';
import {useIntl} from 'react-intl';
import {Platform, ScrollView, View} from 'react-native';
import {Edge, SafeAreaView} from 'react-native-safe-area-context';
@@ -37,6 +37,16 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
});
const edges: Edge[] = ['left', 'right'];
const mentionTexts = {
crtOn: {
id: t('notification_settings.mentions'),
defaultMessage: 'Mentions',
},
crtOff: {
id: t('notification_settings.mentions_replies'),
defaultMessage: 'Mentions and Replies',
},
};
type NotificationsProps = {
isCRTEnabled: boolean;
enableAutoResponder: boolean;
@@ -46,14 +56,7 @@ const Notifications = ({isCRTEnabled, enableAutoResponder}: NotificationsProps)
const styles = getStyleSheet(theme);
const intl = useIntl();
let mentionsI18nId = t('notification_settings.mentions_replies');
let mentionsI18nDefault = 'Mentions and Replies';
if (isCRTEnabled) {
mentionsI18nId = t('notification_settings.mentions');
mentionsI18nDefault = 'Mentions';
}
const goToNotificationSettingsMentions = () => {
const goToNotificationSettingsMentions = useCallback(() => {
const screen = Screens.SETTINGS_NOTIFICATION_MENTION;
const id = isCRTEnabled ? t('notification_settings.mentions') : t('notification_settings.mentions_replies');
@@ -61,9 +64,9 @@ const Notifications = ({isCRTEnabled, enableAutoResponder}: NotificationsProps)
const title = intl.formatMessage({id, defaultMessage});
goToScreen(screen, title);
};
}, [isCRTEnabled]);
const goToNotificationSettingsPush = () => {
const goToNotificationSettingsPush = useCallback(() => {
const screen = Screens.SETTINGS_NOTIFICATION_PUSH;
const title = intl.formatMessage({
id: 'notification_settings.push_notification',
@@ -71,16 +74,16 @@ const Notifications = ({isCRTEnabled, enableAutoResponder}: NotificationsProps)
});
goToScreen(screen, title);
};
}, []);
const goToNotificationAutoResponder = () => {
const goToNotificationAutoResponder = useCallback(() => {
const screen = Screens.SETTINGS_NOTIFICATION_AUTO_RESPONDER;
const title = intl.formatMessage({
id: 'notification_settings.auto_responder',
defaultMessage: 'Automatic Replies',
});
goToScreen(screen, title);
};
}, []);
return (
<SafeAreaView
@@ -94,8 +97,8 @@ const Notifications = ({isCRTEnabled, enableAutoResponder}: NotificationsProps)
>
<View style={styles.divider}/>
<SettingOption
defaultMessage={mentionsI18nDefault}
i18nId={mentionsI18nId}
defaultMessage={isCRTEnabled ? mentionTexts.crtOn.defaultMessage : mentionTexts.crtOff.defaultMessage}
i18nId={isCRTEnabled ? mentionTexts.crtOn.id : mentionTexts.crtOff.id}
onPress={goToNotificationSettingsMentions}
optionName='mentions'
/>

View File

@@ -307,16 +307,17 @@ export function getNotificationProps(user: UserModel) {
}
const props: UserNotifyProps = {
email: 'true',
mark_unread: 'all',
channel: 'true',
comments: 'any',
desktop: 'all',
desktop_sound: 'true',
email: 'true',
first_name: (!user || !user.firstName) ? 'false' : 'true',
mark_unread: 'all',
mention_keys: user ? `${user.username},@${user.username}` : '',
push: 'mention',
push_status: 'online',
push_threads: 'all',
};
return props;

View File

@@ -16,6 +16,7 @@ type UserNotifyProps = {
push: 'default' | 'all' | 'mention' | 'none';
push_status: 'ooo' | 'offline' | 'away' | 'dnd' | 'online';
user_id?: string;
push_threads?: 'all' | 'mention';
};
type UserProfile = {

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
type PushStatus = 'away' | 'online' | 'offline' | 'none' | 'mention' | 'all';
type PushStatus = 'away' | 'online' | 'offline' | 'none' | 'mention' | 'all' | 'ooo' | 'dnd' | 'default' ;