MM-39711 - Gekidou Settings - Mentions functionality [3] (#6368)

This commit is contained in:
Avinash Lingaloo
2022-06-13 17:47:59 +04:00
committed by GitHub
parent f47b39fbe7
commit c5dc41dae3
7 changed files with 164 additions and 98 deletions

View File

@@ -92,44 +92,44 @@ export type FloatingTextInputRef = {
type FloatingTextInputProps = TextInputProps & {
containerStyle?: ViewStyle;
textInputStyle?: TextStyle;
labelTextStyle?: TextStyle;
editable?: boolean;
error?: string;
errorIcon?: string;
isKeyboardInput?: boolean;
label: string;
labelTextStyle?: TextStyle;
multiline?: boolean;
onBlur?: (event: NativeSyntheticEvent<TargetedEvent>) => void;
onFocus?: (e: NativeSyntheticEvent<TargetedEvent>) => void;
onPress?: (e: GestureResponderEvent) => void;
onLayout?: (e: LayoutChangeEvent) => void;
onPress?: (e: GestureResponderEvent) => void;
placeholder?: string;
showErrorIcon?: boolean;
testID?: string;
textInputStyle?: TextStyle;
theme: Theme;
value: string;
}
const FloatingTextInput = forwardRef<FloatingTextInputRef, FloatingTextInputProps>(({
error,
containerStyle,
isKeyboardInput = true,
editable = true,
error,
errorIcon = 'alert-outline',
isKeyboardInput = true,
label = '',
onPress = undefined,
onFocus,
onBlur,
onLayout,
showErrorIcon = true,
placeholder,
labelTextStyle,
multiline,
onBlur,
onFocus,
onLayout,
onPress,
placeholder,
showErrorIcon = true,
testID,
textInputStyle,
theme,
value = '',
textInputStyle,
labelTextStyle,
testID,
...props
}: FloatingTextInputProps, ref) => {
const [focused, setIsFocused] = useState(false);

View File

@@ -49,10 +49,10 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
},
input: {
color: theme.centerChannelColor,
fontSize: 15,
height: 150,
paddingHorizontal: 15,
paddingVertical: 10,
...typography('Body', 200, 'Regular'),
},
footer: {
paddingHorizontal: 15,
@@ -65,7 +65,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
},
label: {
color: theme.centerChannelColor,
...typography('Body', 200, 'Regular'),
...typography('Body', 100, 'Regular'),
},
enabled: {
paddingHorizontal: 8,
@@ -172,7 +172,7 @@ const NotificationAutoResponder = ({currentUser, componentId}: NotificationAutoR
placeholder={intl.formatMessage(headerText)}
placeholderTextColor={changeOpacity(theme.centerChannelColor, 0.4)}
returnKeyType='done'
style={styles.input}
textInputStyle={styles.input}
textAlignVertical='top'
theme={theme}
underlineColorAndroid='transparent'

View File

@@ -1,46 +1,32 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useReducer} from 'react';
import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {useIntl} from 'react-intl';
import {Alert, View} from 'react-native';
import {View} from 'react-native';
import {updateMe} from '@actions/remote/user';
import Block from '@components/block';
import FloatingTextInput from '@components/floating_text_input_label';
import OptionItem from '@components/option_item';
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 {t} from '@i18n';
import {popTopScreen, setButtons} from '@screens/navigation';
import UserModel from '@typings/database/models/servers/user';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {changeOpacity, getKeyboardAppearanceFromTheme, makeStyleSheetFromTheme} from '@utils/theme';
import {typography} from '@utils/typography';
const UPDATE_MENTION_PREF = 'UPDATE_MENTION_PREF';
const INITIAL_STATE = {
firstName: false,
usernameMention: false,
channel: false,
};
type Action = {
type: string;
data: Partial<typeof INITIAL_STATE>;
}
const reducer = (state: typeof INITIAL_STATE, action: Action) => {
switch (action.type) {
case UPDATE_MENTION_PREF:
return {
...state,
...action.data,
};
default:
return state;
}
};
import {getNotificationProps} from '@utils/user';
const mentionHeaderText = {
id: t('notification_settings.mentions.wordsTrigger'),
defaultMessage: 'Words that trigger mentions',
};
const SAVE_MENTION_BUTTON_ID = 'SAVE_MENTION_BUTTON_ID';
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
separator: {
@@ -63,48 +49,113 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
container: {
paddingHorizontal: 8,
},
input: {
color: theme.centerChannelColor,
height: 150,
paddingHorizontal: 15,
...typography('Body', 100, 'Regular'),
},
containerStyle: {
marginTop: 30,
},
};
});
const getMentionProps = (currentUser: UserModel) => {
const notifyProps = getNotificationProps(currentUser);
const mKeys = (notifyProps.mention_keys || '').split(',');
const usernameMentionIndex = mKeys.indexOf(currentUser.username);
if (usernameMentionIndex > -1) {
mKeys.splice(usernameMentionIndex, 1);
}
return {
mentionKeys: mKeys.join(','),
usernameMention: usernameMentionIndex > -1,
notifyProps,
};
};
type MentionSectionProps = {
currentUser?: UserModel;
mentionKeys: string;
componentId: string;
currentUser: UserModel;
}
const MentionSettings = ({currentUser, mentionKeys}: MentionSectionProps) => {
const [{firstName, usernameMention, channel}, dispatch] = useReducer(reducer, INITIAL_STATE);
const MentionSettings = ({componentId, currentUser}: MentionSectionProps) => {
const serverUrl = useServerUrl();
const mentionProps = useMemo(() => getMentionProps(currentUser), [currentUser.notifyProps]);
const notifyProps = currentUser.notifyProps || mentionProps.notifyProps;
const [tglFirstName, setTglFirstName] = useState(notifyProps.first_name === 'true');
const [tglChannel, setTglChannel] = useState(notifyProps.channel === 'true');
const [tglUserName, setTglUserName] = useState(mentionProps.usernameMention);
const [mentionKeys, setMentionKeys] = useState(mentionProps.mentionKeys);
const theme = useTheme();
const styles = getStyleSheet(theme);
const intl = useIntl();
const toggleChannelMentions = () => {
dispatch({
type: UPDATE_MENTION_PREF,
data: {
channel: !channel,
},
});
};
const toggleUsernameMention = () => {
dispatch({
type: UPDATE_MENTION_PREF,
data: {
usernameMention: !usernameMention,
},
});
};
const toggleFirstNameMention = () => {
dispatch({
type: UPDATE_MENTION_PREF,
data: {
firstName: !firstName,
},
});
};
const goToNotificationSettingsMentionKeywords = () => {
return Alert.alert(
'The functionality you are trying to use has not yet been implemented.',
);
};
const saveButton = useMemo(() => {
return {
id: SAVE_MENTION_BUTTON_ID,
enabled: false,
showAsAction: 'always' as const,
testID: 'notification_settings.mentions.save.button',
color: theme.sidebarHeaderTextColor,
text: intl.formatMessage({id: 'settings.save', defaultMessage: 'Save'}),
};
}, [theme.sidebarHeaderTextColor]);
const close = () => popTopScreen(componentId);
const saveMention = useCallback(() => {
const notify_props: UserNotifyProps = {
...notifyProps,
first_name: `${tglFirstName}`,
channel: `${tglChannel}`,
mention_keys: mentionKeys};
updateMe(serverUrl, {notify_props});
close();
}, [serverUrl, notifyProps, tglFirstName, tglChannel, mentionKeys]);
const onToggleFirstName = useCallback(() => {
setTglFirstName((prev) => !prev);
}, []);
const onToggleUserName = useCallback(() => {
setTglUserName((prev) => !prev);
}, []);
const onToggleChannel = useCallback(() => {
setTglChannel((prev) => !prev);
}, []);
const onChangeText = useCallback((text: string) => {
setMentionKeys(text);
}, []);
useEffect(() => {
const fNameChanged = tglFirstName !== Boolean(notifyProps.first_name);
const channelChanged = tglChannel !== Boolean(notifyProps.channel);
const usnChanged = tglUserName !== mentionProps.usernameMention;
const kwsChanged = mentionProps.mentionKeys !== mentionKeys;
const enabled = fNameChanged || usnChanged || channelChanged || kwsChanged;
const buttons = {
rightButtons: [{
...saveButton,
enabled,
}],
};
setButtons(componentId, buttons);
}, [componentId, saveButton, tglFirstName, tglChannel, tglUserName, mentionKeys, notifyProps]);
useNavButtonPressed(SAVE_MENTION_BUTTON_ID, componentId, saveMention, [saveMention]);
useAndroidHardwareBackHandler(componentId, close);
return (
<Block
@@ -114,11 +165,11 @@ const MentionSettings = ({currentUser, mentionKeys}: MentionSectionProps) => {
{ Boolean(currentUser?.firstName) && (
<>
<OptionItem
action={toggleFirstNameMention}
action={onToggleFirstName}
containerStyle={styles.container}
description={intl.formatMessage({id: 'notification_settings.mentions.sensitiveName', defaultMessage: 'Your case sensitive first name'})}
label={currentUser!.firstName}
selected={firstName}
label={currentUser.firstName}
selected={tglFirstName}
type='toggle'
/>
<View style={styles.separator}/>
@@ -127,30 +178,42 @@ const MentionSettings = ({currentUser, mentionKeys}: MentionSectionProps) => {
}
{Boolean(currentUser?.username) && (
<OptionItem
action={toggleUsernameMention}
action={onToggleUserName}
containerStyle={styles.container}
description={intl.formatMessage({id: 'notification_settings.mentions.sensitiveUsername', defaultMessage: 'Your non-case sensitive username'})}
label={currentUser!.username}
selected={usernameMention}
label={currentUser.username}
selected={tglUserName}
type='toggle'
/>
)}
<View style={styles.separator}/>
<OptionItem
action={toggleChannelMentions}
action={onToggleChannel}
containerStyle={styles.container}
description={intl.formatMessage({id: 'notification_settings.mentions.channelWide', defaultMessage: 'Channel-wide mentions'})}
label='@channel, @all, @here'
selected={channel}
selected={tglChannel}
type='toggle'
/>
<View style={styles.separator}/>
<OptionItem
action={goToNotificationSettingsMentionKeywords}
containerStyle={styles.container}
description={mentionKeys || intl.formatMessage({id: 'notification_settings.mentions.keywordsDescription', defaultMessage: 'Other words that trigger a mention'})}
<FloatingTextInput
allowFontScaling={true}
autoCapitalize='none'
autoCorrect={false}
blurOnSubmit={true}
containerStyle={styles.containerStyle}
keyboardAppearance={getKeyboardAppearanceFromTheme(theme)}
label={intl.formatMessage({id: 'notification_settings.mentions.keywords', defaultMessage: 'Keywords'})}
type='arrow'
multiline={true}
onChangeText={onChangeText}
placeholder={intl.formatMessage({id: 'notification_settings.mentions..keywordsDescription', defaultMessage: 'Other words that trigger a mention'})}
placeholderTextColor={changeOpacity(theme.centerChannelColor, 0.4)}
returnKeyType='done'
textInputStyle={styles.input}
textAlignVertical='top'
theme={theme}
underlineColorAndroid='transparent'
value={mentionKeys}
/>
</Block>
);

View File

@@ -7,6 +7,7 @@ import {SafeAreaView} from 'react-native-safe-area-context';
import {useTheme} from '@context/theme';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {typography} from '@utils/typography';
import MentionSettings from './mention_settings';
import ReplySettings from './reply_settings';
@@ -21,8 +22,8 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
},
input: {
color: theme.centerChannelColor,
fontSize: 12,
height: 40,
...typography('Body', 75, 'Regular'),
},
scrollView: {
flex: 1,
@@ -35,11 +36,11 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
});
type NotificationMentionProps = {
isCRTEnabled?: boolean;
currentUser?: UserModel;
mentionKeys: string;
componentId: string;
currentUser: UserModel;
isCRTEnabled: boolean;
}
const NotificationMention = ({currentUser, mentionKeys, isCRTEnabled}: NotificationMentionProps) => {
const NotificationMention = ({componentId, currentUser, isCRTEnabled}: NotificationMentionProps) => {
const theme = useTheme();
const styles = getStyleSheet(theme);
@@ -55,8 +56,8 @@ const NotificationMention = ({currentUser, mentionKeys, isCRTEnabled}: Notificat
alwaysBounceVertical={false}
>
<MentionSettings
mentionKeys={mentionKeys}
currentUser={currentUser}
componentId={componentId}
/>
{!isCRTEnabled && (
<ReplySettings/>

View File

@@ -33,9 +33,9 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
},
disabled: {
color: theme.centerChannelColor,
fontSize: 15,
paddingHorizontal: 15,
paddingVertical: 10,
...typography('Body', 200, 'Regular'),
},
container: {
paddingHorizontal: 8,

View File

@@ -291,7 +291,9 @@ export function getNotificationProps(user: UserModel) {
return user.notifyProps;
}
const props: Partial<UserNotifyProps> = {
const props: UserNotifyProps = {
email: 'true',
mark_unread: 'all',
channel: 'true',
comments: 'any',
desktop: 'all',

View File

@@ -564,9 +564,9 @@
"notification_settings.mention.reply": "Send reply notifications for",
"notification_settings.mentions": "Mentions",
"notification_settings.mentions_replies": "Mentions and Replies",
"notification_settings.mentions..keywordsDescription": "Other words that trigger a mention",
"notification_settings.mentions.channelWide": "Channel-wide mentions",
"notification_settings.mentions.keywords": "Keywords",
"notification_settings.mentions.keywordsDescription": "Other words that trigger a mention",
"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",