MM-39711 - Gekidou Notification Push Notification main screen (#6312)
* added chevron to menu item component * starting with the skeleton * starting with the skeleton * starting with the skeleton * starting with the skeleton * remove extra line * tested on tablets * some corrections * corrections as per review * starting with notification skeleton * attached notification settings to navigation * added auto responder * update translation * update snapshot * updated snapshot * correction after review * removed unnecessary screen * refactored * updated the testIDs * Update Package.resolved * refactor * removed Mattermost as default server name * fix ts * refactored settings constant * display settings skeleton - pending: query for allowed themes * added 'allowedThemes' query * added section item * mention screen skeleton in place * added section and sectionItem component * added reply section to the mention screen * update i18n * rename screens properly * update i18n * Refactored to MentionSettings component * Refactored to ReplySettings component * style clean up * textTransform uppercase * rename Section/SectionItem to Block/BlockItem * added mobile push notif screen - push status section * adding text to those two components * correction following review * added mobile push notification section * added mobile push notification thread section * style fix * code fix * code fix * MM-39711 - Gekidou Notification - Auto Responder main screen (#6313) * added skeleton for auto responder * code clean up * correction from peer review * correction from PR review * clean up * PR review correction * correction * clean up * clean up * code clean up * code clean up
This commit is contained in:
parent
18a94f2b33
commit
2d3d43c000
20 changed files with 699 additions and 126 deletions
|
|
@ -2,7 +2,7 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {ReactElement, useCallback, useMemo} from 'react';
|
||||
import {Switch, Text, TouchableOpacity, View} from 'react-native';
|
||||
import {StyleProp, Switch, Text, TextStyle, TouchableOpacity, View, ViewStyle} from 'react-native';
|
||||
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
import {useTheme} from '@context/theme';
|
||||
|
|
@ -36,15 +36,12 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
},
|
||||
label: {
|
||||
color: theme.centerChannelColor,
|
||||
...typography('Body', 600, 'SemiBold'),
|
||||
fontSize: 16,
|
||||
lineHeight: 24,
|
||||
...typography('Body', 200, 'SemiBold'),
|
||||
marginLeft: 9,
|
||||
},
|
||||
description: {
|
||||
color: changeOpacity(theme.centerChannelColor, 0.6),
|
||||
...typography('Body', 400, 'Regular'),
|
||||
fontSize: 12,
|
||||
lineHeight: 16,
|
||||
...typography('Body', 75, 'Regular'),
|
||||
marginTop: 3,
|
||||
},
|
||||
arrow: {
|
||||
|
|
@ -62,14 +59,29 @@ type Props = {
|
|||
action: (value: string | boolean) => void;
|
||||
actionType: string;
|
||||
actionValue?: string;
|
||||
containerStyle?: StyleProp<ViewStyle>;
|
||||
description?: string | ReactElement;
|
||||
descriptionStyle?: StyleProp<TextStyle>;
|
||||
icon?: string;
|
||||
label: string | ReactElement;
|
||||
labelStyle?: StyleProp<TextStyle>;
|
||||
selected?: boolean;
|
||||
testID?: string;
|
||||
}
|
||||
|
||||
const BlockItem = ({testID = 'sectionItem', action, actionType, actionValue, label, selected, description, icon}: Props) => {
|
||||
const BlockItem = ({
|
||||
action,
|
||||
actionType,
|
||||
actionValue,
|
||||
containerStyle,
|
||||
description,
|
||||
descriptionStyle,
|
||||
icon,
|
||||
label,
|
||||
labelStyle,
|
||||
selected,
|
||||
testID = 'sectionItem',
|
||||
}: Props) => {
|
||||
const theme = useTheme();
|
||||
const style = getStyleSheet(theme);
|
||||
|
||||
|
|
@ -104,17 +116,17 @@ const BlockItem = ({testID = 'sectionItem', action, actionType, actionValue, lab
|
|||
action(actionValue || '');
|
||||
}, [actionValue, action]);
|
||||
|
||||
const labelStyle = useMemo(() => {
|
||||
const labelStyles = useMemo(() => {
|
||||
if (icon) {
|
||||
return [style.label, {marginLeft: 4}];
|
||||
}
|
||||
return style.label;
|
||||
return [style.label, labelStyle];
|
||||
}, [Boolean(icon), style]);
|
||||
|
||||
const component = (
|
||||
<View
|
||||
testID={testID}
|
||||
style={style.container}
|
||||
style={[style.container, containerStyle]}
|
||||
>
|
||||
<View style={description ? style.doubleContainer : style.singleContainer}>
|
||||
<View style={style.labelContainer}>
|
||||
|
|
@ -126,14 +138,14 @@ const BlockItem = ({testID = 'sectionItem', action, actionType, actionValue, lab
|
|||
/>
|
||||
)}
|
||||
<Text
|
||||
style={labelStyle}
|
||||
style={labelStyles}
|
||||
testID={`${testID}.label`}
|
||||
>
|
||||
{label}
|
||||
</Text>
|
||||
</View>
|
||||
<Text
|
||||
style={style.description}
|
||||
style={[style.description, descriptionStyle]}
|
||||
testID={`${testID}.description`}
|
||||
>
|
||||
{description}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,9 @@ export const SERVER = 'Server';
|
|||
export const SETTINGS = 'Settings';
|
||||
export const SETTINGS_DISPLAY = 'SettingsDisplay';
|
||||
export const SETTINGS_NOTIFICATION = 'SettingsNotification';
|
||||
export const SETTINGS_NOTIFICATION_AUTO_RESPONDER = 'SettingsNotificationAutoResponder';
|
||||
export const SETTINGS_NOTIFICATION_MENTION = 'SettingsNotificationMention';
|
||||
export const SETTINGS_NOTIFICATION_PUSH = 'SettingsNotificationPush';
|
||||
export const SNACK_BAR = 'SnackBar';
|
||||
export const SSO = 'SSO';
|
||||
export const THREAD = 'Thread';
|
||||
|
|
@ -95,7 +97,9 @@ export default {
|
|||
SETTINGS,
|
||||
SETTINGS_DISPLAY,
|
||||
SETTINGS_NOTIFICATION,
|
||||
SETTINGS_NOTIFICATION_AUTO_RESPONDER,
|
||||
SETTINGS_NOTIFICATION_MENTION,
|
||||
SETTINGS_NOTIFICATION_PUSH,
|
||||
SNACK_BAR,
|
||||
SSO,
|
||||
THREAD,
|
||||
|
|
|
|||
|
|
@ -197,6 +197,12 @@ Navigation.setLazyComponentRegistrator((screenName) => {
|
|||
case Screens.SETTINGS_NOTIFICATION_MENTION:
|
||||
screen = withServerDatabase(require('@screens/settings/notification_mention').default);
|
||||
break;
|
||||
case Screens.SETTINGS_NOTIFICATION_PUSH:
|
||||
screen = withServerDatabase(require('@screens/settings/notification_push').default);
|
||||
break;
|
||||
case Screens.SETTINGS_NOTIFICATION_AUTO_RESPONDER:
|
||||
screen = withServerDatabase(require('@screens/settings/notification_auto_responder').default);
|
||||
break;
|
||||
}
|
||||
|
||||
if (screen) {
|
||||
|
|
|
|||
|
|
@ -43,13 +43,13 @@ export const NotificationsOptionConfig = {
|
|||
},
|
||||
push_notification: {
|
||||
defaultMessage: 'Push Notifications',
|
||||
i18nId: t('mobile.notification_settings.mobile'),
|
||||
i18nId: t('notification_settings.mobile'),
|
||||
iconName: 'cellphone',
|
||||
testID: 'notification_settings.push_notification',
|
||||
},
|
||||
automatic_dm_replies: {
|
||||
defaultMessage: 'Automatic Direct Message Replies',
|
||||
i18nId: t('mobile.notification_settings.ooo_auto_responder'),
|
||||
i18nId: t('notification_settings.ooo_auto_responder'),
|
||||
iconName: 'reply-outline',
|
||||
testID: 'notification_settings.automatic_dm_replies',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ const Display = ({isTimezoneEnabled, isThemeSwitchingEnabled}: DisplayProps) =>
|
|||
return (
|
||||
<SafeAreaView
|
||||
edges={['left', 'right']}
|
||||
testID='notification_settings.screen'
|
||||
testID='notification_display.screen'
|
||||
style={styles.container}
|
||||
>
|
||||
<ScrollView
|
||||
|
|
|
|||
18
app/screens/settings/notification_auto_responder/index.ts
Normal file
18
app/screens/settings/notification_auto_responder/index.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
|
||||
import withObservables from '@nozbe/with-observables';
|
||||
|
||||
import {observeCurrentUser} from '@queries/servers/user';
|
||||
import {WithDatabaseArgs} from '@typings/database/database';
|
||||
|
||||
import NotificationAutoResponder from './notification_auto_responder';
|
||||
|
||||
const enhanced = withObservables([], ({database}: WithDatabaseArgs) => {
|
||||
return {
|
||||
currentUser: observeCurrentUser(database),
|
||||
};
|
||||
});
|
||||
|
||||
export default withDatabase(enhanced(NotificationAutoResponder));
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useCallback, useMemo, useRef, useState} from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {View} from 'react-native';
|
||||
import {Edge, SafeAreaView} from 'react-native-safe-area-context';
|
||||
|
||||
import BlockItem from '@components/block_item';
|
||||
import FloatingTextInput from '@components/floating_text_input_label';
|
||||
import FormattedText from '@components/formatted_text';
|
||||
import {General} from '@constants';
|
||||
import {useTheme} from '@context/theme';
|
||||
import {t} from '@i18n';
|
||||
import {changeOpacity, makeStyleSheetFromTheme, getKeyboardAppearanceFromTheme} from '@utils/theme';
|
||||
import {typography} from '@utils/typography';
|
||||
import {getNotificationProps} from '@utils/user';
|
||||
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
const headerText = {
|
||||
id: t('notification_settings.auto_responder'),
|
||||
defaultMessage: 'Custom message',
|
||||
};
|
||||
|
||||
const OOO = {
|
||||
id: t('notification_settings.auto_responder.default_message'),
|
||||
defaultMessage: 'Hello, I am out of office and unable to respond to messages.',
|
||||
};
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
|
||||
return {
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
wrapper: {
|
||||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.06),
|
||||
flex: 1,
|
||||
paddingTop: 35,
|
||||
},
|
||||
input: {
|
||||
color: theme.centerChannelColor,
|
||||
fontSize: 15,
|
||||
height: 150,
|
||||
paddingHorizontal: 15,
|
||||
paddingVertical: 10,
|
||||
},
|
||||
footer: {
|
||||
paddingHorizontal: 15,
|
||||
color: changeOpacity(theme.centerChannelColor, 0.5),
|
||||
textAlign: 'justify',
|
||||
...typography('Body', 75),
|
||||
},
|
||||
area: {
|
||||
paddingHorizontal: 16,
|
||||
},
|
||||
label: {
|
||||
color: theme.centerChannelColor,
|
||||
...typography('Body', 200, 'Regular'),
|
||||
},
|
||||
enabled: {
|
||||
paddingHorizontal: 8,
|
||||
backgroundColor: theme.centerChannelBg,
|
||||
marginBottom: 16,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const edges: Edge[] = ['left', 'right'];
|
||||
type NotificationAutoResponderProps = {
|
||||
currentUser: UserModel;
|
||||
}
|
||||
const NotificationAutoResponder = ({currentUser}: NotificationAutoResponderProps) => {
|
||||
const theme = useTheme();
|
||||
const autoresponderRef = useRef(null);
|
||||
const intl = useIntl();
|
||||
const userNotifyProps = useMemo(() => getNotificationProps(currentUser), [currentUser.notifyProps]);
|
||||
|
||||
const [notifyProps, setNotifyProps] = useState<Partial<UserNotifyProps>>({
|
||||
...userNotifyProps,
|
||||
auto_responder_active: (currentUser.status === General.OUT_OF_OFFICE && userNotifyProps.auto_responder_active) ? 'true' : 'false',
|
||||
auto_responder_message: userNotifyProps.auto_responder_message || intl.formatMessage(OOO),
|
||||
});
|
||||
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
const onAutoResponseToggle = useCallback((active: boolean) => {
|
||||
setNotifyProps({
|
||||
...notifyProps,
|
||||
auto_responder_active: `${active}`,
|
||||
});
|
||||
}, [notifyProps]);
|
||||
|
||||
const onAutoResponseChangeText = useCallback((message: string) => {
|
||||
setNotifyProps({
|
||||
...notifyProps,
|
||||
auto_responder_message: message,
|
||||
});
|
||||
}, [notifyProps]);
|
||||
|
||||
return (
|
||||
<SafeAreaView
|
||||
edges={edges}
|
||||
style={styles.container}
|
||||
>
|
||||
<View style={styles.wrapper}>
|
||||
<View
|
||||
style={styles.enabled}
|
||||
>
|
||||
<BlockItem
|
||||
label={
|
||||
<FormattedText
|
||||
id='notification_settings.auto_responder.enabled'
|
||||
defaultMessage='Enabled'
|
||||
style={styles.label}
|
||||
/>}
|
||||
action={onAutoResponseToggle}
|
||||
actionType='toggle'
|
||||
selected={notifyProps.auto_responder_active === 'true'}
|
||||
/>
|
||||
</View>
|
||||
{notifyProps.auto_responder_active === 'true' && (
|
||||
<FloatingTextInput
|
||||
allowFontScaling={true}
|
||||
autoCapitalize='none'
|
||||
autoCorrect={false}
|
||||
blurOnSubmit={true}
|
||||
keyboardAppearance={getKeyboardAppearanceFromTheme(theme)}
|
||||
label={intl.formatMessage(headerText)}
|
||||
multiline={true}
|
||||
onChangeText={onAutoResponseChangeText}
|
||||
placeholder={intl.formatMessage(headerText)}
|
||||
placeholderTextColor={changeOpacity(theme.centerChannelColor, 0.4)}
|
||||
ref={autoresponderRef}
|
||||
returnKeyType='done'
|
||||
style={styles.input}
|
||||
textAlignVertical='top'
|
||||
theme={theme}
|
||||
underlineColorAndroid='transparent'
|
||||
value={notifyProps.auto_responder_message || ''}
|
||||
/>
|
||||
)}
|
||||
<FormattedText
|
||||
id={'notification_settings.auto_responder.footer_message'}
|
||||
defaultMessage={'Set a custom message that will be automatically sent in response to Direct Messages. Mentions in Public and Private Channels will not trigger the automated reply. Enabling Automatic Replies sets your status to Out of Office and disables email and push notifications.'}
|
||||
style={styles.footer}
|
||||
/>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotificationAutoResponder;
|
||||
|
|
@ -2,11 +2,11 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useReducer} from 'react';
|
||||
import {Alert, Text, View} from 'react-native';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {Alert, View} from 'react-native';
|
||||
|
||||
import Block from '@components/block';
|
||||
import BlockItem from '@components/block_item';
|
||||
import FormattedText from '@components/formatted_text';
|
||||
import {useTheme} from '@context/theme';
|
||||
import {t} from '@i18n';
|
||||
import UserModel from '@typings/database/models/servers/user';
|
||||
|
|
@ -47,19 +47,21 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.1),
|
||||
flex: 1,
|
||||
height: 1,
|
||||
marginLeft: 15,
|
||||
},
|
||||
area: {
|
||||
paddingHorizontal: 16,
|
||||
},
|
||||
upperCase: {
|
||||
textTransform: 'uppercase',
|
||||
},
|
||||
label: {
|
||||
color: theme.centerChannelColor,
|
||||
...typography('Body', 400, 'Regular'),
|
||||
fontSize: 16,
|
||||
lineHeight: 24,
|
||||
...typography('Body', 200, 'Regular'),
|
||||
},
|
||||
desc: {
|
||||
color: theme.centerChannelColor,
|
||||
...typography('Body', 100, 'Regular'),
|
||||
paddingLeft: 8,
|
||||
},
|
||||
container: {
|
||||
paddingHorizontal: 8,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
@ -72,18 +74,7 @@ const MentionSettings = ({currentUser, mentionKeys}: MentionSectionProps) => {
|
|||
const [{firstName, usernameMention, channel}, dispatch] = useReducer(reducer, INITIAL_STATE);
|
||||
const theme = useTheme();
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
let mentionKeysComponent;
|
||||
if (mentionKeys) {
|
||||
mentionKeysComponent = (<Text>{mentionKeys}</Text>);
|
||||
} else {
|
||||
mentionKeysComponent = (
|
||||
<FormattedText
|
||||
id='notification_settings.mentions.keywordsDescription'
|
||||
defaultMessage='Other words that trigger a mention'
|
||||
/>
|
||||
);
|
||||
}
|
||||
const intl = useIntl();
|
||||
|
||||
const toggleChannelMentions = () => {
|
||||
dispatch({
|
||||
|
|
@ -119,24 +110,17 @@ const MentionSettings = ({currentUser, mentionKeys}: MentionSectionProps) => {
|
|||
<Block
|
||||
headerText={mentionHeaderText}
|
||||
headerStyles={styles.upperCase}
|
||||
containerStyles={styles.area}
|
||||
>
|
||||
{ Boolean(currentUser?.firstName) && (
|
||||
<>
|
||||
<BlockItem
|
||||
label={(
|
||||
<Text style={styles.label}>
|
||||
{currentUser!.firstName}
|
||||
</Text>
|
||||
)}
|
||||
description={(
|
||||
<FormattedText
|
||||
id='notification_settings.mentions.sensitiveName'
|
||||
defaultMessage='Your case sensitive first name'
|
||||
/>
|
||||
)}
|
||||
action={toggleFirstNameMention}
|
||||
actionType='toggle'
|
||||
containerStyle={styles.container}
|
||||
description={intl.formatMessage({id: 'notification_settings.mentions.sensitiveName', defaultMessage: 'Your case sensitive first name'})}
|
||||
descriptionStyle={styles.desc}
|
||||
label={currentUser!.firstName}
|
||||
labelStyle={styles.label}
|
||||
selected={firstName}
|
||||
/>
|
||||
<View style={styles.separator}/>
|
||||
|
|
@ -145,51 +129,36 @@ const MentionSettings = ({currentUser, mentionKeys}: MentionSectionProps) => {
|
|||
}
|
||||
{Boolean(currentUser?.username) && (
|
||||
<BlockItem
|
||||
label={(
|
||||
<Text style={styles.label}>
|
||||
{currentUser!.username}
|
||||
</Text>
|
||||
)}
|
||||
description={(
|
||||
<FormattedText
|
||||
id='notification_settings.mentions.sensitiveUsername'
|
||||
defaultMessage='Your non-case sensitive username'
|
||||
/>
|
||||
)}
|
||||
selected={usernameMention}
|
||||
action={toggleUsernameMention}
|
||||
actionType='toggle'
|
||||
containerStyle={styles.container}
|
||||
description={intl.formatMessage({id: 'notification_settings.mentions.sensitiveUsername', defaultMessage: 'Your non-case sensitive username'})}
|
||||
descriptionStyle={styles.desc}
|
||||
label={currentUser!.username}
|
||||
labelStyle={styles.label}
|
||||
selected={usernameMention}
|
||||
/>
|
||||
)}
|
||||
<View style={styles.separator}/>
|
||||
<BlockItem
|
||||
label={(
|
||||
<Text style={styles.label}>
|
||||
{'@channel, @all, @here'}
|
||||
</Text>
|
||||
)}
|
||||
description={(
|
||||
<FormattedText
|
||||
id='notification_settings.mentions.channelWide'
|
||||
defaultMessage='Channel-wide mentions'
|
||||
/>
|
||||
)}
|
||||
action={toggleChannelMentions}
|
||||
actionType='toggle'
|
||||
containerStyle={styles.container}
|
||||
description={intl.formatMessage({id: 'notification_settings.mentions.channelWide', defaultMessage: 'Channel-wide mentions'})}
|
||||
descriptionStyle={styles.desc}
|
||||
label='@channel, @all, @here'
|
||||
labelStyle={styles.label}
|
||||
selected={channel}
|
||||
/>
|
||||
<View style={styles.separator}/>
|
||||
<BlockItem
|
||||
label={(
|
||||
<FormattedText
|
||||
id='notification_settings.mentions.keywords'
|
||||
defaultMessage='Keywords'
|
||||
style={styles.label}
|
||||
/>
|
||||
)}
|
||||
description={mentionKeysComponent}
|
||||
action={goToNotificationSettingsMentionKeywords}
|
||||
actionType='arrow'
|
||||
containerStyle={styles.container}
|
||||
description={mentionKeys || intl.formatMessage({id: 'notification_settings.mentions.keywordsDescription', defaultMessage: 'Other words that trigger a mention'})}
|
||||
descriptionStyle={styles.desc}
|
||||
label={intl.formatMessage({id: 'notification_settings.mentions.keywords', defaultMessage: 'Keywords'})}
|
||||
labelStyle={styles.label}
|
||||
/>
|
||||
</Block>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ const NotificationMention = ({currentUser, mentionKeys, isCRTEnabled}: Notificat
|
|||
return (
|
||||
<SafeAreaView
|
||||
edges={['left', 'right']}
|
||||
testID='notification_settings.screen'
|
||||
testID='notification_mention.screen'
|
||||
style={styles.container}
|
||||
>
|
||||
<ScrollView
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useState} from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {View} from 'react-native';
|
||||
|
||||
import Block from '@components/block';
|
||||
import BlockItem from '@components/block_item';
|
||||
import FormattedText from '@components/formatted_text';
|
||||
import {useTheme} from '@context/theme';
|
||||
import {t} from '@i18n';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
|
|
@ -19,23 +19,20 @@ const replyHeaderText = {
|
|||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
return {
|
||||
area: {
|
||||
paddingHorizontal: 16,
|
||||
},
|
||||
separator: {
|
||||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.1),
|
||||
flex: 1,
|
||||
height: 1,
|
||||
marginLeft: 15,
|
||||
},
|
||||
upperCase: {
|
||||
textTransform: 'uppercase',
|
||||
},
|
||||
label: {
|
||||
color: theme.centerChannelColor,
|
||||
...typography('Body', 400, 'Regular'),
|
||||
fontSize: 16,
|
||||
lineHeight: 24,
|
||||
...typography('Body', 200, 'Regular'),
|
||||
},
|
||||
container: {
|
||||
paddingHorizontal: 8,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
@ -44,6 +41,7 @@ const ReplySettings = () => {
|
|||
const [replyNotificationType, setReplyNotificationType] = useState('any'); //todo: initialize with value from db/api
|
||||
const theme = useTheme();
|
||||
const styles = getStyleSheet(theme);
|
||||
const intl = useIntl();
|
||||
|
||||
const setReplyNotifications = (notifType: string) => {
|
||||
setReplyNotificationType(notifType);
|
||||
|
|
@ -52,48 +50,35 @@ const ReplySettings = () => {
|
|||
return (
|
||||
<Block
|
||||
headerText={replyHeaderText}
|
||||
containerStyles={styles.area}
|
||||
headerStyles={styles.upperCase}
|
||||
>
|
||||
<BlockItem
|
||||
label={(
|
||||
<FormattedText
|
||||
id='notification_settings.threads_start_participate'
|
||||
defaultMessage='Threads that I start or participate in'
|
||||
style={styles.label}
|
||||
/>
|
||||
)}
|
||||
action={setReplyNotifications}
|
||||
actionType='select'
|
||||
actionValue='any'
|
||||
containerStyle={styles.container}
|
||||
label={intl.formatMessage({id: 'notification_settings.threads_start_participate', defaultMessage: 'Threads that I start or participate in'})}
|
||||
labelStyle={styles.label}
|
||||
selected={replyNotificationType === 'any'}
|
||||
/>
|
||||
<View style={styles.separator}/>
|
||||
<BlockItem
|
||||
label={(
|
||||
<FormattedText
|
||||
id='notification_settings.threads_start'
|
||||
defaultMessage='Threads that I start'
|
||||
style={styles.label}
|
||||
/>
|
||||
)}
|
||||
action={setReplyNotifications}
|
||||
actionType='select'
|
||||
actionValue='root'
|
||||
containerStyle={styles.container}
|
||||
label={intl.formatMessage({id: 'notification_settings.threads_start', defaultMessage: 'Threads that I start'})}
|
||||
labelStyle={styles.label}
|
||||
selected={replyNotificationType === 'root'}
|
||||
/>
|
||||
<View style={styles.separator}/>
|
||||
<BlockItem
|
||||
label={(
|
||||
<FormattedText
|
||||
id='notification_settings.threads_mentions'
|
||||
defaultMessage='Mentions in threads'
|
||||
style={styles.label}
|
||||
/>
|
||||
)}
|
||||
action={setReplyNotifications}
|
||||
actionType='select'
|
||||
actionValue='never'
|
||||
containerStyle={styles.container}
|
||||
label={intl.formatMessage({id: 'notification_settings.threads_mentions', defaultMessage: 'Mentions in threads'})}
|
||||
labelStyle={styles.label}
|
||||
selected={replyNotificationType === 'never'}
|
||||
/>
|
||||
</Block>
|
||||
|
|
|
|||
20
app/screens/settings/notification_push/index.tsx
Normal file
20
app/screens/settings/notification_push/index.tsx
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
|
||||
import withObservables from '@nozbe/with-observables';
|
||||
|
||||
import {observeConfigBooleanValue} from '@queries/servers/system';
|
||||
import {observeIsCRTEnabled} from '@queries/servers/thread';
|
||||
import {WithDatabaseArgs} from '@typings/database/database';
|
||||
|
||||
import NotificationPush from './notification_push';
|
||||
|
||||
const enhanced = withObservables([], ({database}: WithDatabaseArgs) => {
|
||||
return {
|
||||
sendPushNotifications: observeConfigBooleanValue(database, 'SendPushNotifications'),
|
||||
isCRTEnabled: observeIsCRTEnabled(database),
|
||||
};
|
||||
});
|
||||
|
||||
export default withDatabase(enhanced(NotificationPush));
|
||||
89
app/screens/settings/notification_push/notification_push.tsx
Normal file
89
app/screens/settings/notification_push/notification_push.tsx
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useState} from 'react';
|
||||
import {ScrollView} from 'react-native';
|
||||
import {Edge, SafeAreaView} from 'react-native-safe-area-context';
|
||||
|
||||
import {useTheme} from '@context/theme';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
|
||||
import MobileSendPush from './push_send';
|
||||
import MobilePushStatus from './push_status';
|
||||
import MobilePushThread from './push_thread';
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
return {
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
scrollView: {
|
||||
flex: 1,
|
||||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.06),
|
||||
},
|
||||
scrollViewContent: {
|
||||
paddingVertical: 30,
|
||||
},
|
||||
};
|
||||
});
|
||||
const edges: Edge[] = ['left', 'right'];
|
||||
|
||||
type NotificationMobileProps = {
|
||||
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 styles = getStyleSheet(theme);
|
||||
|
||||
const setMobilePushStatus = (status: PushStatus) => {
|
||||
setPushStatus(status);
|
||||
};
|
||||
|
||||
const setMobilePushPref = (status: PushStatus) => {
|
||||
setPushPref(status);
|
||||
};
|
||||
|
||||
const onMobilePushThreadChanged = (status: PushStatus) => {
|
||||
setPushThreadPref(status);
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView
|
||||
edges={edges}
|
||||
testID='notification_push.screen'
|
||||
style={styles.container}
|
||||
>
|
||||
<ScrollView
|
||||
style={styles.scrollView}
|
||||
contentContainerStyle={styles.scrollViewContent}
|
||||
alwaysBounceVertical={false}
|
||||
>
|
||||
<MobileSendPush
|
||||
sendPushNotifications={sendPushNotifications}
|
||||
pushStatus={pushPref}
|
||||
setMobilePushPref={setMobilePushPref}
|
||||
/>
|
||||
{isCRTEnabled && pushPref === 'mention' && (
|
||||
<MobilePushThread
|
||||
pushThread={pushThread}
|
||||
onMobilePushThreadChanged={onMobilePushThreadChanged}
|
||||
/>
|
||||
)}
|
||||
{sendPushNotifications && pushPref !== 'none' && (
|
||||
<MobilePushStatus
|
||||
pushStatus={pushStatus}
|
||||
setMobilePushStatus={setMobilePushStatus}
|
||||
/>
|
||||
)}
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotificationPush;
|
||||
102
app/screens/settings/notification_push/push_send.tsx
Normal file
102
app/screens/settings/notification_push/push_send.tsx
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {View} from 'react-native';
|
||||
|
||||
import Block from '@components/block';
|
||||
import BlockItem from '@components/block_item';
|
||||
import FormattedText from '@components/formatted_text';
|
||||
import {useTheme} from '@context/theme';
|
||||
import {t} from '@i18n';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
import {typography} from '@utils/typography';
|
||||
|
||||
const headerText = {
|
||||
id: t('notification_settings.send_notification'),
|
||||
defaultMessage: 'Send notifications',
|
||||
};
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
return {
|
||||
upperCase: {
|
||||
textTransform: 'uppercase',
|
||||
},
|
||||
separator: {
|
||||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.1),
|
||||
flex: 1,
|
||||
height: 1,
|
||||
},
|
||||
label: {
|
||||
color: theme.centerChannelColor,
|
||||
...typography('Body', 100, 'Regular'),
|
||||
},
|
||||
disabled: {
|
||||
color: theme.centerChannelColor,
|
||||
fontSize: 15,
|
||||
paddingHorizontal: 15,
|
||||
paddingVertical: 10,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
type MobileSendPushProps = {
|
||||
sendPushNotifications: boolean;
|
||||
pushStatus: PushStatus;
|
||||
setMobilePushPref: (status: PushStatus) => void;
|
||||
}
|
||||
const MobileSendPush = ({sendPushNotifications, pushStatus, setMobilePushPref}: MobileSendPushProps) => {
|
||||
const theme = useTheme();
|
||||
const styles = getStyleSheet(theme);
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<Block
|
||||
headerText={headerText}
|
||||
headerStyles={styles.upperCase}
|
||||
>
|
||||
{sendPushNotifications &&
|
||||
<>
|
||||
<BlockItem
|
||||
action={setMobilePushPref}
|
||||
actionType='select'
|
||||
actionValue='all'
|
||||
label={intl.formatMessage({id: 'notification_settings.pushNotification.allActivity', defaultMessage: 'For all activity'})}
|
||||
labelStyle={styles.label}
|
||||
selected={pushStatus === 'all'}
|
||||
testID='notification_settings.pushNotification.allActivity'
|
||||
/>
|
||||
<View style={styles.separator}/>
|
||||
<BlockItem
|
||||
action={setMobilePushPref}
|
||||
actionType='select'
|
||||
actionValue='mention'
|
||||
label={intl.formatMessage({id: 'notification_settings.pushNotification.onlyMentions', defaultMessage: 'Only for mentions and direct messages'})}
|
||||
labelStyle={styles.label}
|
||||
selected={pushStatus === 'mention'}
|
||||
testID='notification_settings.pushNotification.onlyMentions'
|
||||
/>
|
||||
<View style={styles.separator}/>
|
||||
<BlockItem
|
||||
action={setMobilePushPref}
|
||||
actionType='select'
|
||||
actionValue='none'
|
||||
label={intl.formatMessage({id: 'notification_settings.pushNotification.never', defaultMessage: 'Never'})}
|
||||
labelStyle={styles.label}
|
||||
selected={pushStatus === 'none'}
|
||||
testID='notification_settings.pushNotification.never'
|
||||
/>
|
||||
</>
|
||||
}
|
||||
{!sendPushNotifications &&
|
||||
<FormattedText
|
||||
defaultMessage='Push notifications for mobile devices have been disabled by your System Administrator.'
|
||||
id='notification_settings.pushNotification.disabled_long'
|
||||
style={styles.disabled}
|
||||
/>
|
||||
}
|
||||
</Block>
|
||||
);
|
||||
};
|
||||
|
||||
export default MobileSendPush;
|
||||
82
app/screens/settings/notification_push/push_status.tsx
Normal file
82
app/screens/settings/notification_push/push_status.tsx
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {View} from 'react-native';
|
||||
|
||||
import Block from '@components/block';
|
||||
import BlockItem from '@components/block_item';
|
||||
import {useTheme} from '@context/theme';
|
||||
import {t} from '@i18n';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
import {typography} from '@utils/typography';
|
||||
|
||||
const headerText = {
|
||||
id: t('notification_settings.mobile.push_status'),
|
||||
defaultMessage: 'Trigger push notifications when',
|
||||
};
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
return {
|
||||
upperCase: {
|
||||
textTransform: 'uppercase',
|
||||
},
|
||||
separator: {
|
||||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.1),
|
||||
flex: 1,
|
||||
height: 1,
|
||||
},
|
||||
label: {
|
||||
color: theme.centerChannelColor,
|
||||
...typography('Body', 100, 'Regular'),
|
||||
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
type MobilePushStatusProps = {
|
||||
pushStatus: PushStatus;
|
||||
setMobilePushStatus: (status: PushStatus) => void;
|
||||
}
|
||||
const MobilePushStatus = ({pushStatus, setMobilePushStatus}: MobilePushStatusProps) => {
|
||||
const theme = useTheme();
|
||||
const styles = getStyleSheet(theme);
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<Block
|
||||
headerText={headerText}
|
||||
headerStyles={styles.upperCase}
|
||||
>
|
||||
<BlockItem
|
||||
label={intl.formatMessage({id: 'notification_settings.mobile.online', defaultMessage: 'Online, away or offline'})}
|
||||
labelStyle={styles.label}
|
||||
action={setMobilePushStatus}
|
||||
actionType='select'
|
||||
actionValue='online'
|
||||
selected={pushStatus === 'online'}
|
||||
/>
|
||||
<View style={styles.separator}/>
|
||||
<BlockItem
|
||||
label={intl.formatMessage({id: 'notification_settings.mobile.away', defaultMessage: 'Away or offline'})}
|
||||
labelStyle={styles.label}
|
||||
action={setMobilePushStatus}
|
||||
actionType='select'
|
||||
actionValue='away'
|
||||
selected={pushStatus === 'away'}
|
||||
/>
|
||||
<View style={styles.separator}/>
|
||||
<BlockItem
|
||||
label={intl.formatMessage({id: 'notification_settings.mobile.offline', defaultMessage: 'Offline'})}
|
||||
labelStyle={styles.label}
|
||||
action={setMobilePushStatus}
|
||||
actionType='select'
|
||||
actionValue='offline'
|
||||
selected={pushStatus === 'offline'}
|
||||
/>
|
||||
</Block>
|
||||
);
|
||||
};
|
||||
|
||||
export default MobilePushStatus;
|
||||
78
app/screens/settings/notification_push/push_thread.tsx
Normal file
78
app/screens/settings/notification_push/push_thread.tsx
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {View} from 'react-native';
|
||||
|
||||
import Block from '@components/block';
|
||||
import BlockItem from '@components/block_item';
|
||||
import FormattedText from '@components/formatted_text';
|
||||
import {useTheme} from '@context/theme';
|
||||
import {t} from '@i18n';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
import {typography} from '@utils/typography';
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
return {
|
||||
upperCase: {
|
||||
textTransform: 'uppercase',
|
||||
},
|
||||
separator: {
|
||||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.1),
|
||||
flex: 1,
|
||||
height: 1,
|
||||
marginLeft: 15,
|
||||
},
|
||||
area: {
|
||||
paddingHorizontal: 16,
|
||||
},
|
||||
label: {
|
||||
color: theme.centerChannelColor,
|
||||
...typography('Body', 100, 'Regular'),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const headerText = {
|
||||
id: t('notification_settings.push_threads'),
|
||||
defaultMessage: 'Thread reply notifications',
|
||||
};
|
||||
const footerText = {
|
||||
id: t('notification_settings.push_threads.info'),
|
||||
defaultMessage: 'When enabled, any reply to a thread you\'re following will send a mobile push notification',
|
||||
};
|
||||
|
||||
type MobilePushThreadProps = {
|
||||
onMobilePushThreadChanged: (status: string) => void;
|
||||
pushThread: PushStatus;
|
||||
}
|
||||
|
||||
const MobilePushThread = ({pushThread, onMobilePushThreadChanged}: MobilePushThreadProps) => {
|
||||
const theme = useTheme();
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
return (
|
||||
<Block
|
||||
headerText={headerText}
|
||||
footerText={footerText}
|
||||
headerStyles={styles.upperCase}
|
||||
containerStyles={styles.area}
|
||||
>
|
||||
<BlockItem
|
||||
label={(
|
||||
<FormattedText
|
||||
id='notification_settings.push_threads.description'
|
||||
defaultMessage={'Notify me about all replies to threads I\'m following'}
|
||||
style={styles.label}
|
||||
/>
|
||||
)}
|
||||
action={onMobilePushThreadChanged}
|
||||
actionType='toggle'
|
||||
selected={pushThread === 'all'}
|
||||
/>
|
||||
<View style={styles.separator}/>
|
||||
</Block>
|
||||
);
|
||||
};
|
||||
|
||||
export default MobilePushThread;
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {Alert, Platform, ScrollView, View} from 'react-native';
|
||||
import {Platform, ScrollView, View} from 'react-native';
|
||||
import {Edge, SafeAreaView} from 'react-native-safe-area-context';
|
||||
|
||||
import {Screens} from '@constants';
|
||||
|
|
@ -53,12 +53,6 @@ const Notifications = ({isCRTEnabled, enableAutoResponder}: NotificationsProps)
|
|||
mentionsI18nDefault = 'Mentions';
|
||||
}
|
||||
|
||||
const onPressHandler = () => {
|
||||
return Alert.alert(
|
||||
'The functionality you are trying to use has not yet been implemented.',
|
||||
);
|
||||
};
|
||||
|
||||
const goToNotificationSettingsMentions = () => {
|
||||
const screen = Screens.SETTINGS_NOTIFICATION_MENTION;
|
||||
|
||||
|
|
@ -69,6 +63,25 @@ const Notifications = ({isCRTEnabled, enableAutoResponder}: NotificationsProps)
|
|||
goToScreen(screen, title);
|
||||
};
|
||||
|
||||
const goToNotificationSettingsPush = () => {
|
||||
const screen = Screens.SETTINGS_NOTIFICATION_PUSH;
|
||||
const title = intl.formatMessage({
|
||||
id: 'notification_settings.push_notification',
|
||||
defaultMessage: 'Push Notifications',
|
||||
});
|
||||
|
||||
goToScreen(screen, title);
|
||||
};
|
||||
|
||||
const goToNotificationAutoResponder = () => {
|
||||
const screen = Screens.SETTINGS_NOTIFICATION_AUTO_RESPONDER;
|
||||
const title = intl.formatMessage({
|
||||
id: 'notification_settings.auto_responder',
|
||||
defaultMessage: 'Automatic Replies',
|
||||
});
|
||||
goToScreen(screen, title);
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView
|
||||
edges={edges}
|
||||
|
|
@ -88,11 +101,11 @@ const Notifications = ({isCRTEnabled, enableAutoResponder}: NotificationsProps)
|
|||
/>
|
||||
<SettingOption
|
||||
optionName='push_notification'
|
||||
onPress={onPressHandler}
|
||||
onPress={goToNotificationSettingsPush}
|
||||
/>
|
||||
{enableAutoResponder && (
|
||||
<SettingOption
|
||||
onPress={onPressHandler}
|
||||
onPress={goToNotificationAutoResponder}
|
||||
optionName='automatic_dm_replies'
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -285,3 +285,22 @@ export function filterProfilesMatchingTerm(users: UserProfile[], term: string):
|
|||
some((suggestion) => suggestion.startsWith(trimmedTerm));
|
||||
});
|
||||
}
|
||||
|
||||
export function getNotificationProps(user: UserModel) {
|
||||
if (user && user.notifyProps) {
|
||||
return user.notifyProps;
|
||||
}
|
||||
|
||||
const props: Partial<UserNotifyProps> = {
|
||||
channel: 'true',
|
||||
comments: 'any',
|
||||
desktop: 'all',
|
||||
desktop_sound: 'true',
|
||||
first_name: (!user || !user.firstName) ? 'false' : 'true',
|
||||
mention_keys: user ? `${user.username},@${user.username}` : '',
|
||||
push: 'mention',
|
||||
push_status: 'online',
|
||||
};
|
||||
|
||||
return props;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -441,8 +441,6 @@
|
|||
"mobile.notice_mobile_link": "mobile apps",
|
||||
"mobile.notice_platform_link": "server",
|
||||
"mobile.notice_text": "Mattermost is made possible by the open source software used in our {platform} and {mobile}.",
|
||||
"mobile.notification_settings.mobile": "Push Notifications",
|
||||
"mobile.notification_settings.ooo_auto_responder": "Automatic Direct Message Replies",
|
||||
"mobile.oauth.failed_to_login": "Your login attempt failed. Please try again.",
|
||||
"mobile.oauth.failed_to_open_link": "The link failed to open. Please try again.",
|
||||
"mobile.oauth.failed_to_open_link_no_browser": "The link failed to open. Please verify that a browser is installed on the device.",
|
||||
|
|
@ -553,6 +551,11 @@
|
|||
"more_messages.text": "{count} new {count, plural, one {message} other {messages}}",
|
||||
"msg_typing.areTyping": "{users} and {last} are typing...",
|
||||
"msg_typing.isTyping": "{user} is typing...",
|
||||
"notification_settings.auto_responder": "Automatic Replies",
|
||||
"notification_settings.auto_responder.default_message": "Hello, I am out of office and unable to respond to messages.",
|
||||
"notification_settings.auto_responder.enabled": "Enabled",
|
||||
"notification_settings.auto_responder.footer_message": "Set a custom message that will be automatically sent in response to Direct Messages. Mentions in Public and Private Channels will not trigger the automated reply. Enabling Automatic Replies sets your status to Out of Office and disables email and push notifications.",
|
||||
"notification_settings.auto_responder.message_placeholder": "Message",
|
||||
"notification_settings.mention.reply": "Send reply notifications for",
|
||||
"notification_settings.mentions": "Mentions",
|
||||
"notification_settings.mentions_replies": "Mentions and Replies",
|
||||
|
|
@ -562,6 +565,21 @@
|
|||
"notification_settings.mentions.sensitiveName": "Your case sensitive first name",
|
||||
"notification_settings.mentions.sensitiveUsername": "Your non-case sensitive username",
|
||||
"notification_settings.mentions.wordsTrigger": "Words that trigger mentions",
|
||||
"notification_settings.mobile": "Push Notifications",
|
||||
"notification_settings.mobile.away": "Away or offline",
|
||||
"notification_settings.mobile.offline": "Offline",
|
||||
"notification_settings.mobile.online": "Online, away or offline",
|
||||
"notification_settings.mobile.push_status": "Trigger push notifications when",
|
||||
"notification_settings.ooo_auto_responder": "Automatic Direct Message Replies",
|
||||
"notification_settings.push_notification": "Push Notifications",
|
||||
"notification_settings.push_threads": "Thread reply notifications",
|
||||
"notification_settings.push_threads.description": "Notify me about all replies to threads I'm following",
|
||||
"notification_settings.push_threads.info": "When enabled, any reply to a thread you're following will send a mobile push notification",
|
||||
"notification_settings.pushNotification.allActivity": "For all activity",
|
||||
"notification_settings.pushNotification.disabled_long": "Push notifications for mobile devices have been disabled by your System Administrator.",
|
||||
"notification_settings.pushNotification.never": "Never",
|
||||
"notification_settings.pushNotification.onlyMentions": "Only for mentions and direct messages",
|
||||
"notification_settings.send_notification": "Send notifications",
|
||||
"notification_settings.threads_mentions": "Mentions in threads",
|
||||
"notification_settings.threads_start": "Threads that I start",
|
||||
"notification_settings.threads_start_participate": "Threads that I start or participate in",
|
||||
|
|
|
|||
8
types/api/users.d.ts
vendored
8
types/api/users.d.ts
vendored
|
|
@ -4,17 +4,17 @@
|
|||
type UserNotifyProps = {
|
||||
auto_responder_active?: 'true' | 'false';
|
||||
auto_responder_message?: string;
|
||||
channel: 'true' | 'false';
|
||||
comments: 'never' | 'root' | 'any';
|
||||
desktop: 'default' | 'all' | 'mention' | 'none';
|
||||
desktop_notification_sound?: string;
|
||||
desktop_sound: 'true' | 'false';
|
||||
email: 'true' | 'false';
|
||||
first_name: 'true' | 'false';
|
||||
mark_unread: 'all' | 'mention';
|
||||
mention_keys: string;
|
||||
push: 'default' | 'all' | 'mention' | 'none';
|
||||
push_status: 'ooo' | 'offline' | 'away' | 'dnd' | 'online';
|
||||
comments: 'never' | 'root' | 'any';
|
||||
first_name: 'true' | 'false';
|
||||
channel: 'true' | 'false';
|
||||
mention_keys: string;
|
||||
user_id?: string;
|
||||
};
|
||||
|
||||
|
|
|
|||
4
types/screens/settings.d.ts
vendored
Normal file
4
types/screens/settings.d.ts
vendored
Normal file
|
|
@ -0,0 +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';
|
||||
Loading…
Reference in a new issue