diff --git a/app/containers/MessageComposer/MessageComposer.test.tsx b/app/containers/MessageComposer/MessageComposer.test.tsx
index 644decabae8..cd63fddf52d 100644
--- a/app/containers/MessageComposer/MessageComposer.test.tsx
+++ b/app/containers/MessageComposer/MessageComposer.test.tsx
@@ -439,6 +439,70 @@ describe('MessageComposer', () => {
expect(onSendMessage).toHaveBeenCalledWith('@john', undefined);
});
+ test('does not show @all or @here in autocomplete when user does not have permissions', async () => {
+ mockedStore.dispatch(setPermissions({ 'mention-all': [], 'mention-here': [] }));
+ const onSendMessage = jest.fn();
+ render();
+
+ await fireEvent(screen.getByTestId('message-composer-input'), 'focus');
+ await fireEvent.changeText(screen.getByTestId('message-composer-input'), '@');
+ await fireEvent(screen.getByTestId('message-composer-input'), 'selectionChange', {
+ nativeEvent: { selection: { start: 1, end: 1 } }
+ });
+ jest.advanceTimersByTime(500);
+
+ await waitFor(() => expect(screen.queryByTestId('autocomplete-item-all')).not.toBeOnTheScreen());
+ await waitFor(() => expect(screen.queryByTestId('autocomplete-item-here')).not.toBeOnTheScreen());
+ });
+
+ test('shows only @all when user has mention-all permission', async () => {
+ mockedStore.dispatch(setPermissions({ 'mention-all': ['user'], 'mention-here': [] }));
+ const onSendMessage = jest.fn();
+ render();
+
+ await fireEvent(screen.getByTestId('message-composer-input'), 'focus');
+ await fireEvent.changeText(screen.getByTestId('message-composer-input'), '@');
+ await fireEvent(screen.getByTestId('message-composer-input'), 'selectionChange', {
+ nativeEvent: { selection: { start: 1, end: 1 } }
+ });
+ jest.advanceTimersByTime(500);
+
+ await waitFor(() => expect(screen.queryByTestId('autocomplete-item-all')).toBeOnTheScreen());
+ await waitFor(() => expect(screen.queryByTestId('autocomplete-item-here')).not.toBeOnTheScreen());
+ });
+
+ test('shows only @here when user has mention-here permission', async () => {
+ mockedStore.dispatch(setPermissions({ 'mention-here': ['user'], 'mention-all': [] }));
+ const onSendMessage = jest.fn();
+ render();
+
+ await fireEvent(screen.getByTestId('message-composer-input'), 'focus');
+ await fireEvent.changeText(screen.getByTestId('message-composer-input'), '@');
+ await fireEvent(screen.getByTestId('message-composer-input'), 'selectionChange', {
+ nativeEvent: { selection: { start: 1, end: 1 } }
+ });
+ jest.advanceTimersByTime(500);
+
+ await waitFor(() => expect(screen.queryByTestId('autocomplete-item-here')).toBeOnTheScreen());
+ await waitFor(() => expect(screen.queryByTestId('autocomplete-item-all')).not.toBeOnTheScreen());
+ });
+
+ test('shows both @all and @here when user has both permissions', async () => {
+ mockedStore.dispatch(setPermissions({ 'mention-all': ['user'], 'mention-here': ['user'] }));
+ const onSendMessage = jest.fn();
+ render();
+
+ await fireEvent(screen.getByTestId('message-composer-input'), 'focus');
+ await fireEvent.changeText(screen.getByTestId('message-composer-input'), '@');
+ await fireEvent(screen.getByTestId('message-composer-input'), 'selectionChange', {
+ nativeEvent: { selection: { start: 1, end: 1 } }
+ });
+ jest.advanceTimersByTime(500);
+
+ await waitFor(() => expect(screen.queryByTestId('autocomplete-item-all')).toBeOnTheScreen());
+ await waitFor(() => expect(screen.queryByTestId('autocomplete-item-here')).toBeOnTheScreen());
+ });
+
test('select # room inserts channel and sends, autocomplete hides', async () => {
const onSendMessage = jest.fn();
(search as unknown as jest.Mock).mockImplementationOnce(() => [{ rid: 'r1', name: 'general', t: 'c' }]);
diff --git a/app/containers/MessageComposer/__snapshots__/MessageComposer.test.tsx.snap b/app/containers/MessageComposer/__snapshots__/MessageComposer.test.tsx.snap
index 8dd0f6b4152..ca392c9b2f3 100644
--- a/app/containers/MessageComposer/__snapshots__/MessageComposer.test.tsx.snap
+++ b/app/containers/MessageComposer/__snapshots__/MessageComposer.test.tsx.snap
@@ -82,7 +82,7 @@ exports[`MessageComposer Audio tap record 1`] = `
borderless={true}
collapsable={false}
delayLongPress={600}
- handlerTag={259}
+ handlerTag={289}
handlerType="NativeViewGestureHandler"
hitSlop={
{
@@ -177,7 +177,7 @@ exports[`MessageComposer Audio tap record 1`] = `
borderless={true}
collapsable={false}
delayLongPress={600}
- handlerTag={260}
+ handlerTag={290}
handlerType="NativeViewGestureHandler"
hitSlop={
{
@@ -299,7 +299,7 @@ exports[`MessageComposer Quote Add quote \`abc\` 1`] = `
borderless={true}
collapsable={false}
delayLongPress={600}
- handlerTag={246}
+ handlerTag={276}
handlerType="NativeViewGestureHandler"
hitSlop={
{
@@ -415,7 +415,7 @@ exports[`MessageComposer Quote Add quote \`abc\` 1`] = `
borderless={true}
collapsable={false}
delayLongPress={600}
- handlerTag={247}
+ handlerTag={277}
handlerType="NativeViewGestureHandler"
hitSlop={
{
@@ -587,7 +587,7 @@ exports[`MessageComposer Quote Add quote \`abc\` 1`] = `
borderless={true}
collapsable={false}
delayLongPress={600}
- handlerTag={248}
+ handlerTag={278}
handlerType="NativeViewGestureHandler"
hitSlop={
{
@@ -744,7 +744,7 @@ exports[`MessageComposer Quote Add quote \`def\` 1`] = `
borderless={true}
collapsable={false}
delayLongPress={600}
- handlerTag={249}
+ handlerTag={279}
handlerType="NativeViewGestureHandler"
hitSlop={
{
@@ -860,7 +860,7 @@ exports[`MessageComposer Quote Add quote \`def\` 1`] = `
borderless={true}
collapsable={false}
delayLongPress={600}
- handlerTag={250}
+ handlerTag={280}
handlerType="NativeViewGestureHandler"
hitSlop={
{
@@ -1033,7 +1033,7 @@ exports[`MessageComposer Quote Add quote \`def\` 1`] = `
borderless={true}
collapsable={false}
delayLongPress={600}
- handlerTag={251}
+ handlerTag={281}
handlerType="NativeViewGestureHandler"
hitSlop={
{
@@ -1214,7 +1214,7 @@ exports[`MessageComposer Quote Add quote \`def\` 1`] = `
borderless={true}
collapsable={false}
delayLongPress={600}
- handlerTag={252}
+ handlerTag={282}
handlerType="NativeViewGestureHandler"
hitSlop={
{
@@ -1371,7 +1371,7 @@ exports[`MessageComposer Quote Remove a quote 1`] = `
borderless={true}
collapsable={false}
delayLongPress={600}
- handlerTag={253}
+ handlerTag={283}
handlerType="NativeViewGestureHandler"
hitSlop={
{
@@ -1487,7 +1487,7 @@ exports[`MessageComposer Quote Remove a quote 1`] = `
borderless={true}
collapsable={false}
delayLongPress={600}
- handlerTag={254}
+ handlerTag={284}
handlerType="NativeViewGestureHandler"
hitSlop={
{
@@ -1660,7 +1660,7 @@ exports[`MessageComposer Quote Remove a quote 1`] = `
borderless={true}
collapsable={false}
delayLongPress={600}
- handlerTag={255}
+ handlerTag={285}
handlerType="NativeViewGestureHandler"
hitSlop={
{
@@ -1841,7 +1841,7 @@ exports[`MessageComposer Quote Remove a quote 1`] = `
borderless={true}
collapsable={false}
delayLongPress={600}
- handlerTag={256}
+ handlerTag={286}
handlerType="NativeViewGestureHandler"
hitSlop={
{
diff --git a/app/containers/MessageComposer/hooks/useAutocomplete.ts b/app/containers/MessageComposer/hooks/useAutocomplete.ts
index 94ab23f63cc..906fe8d631e 100644
--- a/app/containers/MessageComposer/hooks/useAutocomplete.ts
+++ b/app/containers/MessageComposer/hooks/useAutocomplete.ts
@@ -16,6 +16,7 @@ import { getCommandPreview, getListCannedResponse } from '../../../lib/services/
import log from '../../../lib/methods/helpers/log';
import I18n from '../../../i18n';
import { NO_CANNED_RESPONSES } from '../constants';
+import { usePermissions } from '../../../lib/hooks/usePermissions';
const MENTIONS_COUNT_TO_DISPLAY = 4;
@@ -52,6 +53,8 @@ export const useAutocomplete = ({
updateAutocompleteVisible?: (updatedAutocompleteVisible: boolean) => void;
}): TAutocompleteItem[] => {
const [items, setItems] = useState([]);
+ const [mentionAll, mentionHere] = usePermissions(['mention-all', 'mention-here']);
+
useEffect(() => {
const getAutocomplete = async () => {
try {
@@ -87,7 +90,7 @@ export const useAutocomplete = ({
type
})) as IAutocompleteUserRoom[];
if (type === '@') {
- if ('all'.includes(text.toLocaleLowerCase())) {
+ if (mentionAll && 'all'.includes(text.toLocaleLowerCase())) {
parsedRes.push({
id: 'all',
title: 'all',
@@ -96,7 +99,7 @@ export const useAutocomplete = ({
t: 'd'
});
}
- if ('here'.includes(text.toLocaleLowerCase())) {
+ if (mentionHere && 'here'.includes(text.toLocaleLowerCase())) {
parsedRes.push({
id: 'here',
title: 'here',
diff --git a/app/lib/methods/getPermissions.ts b/app/lib/methods/getPermissions.ts
index 8bf2fd21db0..02082089ad1 100644
--- a/app/lib/methods/getPermissions.ts
+++ b/app/lib/methods/getPermissions.ts
@@ -66,7 +66,9 @@ export const SUPPORTED_PERMISSIONS = [
'create-team-channel',
'create-team-group',
'delete-team-channel',
- 'delete-team-group'
+ 'delete-team-group',
+ 'mention-all',
+ 'mention-here'
] as const;
export async function setPermissions(): Promise {