From ba52acb26faf896851e42ec6a9bed85753bdd5c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Espino=20Garc=C3=ADa?= Date: Tue, 26 Sep 2023 18:35:40 +0200 Subject: [PATCH] Add GM as DM feature support (#7515) * Add GM as DM feature support * Minor fix * Address feedback * Fix case for non set channel notify prop * Fix strings --- app/actions/app/global.ts | 2 +- app/constants/notification_level.ts | 8 +-- app/constants/preferences.ts | 10 ++- app/constants/versions.ts | 4 ++ app/queries/servers/features.ts | 18 +++++ app/screens/channel/channel.tsx | 11 ++++ .../intro/direct_channel/direct_channel.tsx | 27 +++++++- .../intro/direct_channel/index.ts | 3 + app/screens/channel/index.tsx | 15 ++++- app/screens/channel/use_gm_as_dm_notice.tsx | 65 +++++++++++++++++++ .../options/notification_preference/index.ts | 11 +++- .../notification_preference.tsx | 28 ++++++-- .../channel_notification_preferences.tsx | 40 +++++++++--- .../channel_notification_preferences/index.ts | 27 +++++++- .../notify_about.tsx | 17 ++++- .../thread_replies.tsx | 3 +- .../notification_push/notification_push.tsx | 25 ++++--- .../settings/notification_push/push_send.tsx | 2 +- app/store/ephemeral_store.ts | 2 + app/utils/helpers.ts | 2 +- assets/base/i18n/en.json | 9 ++- 21 files changed, 282 insertions(+), 47 deletions(-) create mode 100644 app/constants/versions.ts create mode 100644 app/queries/servers/features.ts create mode 100644 app/screens/channel/use_gm_as_dm_notice.tsx diff --git a/app/actions/app/global.ts b/app/actions/app/global.ts index bb98cd5db..3de806fb8 100644 --- a/app/actions/app/global.ts +++ b/app/actions/app/global.ts @@ -1,10 +1,10 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {getActiveServerUrl} from '@app/init/credentials'; import {Tutorial} from '@constants'; import {GLOBAL_IDENTIFIERS} from '@constants/database'; import DatabaseManager from '@database/manager'; +import {getActiveServerUrl} from '@init/credentials'; import {logError} from '@utils/log'; export const storeGlobal = async (id: string, value: unknown, prepareRecordsOnly = false) => { diff --git a/app/constants/notification_level.ts b/app/constants/notification_level.ts index e5d771115..e989a0bac 100644 --- a/app/constants/notification_level.ts +++ b/app/constants/notification_level.ts @@ -1,10 +1,10 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -export const ALL = 'all'; -export const DEFAULT = 'default'; -export const MENTION = 'mention'; -export const NONE = 'none'; +export const ALL = 'all' as const; +export const DEFAULT = 'default' as const; +export const MENTION = 'mention' as const; +export const NONE = 'none' as const; export default { ALL, diff --git a/app/constants/preferences.ts b/app/constants/preferences.ts index e9fc7a231..1755530d0 100644 --- a/app/constants/preferences.ts +++ b/app/constants/preferences.ts @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -export const CATEGORIES_TO_KEEP: Record = { +export const CATEGORIES_TO_KEEP = { ADVANCED_SETTINGS: 'advanced_settings', CHANNEL_APPROXIMATE_VIEW_TIME: 'channel_approximate_view_time', CHANNEL_OPEN_TIME: 'channel_open_time', @@ -14,15 +14,21 @@ export const CATEGORIES_TO_KEEP: Record = { SIDEBAR_SETTINGS: 'sidebar_settings', TEAMS_ORDER: 'teams_order', THEME: 'theme', + SYSTEM_NOTICE: 'system_notice', }; -const CATEGORIES: Record = { +const CATEGORIES = { ...CATEGORIES_TO_KEEP, FAVORITE_CHANNEL: 'favorite_channel', }; +const NOTICES = { + GM_AS_DM: 'GMasDM', +}; + const Preferences = { CATEGORIES, + NOTICES, COLLAPSED_REPLY_THREADS: 'collapsed_reply_threads', COLLAPSED_REPLY_THREADS_OFF: 'off', COLLAPSED_REPLY_THREADS_ON: 'on', diff --git a/app/constants/versions.ts b/app/constants/versions.ts new file mode 100644 index 000000000..bb1a55ab8 --- /dev/null +++ b/app/constants/versions.ts @@ -0,0 +1,4 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +export const GM_AS_DM_VERSION = [9, 1, 0]; diff --git a/app/queries/servers/features.ts b/app/queries/servers/features.ts new file mode 100644 index 000000000..b1359a0db --- /dev/null +++ b/app/queries/servers/features.ts @@ -0,0 +1,18 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {of as of$} from 'rxjs'; +import {switchMap} from 'rxjs/operators'; + +import {GM_AS_DM_VERSION} from '@constants/versions'; +import {isMinimumServerVersion} from '@utils/helpers'; + +import {observeConfigValue} from './system'; + +import type {Database} from '@nozbe/watermelondb'; + +export const observeHasGMasDMFeature = (database: Database) => { + return observeConfigValue(database, 'Version').pipe( + switchMap((v) => of$(isMinimumServerVersion(v, ...GM_AS_DM_VERSION))), + ); +}; diff --git a/app/screens/channel/channel.tsx b/app/screens/channel/channel.tsx index e61495e80..3df1bdbc4 100644 --- a/app/screens/channel/channel.tsx +++ b/app/screens/channel/channel.tsx @@ -24,7 +24,9 @@ import EphemeralStore from '@store/ephemeral_store'; import ChannelPostList from './channel_post_list'; import ChannelHeader from './header'; +import useGMasDMNotice from './use_gm_as_dm_notice'; +import type PreferenceModel from '@typings/database/models/servers/preference'; import type {AvailableScreens} from '@typings/screens/navigation'; import type {KeyboardTrackingViewRef} from 'react-native-keyboard-tracking-view'; @@ -36,6 +38,10 @@ type ChannelProps = { isCallsEnabledInChannel: boolean; showIncomingCalls: boolean; isTabletView?: boolean; + dismissedGMasDMNotice: PreferenceModel[]; + currentUserId: string; + channelType: ChannelType; + hasGMasDMFeature: boolean; }; const edges: Edge[] = ['left', 'right']; @@ -55,7 +61,12 @@ const Channel = ({ isCallsEnabledInChannel, showIncomingCalls, isTabletView, + dismissedGMasDMNotice, + channelType, + currentUserId, + hasGMasDMFeature, }: ChannelProps) => { + useGMasDMNotice(currentUserId, channelType, dismissedGMasDMNotice, hasGMasDMFeature); const isTablet = useIsTablet(); const insets = useSafeAreaInsets(); const [shouldRenderPosts, setShouldRenderPosts] = useState(false); diff --git a/app/screens/channel/channel_post_list/intro/direct_channel/direct_channel.tsx b/app/screens/channel/channel_post_list/intro/direct_channel/direct_channel.tsx index aec9e5604..6c5dfe246 100644 --- a/app/screens/channel/channel_post_list/intro/direct_channel/direct_channel.tsx +++ b/app/screens/channel/channel_post_list/intro/direct_channel/direct_channel.tsx @@ -27,6 +27,7 @@ type Props = { isBot: boolean; members?: ChannelMembershipModel[]; theme: Theme; + hasGMasDMFeature: boolean; } const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ @@ -52,6 +53,9 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ textAlign: 'center', ...typography('Body', 200, 'Regular'), }, + boldText: { + ...typography('Body', 200, 'SemiBold'), + }, profilesContainer: { justifyContent: 'center', alignItems: 'center', @@ -67,7 +71,14 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ }, })); -const DirectChannel = ({channel, currentUserId, isBot, members, theme}: Props) => { +const DirectChannel = ({ + channel, + currentUserId, + isBot, + members, + theme, + hasGMasDMFeature, +}: Props) => { const serverUrl = useServerUrl(); const styles = getStyleSheet(theme); @@ -89,11 +100,23 @@ const DirectChannel = ({channel, currentUserId, isBot, members, theme}: Props) = /> ); } + if (!hasGMasDMFeature) { + return ( + + ); + } return ( all activity in this group message.'} id='intro.group_message' style={styles.message} + values={{ + b: (chunk: string) => {chunk}, + }} /> ); }, [channel.displayName, theme]); diff --git a/app/screens/channel/channel_post_list/intro/direct_channel/index.ts b/app/screens/channel/channel_post_list/intro/direct_channel/index.ts index 23a561cfb..e598cfb2e 100644 --- a/app/screens/channel/channel_post_list/intro/direct_channel/index.ts +++ b/app/screens/channel/channel_post_list/intro/direct_channel/index.ts @@ -8,6 +8,7 @@ import {switchMap} from 'rxjs/operators'; import {General} from '@constants'; import {observeChannelMembers} from '@queries/servers/channel'; +import {observeHasGMasDMFeature} from '@queries/servers/features'; import {observeCurrentUserId} from '@queries/servers/system'; import {observeUser} from '@queries/servers/user'; import {getUserIdFromChannelName} from '@utils/user'; @@ -23,6 +24,7 @@ const observeIsBot = (user: UserModel | undefined) => of$(Boolean(user?.isBot)); const enhanced = withObservables([], ({channel, database}: {channel: ChannelModel} & WithDatabaseArgs) => { const currentUserId = observeCurrentUserId(database); const members = observeChannelMembers(database, channel.id); + const hasGMasDMFeature = observeHasGMasDMFeature(database); let isBot = of$(false); if (channel.type === General.DM_CHANNEL) { @@ -40,6 +42,7 @@ const enhanced = withObservables([], ({channel, database}: {channel: ChannelMode currentUserId, isBot, members, + hasGMasDMFeature, }; }); diff --git a/app/screens/channel/index.tsx b/app/screens/channel/index.tsx index 116c1d73b..8c7c20419 100644 --- a/app/screens/channel/index.tsx +++ b/app/screens/channel/index.tsx @@ -12,8 +12,12 @@ import { observeCurrentCall, observeIncomingCalls, } from '@calls/state'; +import {Preferences} from '@constants'; import {withServerUrl} from '@context/server'; -import {observeCurrentChannelId} from '@queries/servers/system'; +import {observeCurrentChannel} from '@queries/servers/channel'; +import {observeHasGMasDMFeature} from '@queries/servers/features'; +import {queryPreferencesByCategoryAndName} from '@queries/servers/preference'; +import {observeCurrentChannelId, observeCurrentUserId} from '@queries/servers/system'; import Channel from './channel'; @@ -56,12 +60,21 @@ const enhanced = withObservables([], ({database, serverUrl}: EnhanceProps) => { distinctUntilChanged(), ); + const dismissedGMasDMNotice = queryPreferencesByCategoryAndName(database, Preferences.CATEGORIES.SYSTEM_NOTICE, Preferences.NOTICES.GM_AS_DM).observe(); + const channelType = observeCurrentChannel(database).pipe(switchMap((c) => of$(c?.type))); + const currentUserId = observeCurrentUserId(database); + const hasGMasDMFeature = observeHasGMasDMFeature(database); + return { channelId, showJoinCallBanner, isInACall, showIncomingCalls, isCallsEnabledInChannel: observeIsCallsEnabledInChannel(database, serverUrl, channelId), + dismissedGMasDMNotice, + channelType, + currentUserId, + hasGMasDMFeature, }; }); diff --git a/app/screens/channel/use_gm_as_dm_notice.tsx b/app/screens/channel/use_gm_as_dm_notice.tsx new file mode 100644 index 000000000..5b32ec861 --- /dev/null +++ b/app/screens/channel/use_gm_as_dm_notice.tsx @@ -0,0 +1,65 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {useEffect} from 'react'; +import {useIntl} from 'react-intl'; +import {Alert} from 'react-native'; + +import {savePreference} from '@actions/remote/preference'; +import {Preferences} from '@constants'; +import {useServerUrl} from '@context/server'; +import {getPreferenceAsBool} from '@helpers/api/preference'; +import EphemeralStore from '@store/ephemeral_store'; + +import type PreferenceModel from '@typings/database/models/servers/preference'; + +const useGMasDMNotice = (userId: string, channelType: ChannelType, dismissedGMasDMNotice: PreferenceModel[], hasGMasDMFeature: boolean) => { + const intl = useIntl(); + const serverUrl = useServerUrl(); + + useEffect(() => { + if (!hasGMasDMFeature) { + return; + } + + const preferenceValue = getPreferenceAsBool(dismissedGMasDMNotice, Preferences.CATEGORIES.SYSTEM_NOTICE, Preferences.NOTICES.GM_AS_DM); + if (preferenceValue) { + return; + } + + if (channelType !== 'G') { + return; + } + + if (EphemeralStore.noticeShown.has(Preferences.NOTICES.GM_AS_DM)) { + return; + } + + const onRemindMeLaterPress = () => { + EphemeralStore.noticeShown.add(Preferences.NOTICES.GM_AS_DM); + }; + + const onHideAndForget = () => { + EphemeralStore.noticeShown.add(Preferences.NOTICES.GM_AS_DM); + savePreference(serverUrl, [{category: Preferences.CATEGORIES.SYSTEM_NOTICE, name: Preferences.NOTICES.GM_AS_DM, value: 'true', user_id: userId}]); + }; + + // Show the GM as DM notice if needed + Alert.alert( + intl.formatMessage({id: 'system_notice.title.gm_as_dm', defaultMessage: 'Updates to Group Messages'}), + intl.formatMessage({id: 'system_noticy.body.gm_as_dm', defaultMessage: 'You will now be notified for all activity in your group messages along with a notification badge for every new message.\n\nYou can configure this in notification preferences for each group message.'}), + [ + { + text: intl.formatMessage({id: 'system_notice.remind_me', defaultMessage: 'Remind Me Later'}), + onPress: onRemindMeLaterPress, + }, + { + text: intl.formatMessage({id: 'system_notice.dont_show', defaultMessage: 'Don\'t Show Again'}), + onPress: onHideAndForget, + }, + ], + ); + }, []); +}; + +export default useGMasDMNotice; diff --git a/app/screens/channel_info/options/notification_preference/index.ts b/app/screens/channel_info/options/notification_preference/index.ts index 48bd52b3f..2e63f35bc 100644 --- a/app/screens/channel_info/options/notification_preference/index.ts +++ b/app/screens/channel_info/options/notification_preference/index.ts @@ -6,7 +6,9 @@ import withObservables from '@nozbe/with-observables'; import {of as of$} from 'rxjs'; import {switchMap} from 'rxjs/operators'; +import {NotificationLevel} from '@constants'; import {observeChannel, observeChannelSettings} from '@queries/servers/channel'; +import {observeHasGMasDMFeature} from '@queries/servers/features'; import {observeCurrentUser} from '@queries/servers/user'; import {getNotificationProps} from '@utils/user'; @@ -19,17 +21,22 @@ type Props = WithDatabaseArgs & { } const enhanced = withObservables(['channelId'], ({channelId, database}: Props) => { - const displayName = observeChannel(database, channelId).pipe(switchMap((c) => of$(c?.displayName))); + const channel = observeChannel(database, channelId); + const channelType = channel.pipe(switchMap((c) => of$(c?.type))); + const displayName = channel.pipe(switchMap((c) => of$(c?.displayName))); const settings = observeChannelSettings(database, channelId); const userNotifyLevel = observeCurrentUser(database).pipe(switchMap((u) => of$(getNotificationProps(u).push))); const notifyLevel = settings.pipe( - switchMap((s) => of$(s?.notifyProps.push)), + switchMap((s) => of$(s?.notifyProps.push || NotificationLevel.DEFAULT)), ); + const hasGMasDMFeature = observeHasGMasDMFeature(database); return { displayName, notifyLevel, userNotifyLevel, + channelType, + hasGMasDMFeature, }; }); diff --git a/app/screens/channel_info/options/notification_preference/notification_preference.tsx b/app/screens/channel_info/options/notification_preference/notification_preference.tsx index 83fdf7c42..253284d48 100644 --- a/app/screens/channel_info/options/notification_preference/notification_preference.tsx +++ b/app/screens/channel_info/options/notification_preference/notification_preference.tsx @@ -10,6 +10,7 @@ import {NotificationLevel, Screens} from '@constants'; import {useTheme} from '@context/theme'; import {t} from '@i18n'; import {goToScreen} from '@screens/navigation'; +import {isTypeDMorGM} from '@utils/channel'; import {preventDoubleTap} from '@utils/tap'; import {changeOpacity} from '@utils/theme'; @@ -20,6 +21,8 @@ type Props = { displayName: string; notifyLevel: NotificationLevel; userNotifyLevel: NotificationLevel; + channelType: ChannelType; + hasGMasDMFeature: boolean; } const notificationLevel = (notifyLevel: NotificationLevel) => { @@ -50,7 +53,14 @@ const notificationLevel = (notifyLevel: NotificationLevel) => { return {id, defaultMessage}; }; -const NotificationPreference = ({channelId, displayName, notifyLevel, userNotifyLevel}: Props) => { +const NotificationPreference = ({ + channelId, + displayName, + notifyLevel, + userNotifyLevel, + channelType, + hasGMasDMFeature, +}: Props) => { const {formatMessage} = useIntl(); const theme = useTheme(); const title = formatMessage({id: 'channel_info.mobile_notifications', defaultMessage: 'Mobile Notifications'}); @@ -74,13 +84,19 @@ const NotificationPreference = ({channelId, displayName, notifyLevel, userNotify }); const notificationLevelToText = () => { - if (notifyLevel === NotificationLevel.DEFAULT) { - const userLevel = notificationLevel(userNotifyLevel); - return formatMessage(userLevel); + let notifyLevelToUse = notifyLevel; + if (notifyLevelToUse === NotificationLevel.DEFAULT) { + notifyLevelToUse = userNotifyLevel; } - const channelLevel = notificationLevel(notifyLevel); - return formatMessage(channelLevel); + if (hasGMasDMFeature) { + if (notifyLevel === NotificationLevel.DEFAULT && notifyLevelToUse === NotificationLevel.MENTION && isTypeDMorGM(channelType)) { + notifyLevelToUse = NotificationLevel.ALL; + } + } + + const messageDescriptor = notificationLevel(notifyLevelToUse); + return formatMessage(messageDescriptor); }; return ( diff --git a/app/screens/channel_notification_preferences/channel_notification_preferences.tsx b/app/screens/channel_notification_preferences/channel_notification_preferences.tsx index 5b8c3611e..17636520b 100644 --- a/app/screens/channel_notification_preferences/channel_notification_preferences.tsx +++ b/app/screens/channel_notification_preferences/channel_notification_preferences.tsx @@ -7,10 +7,12 @@ import {useSharedValue} from 'react-native-reanimated'; import {updateChannelNotifyProps} from '@actions/remote/channel'; import SettingsContainer from '@components/settings/container'; +import {NotificationLevel} from '@constants'; import {useServerUrl} from '@context/server'; import useAndroidHardwareBackHandler from '@hooks/android_back_handler'; import useDidUpdate from '@hooks/did_update'; import useBackNavigation from '@hooks/navigate_back'; +import {isTypeDMorGM} from '@utils/channel'; import {popTopScreen} from '../navigation'; @@ -28,16 +30,29 @@ type Props = { defaultThreadReplies: 'all' | 'mention'; isCRTEnabled: boolean; isMuted: boolean; - notifyLevel?: NotificationLevel; + notifyLevel: NotificationLevel; notifyThreadReplies?: 'all' | 'mention'; + channelType: ChannelType; + hasGMasDMFeature: boolean; } -const ChannelNotificationPreferences = ({channelId, componentId, defaultLevel, defaultThreadReplies, isCRTEnabled, isMuted, notifyLevel, notifyThreadReplies}: Props) => { +const ChannelNotificationPreferences = ({ + channelId, + componentId, + defaultLevel, + defaultThreadReplies, + isCRTEnabled, + isMuted, + notifyLevel, + notifyThreadReplies, + channelType, + hasGMasDMFeature, +}: Props) => { const serverUrl = useServerUrl(); const defaultNotificationReplies = defaultThreadReplies === 'all'; - const diffNotificationLevel = notifyLevel !== 'default' && notifyLevel !== defaultLevel; + const diffNotificationLevel = notifyLevel !== NotificationLevel.DEFAULT && notifyLevel !== defaultLevel; const notifyTitleTop = useSharedValue((isMuted ? MUTED_BANNER_HEIGHT : 0) + BLOCK_TITLE_HEIGHT); - const [notifyAbout, setNotifyAbout] = useState((notifyLevel === undefined || notifyLevel === 'default') ? defaultLevel : notifyLevel); + const [notifyAbout, setNotifyAbout] = useState(notifyLevel === NotificationLevel.DEFAULT ? defaultLevel : notifyLevel); const [threadReplies, setThreadReplies] = useState((notifyThreadReplies || defaultThreadReplies) === 'all'); const [resetDefaultVisible, setResetDefaultVisible] = useState(diffNotificationLevel || defaultNotificationReplies !== threadReplies); @@ -64,8 +79,13 @@ const ChannelNotificationPreferences = ({channelId, componentId, defaultLevel, d const save = useCallback(() => { const pushThreads = threadReplies ? 'all' : 'mention'; - if (notifyLevel !== notifyAbout || (isCRTEnabled && pushThreads !== notifyThreadReplies)) { - const props: Partial = {push: notifyAbout}; + let notifyAboutToUse = notifyAbout; + if (notifyAbout === defaultLevel) { + notifyAboutToUse = NotificationLevel.DEFAULT; + } + + if (notifyLevel !== notifyAboutToUse || (isCRTEnabled && pushThreads !== notifyThreadReplies)) { + const props: Partial = {push: notifyAboutToUse}; if (isCRTEnabled) { props.push_threads = pushThreads; } @@ -73,11 +93,15 @@ const ChannelNotificationPreferences = ({channelId, componentId, defaultLevel, d updateChannelNotifyProps(serverUrl, channelId, props); } popTopScreen(componentId); - }, [channelId, componentId, isCRTEnabled, notifyAbout, notifyLevel, notifyThreadReplies, serverUrl, threadReplies]); + }, [defaultLevel, channelId, componentId, isCRTEnabled, notifyAbout, notifyLevel, notifyThreadReplies, serverUrl, threadReplies]); useBackNavigation(save); useAndroidHardwareBackHandler(componentId, save); + const showThreadReplies = isCRTEnabled && ( + !hasGMasDMFeature || + !isTypeDMorGM(channelType) + ); return ( {isMuted && } @@ -94,7 +118,7 @@ const ChannelNotificationPreferences = ({channelId, componentId, defaultLevel, d notifyTitleTop={notifyTitleTop} onPress={onNotificationLevel} /> - {isCRTEnabled && + {showThreadReplies && { const isCRTEnabled = observeIsCRTEnabled(database); const isMuted = observeIsMutedSetting(database, channelId); const notifyProps = observeCurrentUser(database).pipe(switchMap((u) => of$(getNotificationProps(u)))); + const channelType = observeChannel(database, channelId).pipe(switchMap((c) => of$(c?.type))); + const hasGMasDMFeature = observeHasGMasDMFeature(database); const notifyLevel = settings.pipe( - switchMap((s) => of$(s?.notifyProps.push)), + switchMap((s) => of$(s?.notifyProps.push || NotificationLevel.DEFAULT)), ); const notifyThreadReplies = settings.pipe( @@ -35,7 +40,21 @@ const enhanced = withObservables([], ({channelId, database}: EnhancedProps) => { const defaultLevel = notifyProps.pipe( switchMap((n) => of$(n?.push)), + combineLatestWith(hasGMasDMFeature, channelType), + switchMap(([v, hasFeature, cType]) => { + const shouldShowwithGMasDMBehavior = hasFeature && isTypeDMorGM(cType); + + let defaultLevelToUse = v; + if (shouldShowwithGMasDMBehavior) { + if (v === NotificationLevel.MENTION) { + defaultLevelToUse = NotificationLevel.ALL; + } + } + + return of$(defaultLevelToUse); + }), ); + const defaultThreadReplies = notifyProps.pipe( switchMap((n) => of$(n?.push_threads)), ); @@ -47,6 +66,8 @@ const enhanced = withObservables([], ({channelId, database}: EnhancedProps) => { notifyThreadReplies, defaultLevel, defaultThreadReplies, + channelType, + hasGMasDMFeature, }; }); diff --git a/app/screens/channel_notification_preferences/notify_about.tsx b/app/screens/channel_notification_preferences/notify_about.tsx index b7f52b77d..a53d85439 100644 --- a/app/screens/channel_notification_preferences/notify_about.tsx +++ b/app/screens/channel_notification_preferences/notify_about.tsx @@ -40,7 +40,7 @@ const NOTIFY_OPTIONS: Record = { value: NotificationLevel.ALL, }, [NotificationLevel.MENTION]: { - defaultMessage: 'Mentions, direct messages only', + defaultMessage: 'Mentions only', id: t('channel_notification_preferences.notification.mention'), testID: 'channel_notification_preferences.notification.mention', value: NotificationLevel.MENTION, @@ -53,7 +53,13 @@ const NOTIFY_OPTIONS: Record = { }, }; -const NotifyAbout = ({defaultLevel, isMuted, notifyLevel, notifyTitleTop, onPress}: Props) => { +const NotifyAbout = ({ + defaultLevel, + isMuted, + notifyLevel, + notifyTitleTop, + onPress, +}: Props) => { const {formatMessage} = useIntl(); const onLayout = useCallback((e: LayoutChangeEvent) => { const {y} = e.nativeEvent.layout; @@ -61,6 +67,11 @@ const NotifyAbout = ({defaultLevel, isMuted, notifyLevel, notifyTitleTop, onPres notifyTitleTop.value = y > 0 ? y + 10 : BLOCK_TITLE_HEIGHT; }, []); + let notifyLevelToUse = notifyLevel; + if (notifyLevel === NotificationLevel.DEFAULT) { + notifyLevelToUse = defaultLevel; + } + return ( = { const NotifyAbout = ({isSelected, notifyLevel, onPress}: Props) => { const {formatMessage} = useIntl(); - if ([NotificationLevel.NONE, NotificationLevel.ALL].includes(notifyLevel)) { + const hiddenStates: NotificationLevel[] = [NotificationLevel.NONE, NotificationLevel.ALL]; + if (hiddenStates.includes(notifyLevel)) { return null; } diff --git a/app/screens/settings/notification_push/notification_push.tsx b/app/screens/settings/notification_push/notification_push.tsx index beeae314d..b196a6096 100644 --- a/app/screens/settings/notification_push/notification_push.tsx +++ b/app/screens/settings/notification_push/notification_push.tsx @@ -73,19 +73,24 @@ const NotificationPush = ({componentId, currentUser, isCRTEnabled, sendPushNotif sendPushNotifications={sendPushNotifications} setMobilePushPref={setPushSend} /> - {Platform.OS === 'android' && ()} + {isCRTEnabled && pushSend === 'mention' && ( - + <> + {Platform.OS === 'android' && ()} + + )} - {Platform.OS === 'android' && ()} {sendPushNotifications && pushSend !== 'none' && ( - + <> + {Platform.OS === 'android' && ()} + + )} ); diff --git a/app/screens/settings/notification_push/push_send.tsx b/app/screens/settings/notification_push/push_send.tsx index 8131bc761..84db5310b 100644 --- a/app/screens/settings/notification_push/push_send.tsx +++ b/app/screens/settings/notification_push/push_send.tsx @@ -55,7 +55,7 @@ const MobileSendPush = ({sendPushNotifications, pushStatus, setMobilePushPref}: (); + private pushProxyVerification: {[serverUrl: string]: string | undefined} = {}; private canJoinOtherTeams: {[serverUrl: string]: BehaviorSubject} = {}; diff --git a/app/utils/helpers.ts b/app/utils/helpers.ts index cb1915c0c..4f996fffc 100644 --- a/app/utils/helpers.ts +++ b/app/utils/helpers.ts @@ -17,7 +17,7 @@ const ShareModule: NativeShareExtension|undefined = Platform.select({android: Na // versions, and a non-equal minor version will ignore dot version. // currentVersion is a string, e.g '4.6.0' // minMajorVersion, minMinorVersion, minDotVersion are integers -export const isMinimumServerVersion = (currentVersion: string, minMajorVersion = 0, minMinorVersion = 0, minDotVersion = 0): boolean => { +export const isMinimumServerVersion = (currentVersion = '', minMajorVersion = 0, minMinorVersion = 0, minDotVersion = 0): boolean => { if (!currentVersion || typeof currentVersion !== 'string') { return false; } diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json index 4b8a02ce2..ed13d1cdb 100644 --- a/assets/base/i18n/en.json +++ b/assets/base/i18n/en.json @@ -179,7 +179,7 @@ "channel_notification_preferences.muted_content": "You can change the notification settings, but you will not receive notifications until the channel is unmuted.", "channel_notification_preferences.muted_title": "This channel is muted", "channel_notification_preferences.notification.all": "All new messages", - "channel_notification_preferences.notification.mention": "Mentions, direct messages only", + "channel_notification_preferences.notification.mention": "Mentions only", "channel_notification_preferences.notification.none": "Nothing", "channel_notification_preferences.notification.thread_replies": "Notify me about replies to threads I’m following in this channel", "channel_notification_preferences.notify_about": "Notify me about...", @@ -341,6 +341,7 @@ "intro.created_by": "created by {creator} on {date}.", "intro.direct_message": "This is the start of your conversation with {teammate}. Messages and files shared here are not shown to anyone else.", "intro.group_message": "This is the start of your conversation with this group. Messages and files shared here are not shown to anyone else outside of the group.", + "intro.group_message.after_gm_as_dm": "This is the start of your conversation with this group. Messages and files shared here are not shown to anyone else outside of the group.", "intro.private_channel": "Private Channel", "intro.public_channel": "Public Channel", "intro.townsquare": "Welcome to {name}. Everyone automatically becomes a member of this channel when they join the team.", @@ -765,7 +766,7 @@ "notification_settings.push_threads.replies": "Thread replies", "notification_settings.pushNotification.all_new_messages": "All new messages", "notification_settings.pushNotification.disabled_long": "Push notifications for mobile devices have been disabled by your System Administrator.", - "notification_settings.pushNotification.mentions_only": "Mentions, direct messages only (default)", + "notification_settings.pushNotification.mentions_only": "Only for mentions, direct messages and group messages (default)", "notification_settings.pushNotification.nothing": "Nothing", "notification_settings.send_notification.about": "Notify me about...", "notification_settings.threads_mentions": "Mentions in threads", @@ -1016,6 +1017,10 @@ "suggestion.search.direct": "Direct Messages", "suggestion.search.private": "Private Channels", "suggestion.search.public": "Public Channels", + "system_notice.dont_show": "Don't Show Again", + "system_notice.remind_me": "Remind Me Later", + "system_notice.title.gm_as_dm": "Updates to Group Messages", + "system_noticy.body.gm_as_dm": "You will now be notified for all activity in your group messages along with a notification badge for every new message.\n\nYou can configure this in notification preferences for each group message.", "team_list.no_other_teams.description": "To join another team, ask a Team Admin for an invitation, or create your own team.", "team_list.no_other_teams.title": "No additional teams to join", "terms_of_service.acceptButton": "Accept",