Skip to content

Commit

Permalink
MM 45015 - auto follow threads (mattermost#7463)
Browse files Browse the repository at this point in the history
* auto follow select option added

* unused code removed

* auto follow threads condition fixed on CRT enabled

* error handles

---------

Co-authored-by: Mattermost Build <[email protected]>
  • Loading branch information
2 people authored and Рахман Рустамов committed Jan 12, 2024
1 parent 4282941 commit 551a01f
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 10 deletions.
4 changes: 4 additions & 0 deletions app/constants/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ export const MAX_CHANNEL_NAME_LENGTH = 64;
export const IGNORE_CHANNEL_MENTIONS_ON = 'on';
export const IGNORE_CHANNEL_MENTIONS_OFF = 'off';
export const IGNORE_CHANNEL_MENTIONS_DEFAULT = 'default';
export const CHANNEL_AUTO_FOLLOW_THREADS_TRUE = 'on';
export const CHANNEL_AUTO_FOLLOW_THREADS_FALSE = 'off';

export default {
IGNORE_CHANNEL_MENTIONS_ON,
IGNORE_CHANNEL_MENTIONS_OFF,
IGNORE_CHANNEL_MENTIONS_DEFAULT,
MAX_CHANNEL_NAME_LENGTH,
MIN_CHANNEL_NAME_LENGTH,
CHANNEL_AUTO_FOLLOW_THREADS_TRUE,
CHANNEL_AUTO_FOLLOW_THREADS_FALSE,
};
3 changes: 3 additions & 0 deletions app/screens/channel_info/channel_info.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type Props = {
canEnableDisableCalls: boolean;
isCallsEnabledInChannel: boolean;
canManageMembers: boolean;
isCRTEnabled: boolean;
canManageSettings: boolean;
}

Expand All @@ -51,6 +52,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
}));

const ChannelInfo = ({
isCRTEnabled,
channelId,
closeButtonId,
componentId,
Expand Down Expand Up @@ -105,6 +107,7 @@ const ChannelInfo = ({
type={type}
callsEnabled={callsAvailable}
canManageMembers={canManageMembers}
isCRTEnabled={isCRTEnabled}
canManageSettings={canManageSettings}
/>
<View style={styles.separator}/>
Expand Down
2 changes: 2 additions & 0 deletions app/screens/channel_info/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
observeCurrentTeamId,
observeCurrentUserId,
} from '@queries/servers/system';
import {observeIsCRTEnabled} from '@queries/servers/thread';
import {observeCurrentUser, observeUserIsChannelAdmin, observeUserIsTeamAdmin} from '@queries/servers/user';
import {isTypeDMorGM} from '@utils/channel';
import {isMinimumServerVersion} from '@utils/helpers';
Expand Down Expand Up @@ -117,6 +118,7 @@ const enhanced = withObservables([], ({serverUrl, database}: Props) => {
canEnableDisableCalls,
isCallsEnabledInChannel,
canManageMembers,
isCRTEnabled: observeIsCRTEnabled(database),
canManageSettings,
};
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import React, {useState} from 'react';
import {useIntl} from 'react-intl';

import {updateChannelNotifyProps} from '@actions/remote/channel';
import OptionItem from '@components/option_item';
import {
CHANNEL_AUTO_FOLLOW_THREADS_FALSE,
CHANNEL_AUTO_FOLLOW_THREADS_TRUE,
} from '@constants/channel';
import {useServerUrl} from '@context/server';
import {t} from '@i18n';
import {alertErrorWithFallback} from '@utils/draft';
import {preventDoubleTap} from '@utils/tap';

type Props = {
channelId: string;
followedStatus: boolean;
displayName: string;
};

const AutoFollowThreads = ({channelId, displayName, followedStatus}: Props) => {
const [autoFollow, setAutoFollow] = useState(followedStatus);
const serverUrl = useServerUrl();
const intl = useIntl();

const toggleFollow = preventDoubleTap(async () => {
const props: Partial<ChannelNotifyProps> = {
channel_auto_follow_threads: followedStatus ? CHANNEL_AUTO_FOLLOW_THREADS_FALSE : CHANNEL_AUTO_FOLLOW_THREADS_TRUE,
};
setAutoFollow((v) => !v);
const result = await updateChannelNotifyProps(serverUrl, channelId, props);
if (result?.error) {
alertErrorWithFallback(
intl,
result.error,
{
id: t('channel_info.channel_auto_follow_threads_failed'),
defaultMessage: 'An error occurred trying to auto follow all threads in channel {displayName}',
},
{displayName},
);
setAutoFollow((v) => !v);
}
});

return (
<OptionItem
action={toggleFollow}
label={intl.formatMessage({id: 'channel_info.channel_auto_follow_threads', defaultMessage: 'Follow all threads in this channel'})}
icon='message-plus-outline'
type='toggle'
selected={autoFollow}
testID={`channel_info.options.channel_auto_follow_threads.option.toggled.${autoFollow}`}
/>
);
};

export default AutoFollowThreads;
35 changes: 35 additions & 0 deletions app/screens/channel_info/options/auto_follow_threads/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// 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 {Channel} from '@constants';
import {observeChannel, observeChannelSettings} from '@queries/servers/channel';

import AutoFollowThreads from './auto_follow_threads';

import type {WithDatabaseArgs} from '@typings/database/database';

type Props = WithDatabaseArgs & {
channelId: string;
}

const enhanced = withObservables(['channelId'], ({channelId, database}: Props) => {
const channel = observeChannel(database, channelId);
const settings = observeChannelSettings(database, channelId);
const followedStatus = settings.pipe(
switchMap((s) => {
return of$(s?.notifyProps?.channel_auto_follow_threads === Channel.CHANNEL_AUTO_FOLLOW_THREADS_TRUE);
}),
);

return {
followedStatus,
displayName: channel.pipe(switchMap((c) => of$(c?.displayName))),
};
});

export default withDatabase(enhanced(AutoFollowThreads));
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,47 @@ import React, {useState} from 'react';
import {useIntl} from 'react-intl';

import {updateChannelNotifyProps} from '@actions/remote/channel';
import {t} from '@app/i18n';
import {alertErrorWithFallback} from '@app/utils/draft';
import OptionItem from '@components/option_item';
import {useServerUrl} from '@context/server';
import {preventDoubleTap} from '@utils/tap';

type Props = {
channelId: string;
ignoring: boolean;
displayName: string;
}

const IgnoreMentions = ({channelId, ignoring}: Props) => {
const IgnoreMentions = ({channelId, ignoring, displayName}: Props) => {
const [ignored, setIgnored] = useState(ignoring);
const serverUrl = useServerUrl();
const {formatMessage} = useIntl();
const intl = useIntl();

const toggleIgnore = preventDoubleTap(() => {
const toggleIgnore = preventDoubleTap(async () => {
const props: Partial<ChannelNotifyProps> = {
ignore_channel_mentions: ignoring ? 'off' : 'on',
};
setIgnored(!ignored);
updateChannelNotifyProps(serverUrl, channelId, props);
setIgnored((v) => !v);
const result = await updateChannelNotifyProps(serverUrl, channelId, props);
if (result?.error) {
alertErrorWithFallback(
intl,
result.error,
{
id: t('channel_info.channel_auto_follow_threads_failed'),
defaultMessage: 'An error occurred trying to auto follow all threads in channel {displayName}',
},
{displayName},
);
setIgnored((v) => !v);
}
});

return (
<OptionItem
action={toggleIgnore}
label={formatMessage({id: 'channel_info.ignore_mentions', defaultMessage: 'Ignore @channel, @here, @all'})}
label={intl.formatMessage({id: 'channel_info.ignore_mentions', defaultMessage: 'Ignore @channel, @here, @all'})}
icon='at'
type='toggle'
selected={ignored}
Expand Down
4 changes: 3 additions & 1 deletion app/screens/channel_info/options/ignore_mentions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {of as of$} from 'rxjs';
import {combineLatestWith, switchMap} from 'rxjs/operators';

import {Channel} from '@constants';
import {observeChannelSettings} from '@queries/servers/channel';
import {observeChannel, observeChannelSettings} from '@queries/servers/channel';
import {observeCurrentUser} from '@queries/servers/user';

import IgnoreMentions from './ignore_mentions';
Expand All @@ -34,6 +34,7 @@ const isChannelMentionsIgnored = (channelNotifyProps?: Partial<ChannelNotifyProp
};

const enhanced = withObservables(['channelId'], ({channelId, database}: Props) => {
const channel = observeChannel(database, channelId);
const currentUser = observeCurrentUser(database);
const settings = observeChannelSettings(database, channelId);
const ignoring = currentUser.pipe(
Expand All @@ -43,6 +44,7 @@ const enhanced = withObservables(['channelId'], ({channelId, database}: Props) =

return {
ignoring,
displayName: channel.pipe(switchMap((c) => of$(c?.displayName))),
};
});

Expand Down
14 changes: 11 additions & 3 deletions app/screens/channel_info/options/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {General} from '@constants';
import {isTypeDMorGM} from '@utils/channel';

import AddMembers from './add_members';
import AutoFollowThreads from './auto_follow_threads';
import ChannelFiles from './channel_files';
import EditChannel from './edit_channel';
import IgnoreMentions from './ignore_mentions';
Expand All @@ -20,6 +21,7 @@ type Props = {
type?: ChannelType;
callsEnabled: boolean;
canManageMembers: boolean;
isCRTEnabled: boolean;
canManageSettings: boolean;
}

Expand All @@ -28,15 +30,21 @@ const Options = ({
type,
callsEnabled,
canManageMembers,
isCRTEnabled,
canManageSettings,
}: Props) => {
const isDMorGM = isTypeDMorGM(type);

return (
<>
{type !== General.DM_CHANNEL &&
<IgnoreMentions channelId={channelId}/>
}
{type !== General.DM_CHANNEL && (
<>
{isCRTEnabled && (
<AutoFollowThreads channelId={channelId}/>
)}
<IgnoreMentions channelId={channelId}/>
</>
)}
<NotificationPreference channelId={channelId}/>
<PinnedMessages channelId={channelId}/>
<ChannelFiles channelId={channelId}/>
Expand Down
1 change: 1 addition & 0 deletions assets/base/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
"channel_info.archive_description.cannot_view_archived": "This will archive the channel from the team and remove it from the user interface. Archived channels can be unarchived if needed again.\n\nAre you sure you wish to archive the {term} {name}?",
"channel_info.archive_failed": "An error occurred trying to archive the channel {displayName}",
"channel_info.archive_title": "Archive {term}",
"channel_info.channel_auto_follow_threads": "Follow all threads in this channel",
"channel_info.channel_files": "Files",
"channel_info.close": "Close",
"channel_info.close_dm": "Close direct message",
Expand Down
1 change: 1 addition & 0 deletions types/api/channels.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type ChannelNotifyProps = {
mark_unread: 'all' | 'mention';
push: NotificationLevel;
ignore_channel_mentions: 'default' | 'off' | 'on';
channel_auto_follow_threads: 'on' | 'off';
push_threads: 'all' | 'mention';
};
type Channel = {
Expand Down

0 comments on commit 551a01f

Please sign in to comment.