feat: display disabled actions on action sheet (#5356)

* improve: show the item disabled when the user doesn't have permission

* minor tweak changing from disabled to enabled param

* add the behavior at long press message

* minor tweak

* minor tweak

* remove the header notPermission and show toast

* tweak at auto translate e2e test

* minor tweak

* minor tweak translated

* minor tweak en.json

* minor tweak description
This commit is contained in:
Reinaldo Neto 2023-12-11 12:51:44 -03:00 committed by GitHub
parent 7c0a2692dc
commit 3a5173ffda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 91 additions and 70 deletions

View File

@ -1,11 +1,13 @@
import React from 'react';
import { Text, View } from 'react-native';
import { themes } from '../../lib/constants';
import { CustomIcon } from '../CustomIcon';
import { useTheme } from '../../theme';
import EventEmitter from '../../lib/methods/helpers/events';
import I18n from '../../i18n';
import { TActionSheetOptionsItem } from './Provider';
import styles from './styles';
import { LISTENER } from '../Toast';
import Touch from '../Touch';
export interface IActionSheetItem {
@ -14,25 +16,30 @@ export interface IActionSheetItem {
}
export const Item = React.memo(({ item, hide }: IActionSheetItem) => {
const { theme } = useTheme();
const enabled = item?.enabled ?? true;
const { colors } = useTheme();
const onPress = () => {
hide();
item?.onPress();
if (enabled) {
hide();
item?.onPress();
} else {
EventEmitter.emit(LISTENER, { message: I18n.t('You_dont_have_permission_to_perform_this_action') });
}
};
let textColor = colors.bodyText;
if (item.danger) {
textColor = colors.dangerColor;
}
if (!enabled) {
textColor = colors.fontDisabled;
}
return (
<Touch onPress={onPress} style={[styles.item, { backgroundColor: themes[theme].focusedBackground }]} testID={item.testID}>
{item.icon ? (
<CustomIcon name={item.icon} size={20} color={item.danger ? themes[theme].dangerColor : themes[theme].bodyText} />
) : null}
<Touch onPress={onPress} style={[styles.item, { backgroundColor: colors.focusedBackground }]} testID={item.testID}>
{item.icon ? <CustomIcon name={item.icon} size={20} color={textColor} /> : null}
<View style={styles.titleContainer}>
<Text
numberOfLines={1}
style={[
styles.title,
{ color: item.danger ? themes[theme].dangerColor : themes[theme].bodyText, marginLeft: item.icon ? 16 : 0 }
]}
>
<Text numberOfLines={1} style={[styles.title, { color: textColor, marginLeft: item.icon ? 16 : 0 }]}>
{item.title}
</Text>
</View>

View File

@ -11,6 +11,7 @@ export type TActionSheetOptionsItem = {
testID?: string;
onPress: () => void;
right?: () => React.ReactElement;
enabled?: boolean;
};
export type TActionSheetOptions = {

View File

@ -405,22 +405,22 @@ const MessageActions = React.memo(
}
// Reply in DM
if (room.t !== 'd' && room.t !== 'l' && permissions.hasCreateDirectMessagePermission && !videoConfBlock) {
if (room.t !== 'd' && room.t !== 'l' && !videoConfBlock) {
options.push({
title: I18n.t('Reply_in_direct_message'),
icon: 'arrow-back',
onPress: () => handleReplyInDM(message)
onPress: () => handleReplyInDM(message),
enabled: permissions.hasCreateDirectMessagePermission
});
}
// Create Discussion
if (permissions.hasCreateDiscussionOtherUserPermission) {
options.push({
title: I18n.t('Start_a_Discussion'),
icon: 'discussions',
onPress: () => handleCreateDiscussion(message)
});
}
options.push({
title: I18n.t('Start_a_Discussion'),
icon: 'discussions',
onPress: () => handleCreateDiscussion(message),
enabled: permissions.hasCreateDiscussionOtherUserPermission
});
if (compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '6.2.0') && !videoConfBlock) {
options.push({
@ -454,20 +454,22 @@ const MessageActions = React.memo(
});
// Edit
if (allowEdit(message) && !videoConfBlock) {
if (!videoConfBlock) {
options.push({
title: I18n.t('Edit'),
icon: 'edit',
onPress: () => handleEdit(message)
onPress: () => handleEdit(message),
enabled: allowEdit(message)
});
}
// Pin
if (Message_AllowPinning && permissions?.hasPinPermission && !videoConfBlock) {
if (Message_AllowPinning && !videoConfBlock) {
options.push({
title: I18n.t(message.pinned ? 'Unpin' : 'Pin'),
icon: 'pin',
onPress: () => handlePin(message)
onPress: () => handlePin(message),
enabled: permissions?.hasPinPermission
});
}
@ -516,14 +518,13 @@ const MessageActions = React.memo(
});
// Delete
if (allowDelete(message)) {
options.push({
title: I18n.t('Delete'),
icon: 'delete',
danger: true,
onPress: () => handleDelete(message)
});
}
options.push({
title: I18n.t('Delete'),
icon: 'delete',
danger: true,
onPress: () => handleDelete(message),
enabled: allowDelete(message)
});
return options;
};
@ -534,10 +535,13 @@ const MessageActions = React.memo(
showActionSheet({
options: getOptions(message),
headerHeight: HEADER_HEIGHT,
customHeader:
!isReadOnly || room.reactWhenReadOnly ? (
<Header handleReaction={handleReaction} isMasterDetail={isMasterDetail} message={message} />
) : null
customHeader: (
<>
{!isReadOnly || room.reactWhenReadOnly ? (
<Header handleReaction={handleReaction} isMasterDetail={isMasterDetail} message={message} />
) : null}
</>
)
});
};

View File

@ -904,40 +904,43 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
onPress: () => goToCannedResponses()
});
}
if (permissionToUpload) {
options.push(
{
title: I18n.t('Take_a_photo'),
icon: 'camera-photo',
onPress: this.takePhoto
},
{
title: I18n.t('Take_a_video'),
icon: 'camera',
onPress: this.takeVideo
},
{
title: I18n.t('Choose_from_library'),
icon: 'image',
onPress: this.chooseFromLibrary
},
{
title: I18n.t('Choose_file'),
icon: 'attach',
onPress: this.chooseFile
}
);
}
if (hasCreateDiscussionPermission) {
options.push({
options.push(
{
title: I18n.t('Take_a_photo'),
icon: 'camera-photo',
onPress: this.takePhoto,
enabled: permissionToUpload
},
{
title: I18n.t('Take_a_video'),
icon: 'camera',
onPress: this.takeVideo,
enabled: permissionToUpload
},
{
title: I18n.t('Choose_from_library'),
icon: 'image',
onPress: this.chooseFromLibrary,
enabled: permissionToUpload
},
{
title: I18n.t('Choose_file'),
icon: 'attach',
onPress: this.chooseFile,
enabled: permissionToUpload
},
{
title: I18n.t('Create_Discussion'),
icon: 'discussions',
onPress: this.createDiscussion
});
}
onPress: this.createDiscussion,
enabled: hasCreateDiscussionPermission
}
);
this.closeEmojiAndAction(showActionSheet, { options });
this.closeEmojiAndAction(showActionSheet, {
options
});
};
editCancel = () => {

View File

@ -761,6 +761,7 @@
"Enable_writing_in_room": "Enable writing in room",
"Disable_writing_in_room": "Disable writing in room",
"Pinned_a_message": "Pinned a message:",
"You_dont_have_permission_to_perform_this_action": "You dont have permission to perform this action. Check with a workspace administrator.",
"Jump_to_message": "Jump to message",
"Missed_call": "Missed call"
}

View File

@ -757,5 +757,6 @@
"The_user_will_be_able_to_type_in_roomName": "O usuário poderá digitar em {{roomName}}",
"Enable_writing_in_room": "Permitir escrita na sala",
"Disable_writing_in_room": "Desabilitar escrita na sala",
"You_dont_have_permission_to_perform_this_action": "Você não tem permissão para realizar esta ação. Verifique com um administrador do espaço de trabalho.",
"Missed_call": "Chamada perdida"
}

View File

@ -112,6 +112,7 @@ export const colors = {
strokeExtraLight: '#EBECEF',
strokeLight: '#CBCED1',
surfaceTint: '#F7F8FA',
fontDisabled: '#CBCED1',
...mentions,
...callButtons
},
@ -199,6 +200,7 @@ export const colors = {
strokeExtraLight: '#2F343D',
strokeLight: '#333842',
surfaceTint: '#1F2329',
fontDisabled: '#60646C',
...mentions,
...callButtons
},
@ -286,6 +288,7 @@ export const colors = {
strokeExtraLight: '#2F343D',
strokeLight: '#333842',
surfaceTint: '#1F2329',
fontDisabled: '#60646C',
...mentions,
...callButtons
}

View File

@ -186,6 +186,7 @@ describe('Auto Translate', () => {
await waitForVisible('action-sheet-handle');
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
await element(by[textMatcher]('Edit')).atIndex(0).swipe('up', 'fast', 0.5);
await waitForVisibleTextMatcher('View original', textMatcher);
await element(by[textMatcher]('View original')).atIndex(0).tap();