Compare commits

...

30 Commits

Author SHA1 Message Date
Avinash Lingaloo
2a4b61b9c7 iteration 1 2023-02-01 12:39:56 +04:00
Avinash Lingaloo
2da4f45a31 Merge branch 'main' into mm-44652-channel-notification-setting 2023-01-30 14:48:45 +04:00
Avinash Lingaloo
da3f396f5b chore: i18n extract 2023-01-30 14:41:56 +04:00
Avinash Lingaloo
5d94ccf06b feat: update channel notification pref locally 2023-01-27 19:37:28 +04:00
Avinash Lingaloo
1b5b1b4591 feat: api called made to server 2023-01-27 19:18:09 +04:00
Avinash Lingaloo
b2cbe8b570 Update channel_notification_preference.tsx 2023-01-27 18:50:08 +04:00
Avinash Lingaloo
3176c2fed5 wip 2023-01-27 18:40:29 +04:00
Avinash Lingaloo
b27c72e965 Update notification_preference.tsx 2023-01-27 17:38:20 +04:00
Avinash Lingaloo
7b1a4d6275 Merge branch 'main' into mm-44652-channel-notification-setting 2023-01-27 16:58:55 +04:00
Avinash Lingaloo
701c010bdf feat: saving to server 2023-01-27 16:58:24 +04:00
Avinash Lingaloo
e5db26ed35 Update channel_notification_preference.tsx 2023-01-27 15:07:40 +04:00
Avinash Lingaloo
9d34726bc3 Update channel_notification_preference.tsx 2023-01-27 14:48:35 +04:00
Avinash Lingaloo
8581765196 feat: toggle channel unmute 2023-01-27 13:56:14 +04:00
Avinash Lingaloo
9f3e35a9bc feat: include muted flag
feat: include muted flag
2023-01-26 14:53:57 +04:00
Avinash Lingaloo
89387bf36b feat: channelInfo - rhs info now shows global default notif pref 2023-01-26 14:36:31 +04:00
Avinash Lingaloo
f1261535b7 feat: including global default into the selection 2023-01-26 14:23:24 +04:00
Avinash Lingaloo
dde547a919 feat: only show Thread Replies if on Mention 2023-01-25 15:02:24 +04:00
Avinash Lingaloo
b46ba9aa5d fix: onPress for resetToDefault 2023-01-25 14:55:33 +04:00
Avinash Lingaloo
d9b4d18d69 feat: wiring up channel_notification_preference
Update channel_notification_preference.tsx
2023-01-25 14:14:46 +04:00
Avinash Lingaloo
cae2b818f3 Merge branch 'main' into mm-44652-channel-notification-setting 2023-01-25 10:22:10 +04:00
Avinash Lingaloo
3a56209562 feat: positioning reset to default 2023-01-20 17:09:06 +04:00
Avinash Lingaloo
eef1e90bf2 feat: includes 'reset to default' 2023-01-20 16:54:42 +04:00
Avinash Lingaloo
aa814243b5 fix: remove duplicate text 2023-01-20 15:09:22 +04:00
Avinash Lingaloo
fc16af723a Update channel_notification_preference.tsx 2023-01-20 15:05:19 +04:00
Avinash Lingaloo
273f098bee Merge branch 'main' into mm-44652-channel-notification-setting 2023-01-20 11:54:22 +04:00
Avinash Lingaloo
385105b621 feat: channel notification preference screen - UI part 2 2023-01-11 12:16:21 +04:00
Avinash Lingaloo
bbcbca1675 feat: channel notification preference screen - UI part 1 2023-01-11 12:04:44 +04:00
Avinash Lingaloo
898942b60d fix: the line separator would appear multiple times depending on the selected option. 2023-01-10 13:19:17 +04:00
Avinash Lingaloo
461bbbbfad chore: registers Screens.CHANNEL_MENTION 2023-01-10 11:01:03 +04:00
Avinash Lingaloo
ae0689a05b chore: removes Screens.CHANNEL_MENTION from not_implemented list 2023-01-10 10:59:56 +04:00
14 changed files with 458 additions and 38 deletions

View File

@@ -1154,7 +1154,7 @@ export async function searchAllChannels(serverUrl: string, term: string, archive
}
}
export const updateChannelNotifyProps = async (serverUrl: string, channelId: string, props: Partial<ChannelNotifyProps>) => {
export const updateChannelNotifyProps = async (serverUrl: string, channelId: string, props: Partial<ChannelNotifyProps>, updateLocally = false) => {
let client: Client;
try {
client = NetworkManager.getClient(serverUrl);
@@ -1172,7 +1172,20 @@ export const updateChannelNotifyProps = async (serverUrl: string, channelId: str
const notifyProps = {...props, channel_id: channelId, user_id: userId} as ChannelNotifyProps & {channel_id: string; user_id: string};
await client.updateChannelNotifyProps(notifyProps);
if (updateLocally) {
const channelSettings = await queryMyChannelSettingsByIds(database, [channelId]).fetch();
const myChannelSetting = channelSettings?.[0];
if (myChannelSetting) {
const updatedProps: Partial<ChannelNotifyProps> = {...myChannelSetting.notifyProps, ...notifyProps};
await database.write(async () => {
await myChannelSetting.update((c) => {
c.notifyProps = updatedProps;
});
});
}
}
return {
notifyProps,
};
@@ -1191,6 +1204,10 @@ export const toggleMuteChannel = async (serverUrl: string, channelId: string, sh
try {
const channelSettings = await queryMyChannelSettingsByIds(database, [channelId]).fetch();
const myChannelSetting = channelSettings?.[0];
if (!myChannelSetting) {
return {error: 'Channel setting not found'};
}
const mark_unread = myChannelSetting.notifyProps?.mark_unread === 'mention' ? 'all' : 'mention';
const notifyProps: Partial<ChannelNotifyProps> = {...myChannelSetting.notifyProps, mark_unread};

View File

@@ -2,7 +2,7 @@
// See LICENSE.txt for license information.
import React from 'react';
import {StyleProp, TextStyle, View, ViewStyle} from 'react-native';
import {StyleProp, TextStyle, View, ViewProps, ViewStyle} from 'react-native';
import FormattedText from '@components/formatted_text';
import {useTheme} from '@context/theme';
@@ -36,7 +36,7 @@ export type SectionText = {
values?: MessageDescriptor;
}
export type BlockProps = {
export type BlockProps = ViewProps & {
children: React.ReactNode;
disableFooter?: boolean;
disableHeader?: boolean;
@@ -56,12 +56,16 @@ const Block = ({
headerStyles,
headerText,
footerStyles,
...props
}: BlockProps) => {
const theme = useTheme();
const styles = getStyleSheet(theme);
return (
<View style={styles.container}>
<View
style={styles.container}
{...props}
>
{(headerText && !disableHeader) &&
<FormattedText
defaultMessage={headerText.defaultMessage}

View File

@@ -10,7 +10,7 @@ import {switchMap, distinctUntilChanged} from 'rxjs/operators';
import {observeChannelsWithCalls} from '@calls/state';
import {General} from '@constants';
import {withServerUrl} from '@context/server';
import {observeChannelSettings, observeMyChannel, queryChannelMembers} from '@queries/servers/channel';
import {observeIsMutedSetting, observeMyChannel, queryChannelMembers} from '@queries/servers/channel';
import {queryDraft} from '@queries/servers/drafts';
import {observeCurrentChannelId, observeCurrentUserId} from '@queries/servers/system';
import {observeTeam} from '@queries/servers/team';
@@ -19,7 +19,6 @@ import ChannelItem from './channel_item';
import type {WithDatabaseArgs} from '@typings/database/database';
import type ChannelModel from '@typings/database/models/servers/channel';
import type MyChannelModel from '@typings/database/models/servers/my_channel';
type EnhanceProps = WithDatabaseArgs & {
channel: ChannelModel;
@@ -27,8 +26,6 @@ type EnhanceProps = WithDatabaseArgs & {
serverUrl?: string;
}
const observeIsMutedSetting = (mc: MyChannelModel) => observeChannelSettings(mc.database, mc.id).pipe(switchMap((s) => of$(s?.notifyProps?.mark_unread === General.MENTION)));
const enhance = withObservables(['channel', 'showTeamName'], ({
channel,
database,
@@ -53,7 +50,7 @@ const enhance = withObservables(['channel', 'showTeamName'], ({
if (!mc) {
return of$(false);
}
return observeIsMutedSetting(mc);
return observeIsMutedSetting(database, mc.id);
}),
);

View File

@@ -11,6 +11,7 @@ export const CHANNEL = 'Channel';
export const CHANNEL_ADD_PEOPLE = 'ChannelAddPeople';
export const CHANNEL_INFO = 'ChannelInfo';
export const CHANNEL_MENTION = 'ChannelMention';
export const CHANNEL_NOTIFICATION_PREFERENCE = 'ChannelNotificationPreference';
export const CODE = 'Code';
export const CREATE_DIRECT_MESSAGE = 'CreateDirectMessage';
export const CREATE_OR_EDIT_CHANNEL = 'CreateOrEditChannel';
@@ -79,6 +80,7 @@ export default {
CHANNEL_ADD_PEOPLE,
CHANNEL_INFO,
CHANNEL_MENTION,
CHANNEL_NOTIFICATION_PREFERENCE,
CODE,
CREATE_DIRECT_MESSAGE,
CREATE_OR_EDIT_CHANNEL,

View File

@@ -667,6 +667,10 @@ export const queryChannelsForAutocomplete = (database: Database, matchTerm: stri
return database.get<ChannelModel>(CHANNEL).query(...clauses);
};
export const observeIsMutedSetting = (database: Database, channelId: string) => observeChannelSettings(database, channelId).
pipe(
switchMap((s) => of$(s?.notifyProps?.mark_unread === General.MENTION)),
);
export const queryChannelMembers = (database: Database, channelId: string) => {
return database.get<ChannelMembershipModel>(CHANNEL_MEMBERSHIP).query(
Q.where('channel_id', channelId),

View File

@@ -9,6 +9,7 @@ import {isTypeDMorGM} from '@utils/channel';
import EditChannel from './edit_channel';
import IgnoreMentions from './ignore_mentions';
import NotificationPreference from './notification_preference';
import PinnedMessages from './pinned_messages';
// import Members from './members';
@@ -27,7 +28,7 @@ const Options = ({channelId, type, callsEnabled}: Props) => {
{type !== General.DM_CHANNEL &&
<IgnoreMentions channelId={channelId}/>
}
{/*<NotificationPreference channelId={channelId}/>*/}
<NotificationPreference channelId={channelId}/>
<PinnedMessages channelId={channelId}/>
{/* Add back in after MM-47653 is resolved. https://mattermost.atlassian.net/browse/MM-47653
{type !== General.DM_CHANNEL &&

View File

@@ -6,7 +6,7 @@ import withObservables from '@nozbe/with-observables';
import {of as of$} from 'rxjs';
import {switchMap} from 'rxjs/operators';
import {observeChannelSettings} from '@queries/servers/channel';
import {observeChannel, observeChannelSettings} from '@queries/servers/channel';
import NotificationPreference from './notification_preference';
@@ -17,12 +17,15 @@ type Props = WithDatabaseArgs & {
}
const enhanced = withObservables(['channelId'], ({channelId, database}: Props) => {
const channel = observeChannel(database, channelId);
const displayName = channel.pipe(switchMap((c) => of$(c?.displayName)));
const settings = observeChannelSettings(database, channelId);
const notifyLevel = settings.pipe(
switchMap((s) => of$(s?.notifyProps.push)),
);
return {
displayName,
notifyLevel,
};
});

View File

@@ -7,21 +7,40 @@ import {Platform} from 'react-native';
import OptionItem from '@components/option_item';
import {NotificationLevel, Screens} from '@constants';
import {useTheme} from '@context/theme';
import {t} from '@i18n';
import {goToScreen} from '@screens/navigation';
import {preventDoubleTap} from '@utils/tap';
import {changeOpacity} from '@utils/theme';
type Props = {
channelId: string;
displayName: string;
notifyLevel: NotificationLevel;
}
const NotificationPreference = ({channelId, notifyLevel}: Props) => {
const NotificationPreference = ({channelId, displayName, notifyLevel}: Props) => {
const {formatMessage} = useIntl();
const theme = useTheme();
const title = formatMessage({id: 'channel_info.mobile_notifications', defaultMessage: 'Mobile Notifications'});
const goToMentions = preventDoubleTap(() => {
goToScreen(Screens.CHANNEL_MENTION, title, {channelId});
const goToChannelNotificationPreference = preventDoubleTap(() => {
const options = {
topBar: {
title: {
text: title,
},
subtitle: {
color: changeOpacity(theme.sidebarHeaderTextColor, 0.72),
text: displayName,
},
backButton: {
popStackOnPress: false,
},
},
};
goToScreen(Screens.CHANNEL_NOTIFICATION_PREFERENCE, title, {channelId}, options);
});
const notificationLevelToText = () => {
@@ -54,7 +73,7 @@ const NotificationPreference = ({channelId, notifyLevel}: Props) => {
return (
<OptionItem
action={goToMentions}
action={goToChannelNotificationPreference}
label={title}
icon='cellphone'
type={Platform.select({ios: 'arrow', default: 'default'})}

View File

@@ -0,0 +1,305 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useCallback, useState} from 'react';
import {useIntl} from 'react-intl';
import {LayoutChangeEvent, Text, TouchableOpacity, View} from 'react-native';
import {toggleMuteChannel, updateChannelNotifyProps} from '@actions/remote/channel';
import CompassIcon from '@components/compass_icon';
import {NotificationLevel} from '@constants';
import {useServerUrl} from '@context/server';
import {useTheme} from '@context/theme';
import useAndroidHardwareBackHandler from '@hooks/android_back_handler';
import useBackNavigation from '@hooks/navigate_back';
import {t} from '@i18n';
import {popTopScreen} from '@screens/navigation';
import SettingBlock from '@screens/settings/setting_block';
import SettingContainer from '@screens/settings/setting_container';
import SettingOption from '@screens/settings/setting_option';
import SettingSeparator from '@screens/settings/settings_separator';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {typography} from '@utils/typography';
import type {AvailableScreens} from '@typings/screens/navigation';
type NotifPrefOptions = {
defaultMessage: string;
id: string;
testID: string;
value: string;
}
const BLOCK_TITLE_HEIGHT = 13;
const NOTIFY_OPTIONS_THREAD: Record<string, NotifPrefOptions> = {
THREAD_REPLIES: {
defaultMessage: 'Notify me about replies to threads Im following in this channel',
id: t('channel_notification_preference.notification.thread_replies'),
testID: 'channel_notification_preference.notification.thread_replies',
value: 'thread_replies',
},
};
const NOTIFY_OPTIONS: Record<string, NotifPrefOptions> = {
[NotificationLevel.ALL]: {
defaultMessage: 'All new messages',
id: t('channel_notification_preference.notification.all'),
testID: 'channel_notification_preference.notification.all',
value: NotificationLevel.ALL,
},
[NotificationLevel.MENTION]: {
defaultMessage: 'Mentions, direct messages only',
id: t('channel_notification_preference.notification.mention'),
testID: 'channel_notification_preference.notification.mention',
value: NotificationLevel.MENTION,
},
[NotificationLevel.NONE]: {
defaultMessage: 'Nothing',
id: t('channel_notification_preference.notification.none'),
testID: 'channel_notification_preference.notification.none',
value: NotificationLevel.NONE,
},
};
const NOTIFY_ABOUT = {id: t('channel_notification_preference.notify_about'), defaultMessage: 'Notify me about...'};
const THREAD_REPLIES = {id: t('channel_notification_preference.thread_replies'), defaultMessage: 'Thread replies'};
const RESET_DEFAULT = {id: t('channel_notification_preference.reset_default'), defaultMessage: 'Reset to default'};
const UNMUTE_CONTENT = {id: t('channel_notification_preference.unmute_content'), defaultMessage: 'Unmute channel'};
const MUTED_TITLE = {id: t('channel_notification_preference.muted_title'), defaultMessage: 'This channel is muted'};
const MUTED_CONTENT = {id: t('channel_notification_preference.muted_content'), defaultMessage: 'You can change the notification settings, but you will not receive notifications until the channel is unmuted.'};
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
return {
mutedBanner: {
width: '90%',
minHeight: 200,
backgroundColor: changeOpacity(theme.sidebarTextActiveBorder, 0.16),
alignSelf: 'center',
marginVertical: 20,
paddingHorizontal: 16,
borderRadius: 4,
},
mutedBannerTitle: {
flexDirection: 'row',
marginTop: 16,
},
mutedTextTitle: {
...typography('Heading', 200),
color: theme.centerChannelColor,
marginLeft: 10,
paddingTop: 5,
},
mutedText: {
...typography('Body', 200),
color: theme.centerChannelColor,
marginTop: 12,
marginBottom: 16,
},
unMuteButton: {
flexDirection: 'row',
backgroundColor: theme.buttonBg,
marginBottom: 20,
borderRadius: 4,
paddingVertical: 12,
width: '55%',
paddingHorizontal: 20,
},
unMuteText: {
...typography('Heading', 100),
color: theme.buttonColor,
marginLeft: 7,
},
resetIcon: {
color: theme.linkColor,
height: 18,
width: 18,
},
resetText: {
color: theme.linkColor,
marginLeft: 7,
...typography('Heading', 100),
},
resetContainer: {
position: 'absolute',
flexDirection: 'row',
right: 20,
zIndex: 1,
},
};
});
type NotifyPrefType = typeof NotificationLevel[keyof typeof NotificationLevel];
type ChannelNotifyPropsPushThread = ChannelNotifyProps['push_threads'];
type ChannelNotifyPropsPush = ChannelNotifyProps['push'];
type ChannelNotificationPreferenceProps = {
channelId: string;
componentId: AvailableScreens;
isCRTEnabled: boolean;
isChannelMuted: boolean;
globalDefault: ChannelNotifyPropsPush;
notifyThreadReplies: ChannelNotifyPropsPushThread;
channelNotifyLevel: ChannelNotifyPropsPush;
channelNotifyThreadReplies: ChannelNotifyPropsPushThread;
};
const ChannelNotificationPreference = ({
channelId,
componentId,
isCRTEnabled,
isChannelMuted,
globalDefault,
notifyThreadReplies,
channelNotifyLevel,
channelNotifyThreadReplies,
}: ChannelNotificationPreferenceProps) => {
const serverUrl = useServerUrl();
const intl = useIntl();
const theme = useTheme();
const styles = getStyleSheet(theme);
const [top, setTop] = useState(0);
// const globalDefault = notifyLevel === 'default' ? 'all' : notifyLevel;
const [notifyAbout, setNotifyAbout] = useState<UserNotifyPropsPush>(channelNotifyLevel === 'default' ? 'all' : channelNotifyLevel);
const [threadReplies, setThreadReplies] = useState<boolean>((channelNotifyThreadReplies || notifyThreadReplies) === 'all');
const [resetDefaultVisible, setResetDefaultVisible] = useState<boolean>(false);
const onSetNotifyAbout = useCallback((notifyValue: NotifyPrefType) => {
setNotifyAbout(notifyValue);
setResetDefaultVisible(notifyValue !== globalDefault);
}, [globalDefault]);
const onSetThreadReplies = useCallback(() => {
setThreadReplies((prev) => !prev);
}, []);
const close = () => popTopScreen(componentId);
const saveChannelNotificationPref = useCallback(() => {
if (resetDefaultVisible) {
const props: Partial<ChannelNotifyProps> = {
push: notifyAbout,
push_threads: threadReplies ? 'all' : 'mention',
};
updateChannelNotifyProps(serverUrl, channelId, props);
}
close();
}, [channelId, close, notifyAbout, resetDefaultVisible, serverUrl, threadReplies]);
const renderMutedBanner = useCallback(() => {
const onPress = async () => {
return toggleMuteChannel(serverUrl, channelId, false);
};
return (
<View style={styles.mutedBanner}>
<View style={styles.mutedBannerTitle}>
<CompassIcon
name='bell-off-outline'
size={24}
color={theme.linkColor}
/>
<Text style={styles.mutedTextTitle}>{intl.formatMessage(MUTED_TITLE)}</Text>
</View>
<Text style={styles.mutedText}>{intl.formatMessage(MUTED_CONTENT)}</Text>
<TouchableOpacity
style={styles.unMuteButton}
onPress={onPress}
>
<CompassIcon
name='bell-outline'
size={18}
color={theme.buttonColor}
/>
<Text style={styles.unMuteText}>{intl.formatMessage(UNMUTE_CONTENT)}</Text>
</TouchableOpacity>
</View>
);
}, [intl, styles, serverUrl, channelId]);
const renderResetDefault = useCallback(() => {
const onPress = () => {
setNotifyAbout(globalDefault);
setResetDefaultVisible(false);
};
return (
<TouchableOpacity
style={[styles.resetContainer, {top}]}
onPress={onPress}
>
<CompassIcon
name='refresh'
style={styles.resetIcon}
size={20}
/>
<Text style={styles.resetText}>
{intl.formatMessage(RESET_DEFAULT)}
</Text>
</TouchableOpacity>
);
}, [top, globalDefault]);
const renderThreadReplies = useCallback(() => {
const isHidden = [NotificationLevel.NONE, NotificationLevel.ALL].includes(notifyAbout);
if (isHidden) {
return null;
}
return (
<SettingBlock
headerText={THREAD_REPLIES}
>
<SettingOption
action={onSetThreadReplies}
label={intl.formatMessage({id: NOTIFY_OPTIONS_THREAD.THREAD_REPLIES.id, defaultMessage: NOTIFY_OPTIONS_THREAD.THREAD_REPLIES.defaultMessage})}
testID={NOTIFY_OPTIONS_THREAD.THREAD_REPLIES.testID}
type='toggle'
selected={threadReplies}
/>
<SettingSeparator/>
</SettingBlock>
);
}, [notifyAbout, threadReplies, intl, onSetThreadReplies]);
const onLayout = useCallback((e: LayoutChangeEvent) => {
const {y} = e.nativeEvent.layout;
setTop(y + BLOCK_TITLE_HEIGHT);
}, []);
useBackNavigation(saveChannelNotificationPref);
useAndroidHardwareBackHandler(componentId, saveChannelNotificationPref);
return (
<SettingContainer testID='push_notification_settings'>
{isChannelMuted && renderMutedBanner()}
{resetDefaultVisible && renderResetDefault()}
<SettingBlock
headerText={NOTIFY_ABOUT}
onLayout={onLayout}
>
{ Object.keys(NOTIFY_OPTIONS).map((k: string) => {
const {id, defaultMessage, value, testID} = NOTIFY_OPTIONS[k];
const defaultOption = k === globalDefault ? ' (default)' : '';
const label = `${intl.formatMessage({id, defaultMessage})}${defaultOption}`;
return (
<View key={`notif_pref_option${k}`}>
<SettingOption
action={onSetNotifyAbout}
label={label}
selected={notifyAbout === k}
testID={testID}
type='select'
value={value}
/>
<SettingSeparator/>
</View>
);
})
}
</SettingBlock>
{isCRTEnabled && renderThreadReplies()}
</SettingContainer>
);
};
export default ChannelNotificationPreference;

View File

@@ -0,0 +1,49 @@
// 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 {of as of$} from 'rxjs';
import {switchMap} from 'rxjs/operators';
import {observeChannelSettings, observeIsMutedSetting} from '@queries/servers/channel';
import {observeIsCRTEnabled} from '@queries/servers/thread';
import {observeCurrentUser} from '@queries/servers/user';
import {getNotificationProps} from '@utils/user';
import ChannelNotificationPreference from './channel_notification_preference';
import type {WithDatabaseArgs} from '@typings/database/database';
type CNFProps = WithDatabaseArgs & {
channelId: string;
}
const enhanced = withObservables([], ({channelId, database}: CNFProps) => {
const settings = observeChannelSettings(database, channelId);
const channelNotifyLevel = settings.pipe(
switchMap((s) => of$(s?.notifyProps.push)),
);
const channelNotifyThreadReplies = settings.pipe(
switchMap((s) => of$(s?.notifyProps.push_threads)),
);
const notifyProps = observeCurrentUser(database).pipe(
switchMap((u) => of$(u?.notifyProps ? getNotificationProps(u) : undefined)),
);
const globalDefault = notifyProps.pipe(
switchMap((n) => of$(n?.push)),
);
const notifyThreadReplies = notifyProps.pipe(
switchMap((n) => of$(n?.push_threads)),
);
return {
isCRTEnabled: observeIsCRTEnabled(database),
isChannelMuted: observeIsMutedSetting(database, channelId),
globalDefault,
notifyThreadReplies,
channelNotifyLevel,
channelNotifyThreadReplies,
};
});
export default withDatabase(enhanced(ChannelNotificationPreference));

View File

@@ -76,15 +76,24 @@ Navigation.setLazyComponentRegistrator((screenName) => {
case Screens.BROWSE_CHANNELS:
screen = withServerDatabase(require('@screens/browse_channels').default);
break;
case Screens.CALL:
screen = withServerDatabase(require('@calls/screens/call_screen').default);
break;
case Screens.CHANNEL:
screen = withServerDatabase(require('@screens/channel').default);
break;
case Screens.CHANNEL_INFO:
screen = withServerDatabase(require('@screens/channel_info').default);
break;
case Screens.CHANNEL_NOTIFICATION_PREFERENCE:
screen = withServerDatabase(require('@screens/channel_notification_preference').default);
break;
case Screens.CODE:
screen = withServerDatabase(require('@screens/code').default);
break;
case Screens.CREATE_DIRECT_MESSAGE:
screen = withServerDatabase(require('@screens/create_direct_message').default);
break;
case Screens.CREATE_OR_EDIT_CHANNEL:
screen = withServerDatabase(require('@screens/create_or_edit_channel').default);
break;
@@ -94,9 +103,6 @@ Navigation.setLazyComponentRegistrator((screenName) => {
case Screens.CUSTOM_STATUS_CLEAR_AFTER:
screen = withServerDatabase(require('@screens/custom_status_clear_after').default);
break;
case Screens.CREATE_DIRECT_MESSAGE:
screen = withServerDatabase(require('@screens/create_direct_message').default);
break;
case Screens.EDIT_POST:
screen = withServerDatabase(require('@screens/edit_post').default);
break;
@@ -121,12 +127,12 @@ Navigation.setLazyComponentRegistrator((screenName) => {
case Screens.GLOBAL_THREADS:
screen = withServerDatabase(require('@screens/global_threads').default);
break;
case Screens.INTERACTIVE_DIALOG:
screen = withServerDatabase(require('@screens/interactive_dialog').default);
break;
case Screens.INTEGRATION_SELECTOR:
screen = withServerDatabase(require('@screens/integration_selector').default);
break;
case Screens.INTERACTIVE_DIALOG:
screen = withServerDatabase(require('@screens/interactive_dialog').default);
break;
case Screens.INVITE:
screen = withServerDatabase(require('@screens/invite').default);
break;
@@ -152,9 +158,6 @@ Navigation.setLazyComponentRegistrator((screenName) => {
case Screens.MFA:
screen = withIntl(require('@screens/mfa').default);
break;
case Screens.SELECT_TEAM:
screen = withServerDatabase(require('@screens/select_team').default);
break;
case Screens.PERMALINK:
screen = withServerDatabase(require('@screens/permalink').default);
break;
@@ -170,6 +173,9 @@ Navigation.setLazyComponentRegistrator((screenName) => {
case Screens.REVIEW_APP:
screen = withServerDatabase(require('@screens/review_app').default);
break;
case Screens.SELECT_TEAM:
screen = withServerDatabase(require('@screens/select_team').default);
break;
case Screens.SETTINGS:
screen = withServerDatabase(require('@screens/settings').default);
break;
@@ -245,9 +251,6 @@ Navigation.setLazyComponentRegistrator((screenName) => {
case Screens.USER_PROFILE:
screen = withServerDatabase(require('@screens/user_profile').default);
break;
case Screens.CALL:
screen = withServerDatabase(require('@calls/screens/call_screen').default);
break;
}
if (screen) {

View File

@@ -74,19 +74,23 @@ const NotificationPush = ({componentId, currentUser, isCRTEnabled, sendPushNotif
sendPushNotifications={sendPushNotifications}
setMobilePushPref={setPushSend}
/>
{Platform.OS === 'android' && (<SettingSeparator isGroupSeparator={true}/>)}
{isCRTEnabled && pushSend === 'mention' && (
<MobilePushThread
pushThread={pushThread}
onMobilePushThreadChanged={onMobilePushThreadChanged}
/>
<>
{Platform.OS === 'android' && (<SettingSeparator isGroupSeparator={true}/>)}
<MobilePushThread
pushThread={pushThread}
onMobilePushThreadChanged={onMobilePushThreadChanged}
/>
</>
)}
{Platform.OS === 'android' && (<SettingSeparator isGroupSeparator={true}/>)}
{sendPushNotifications && pushSend !== 'none' && (
<MobilePushStatus
pushStatus={pushStatus}
setMobilePushStatus={setPushStatus}
/>
<>
{Platform.OS === 'android' && (<SettingSeparator isGroupSeparator={true}/>)}
<MobilePushStatus
pushStatus={pushStatus}
setMobilePushStatus={setPushStatus}
/>
</>
)}
</SettingContainer>
);

View File

@@ -168,6 +168,16 @@
"channel_modal.optional": "(optional)",
"channel_modal.purpose": "Purpose",
"channel_modal.purposeEx": "A channel to file bugs and improvements",
"channel_notification_preference.muted_content": "You can change the notification settings, but you will not receive notifications until the channel is unmuted.",
"channel_notification_preference.muted_title": "This channel is muted",
"channel_notification_preference.notification.all": "All new messages",
"channel_notification_preference.notification.mention": "Mentions, direct messages only",
"channel_notification_preference.notification.none": "Nothing",
"channel_notification_preference.notification.thread_replies": "Notify me about replies to threads Im following in this channel",
"channel_notification_preference.notify_about": "Notify me about...",
"channel_notification_preference.reset_default": "Reset to default",
"channel_notification_preference.thread_replies": "Thread replies",
"channel_notification_preference.unmute_content": "Unmute channel",
"combined_system_message.added_to_channel.many_expanded": "{users} and {lastUser} were **added to the channel** by {actor}.",
"combined_system_message.added_to_channel.one": "{firstUser} **added to the channel** by {actor}.",
"combined_system_message.added_to_channel.one_you": "You were **added to the channel** by {actor}.",
@@ -340,6 +350,7 @@
"invite.send_invite": "Send",
"invite.sendInvitationsTo": "Send invitations to…",
"invite.shareLink": "Share link",
"invite.summary.back": "Go back",
"invite.summary.done": "Done",
"invite.summary.email_invite": "An invitation email has been sent",
"invite.summary.error": "{invitationsCount, plural, one {Invitation} other {Invitations}} could not be sent successfully",

View File

@@ -13,9 +13,10 @@ type NotificationLevel = 'default' | 'all' | 'mention' | 'none';
type ChannelNotifyProps = {
desktop: NotificationLevel;
email: NotificationLevel;
ignore_channel_mentions: 'default' | 'off' | 'on';
mark_unread: 'all' | 'mention';
push: NotificationLevel;
ignore_channel_mentions: 'default' | 'off' | 'on';
push_threads: 'all' | 'mention';
};
type Channel = {
id: string;