Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions app/containers/MessageBox/RecordAudio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { events, logEvent } from '../../utils/log';

interface IMessageBoxRecordAudioProps {
theme: string;
permissionToUpload: boolean;
recordingCallback: Function;
onFinish: Function;
}
Expand Down Expand Up @@ -192,9 +193,11 @@ export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAu
};

render() {
const { theme } = this.props;
const { theme, permissionToUpload } = this.props;
const { isRecording, isRecorderActive } = this.state;

if (!permissionToUpload) {
return null;
}
if (!isRecording && !isRecorderActive) {
return (
<BorderlessButton
Expand Down
139 changes: 100 additions & 39 deletions app/containers/MessageBox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ interface IMessageBoxProps {
sharing: boolean;
isActionsEnabled: boolean;
usedCannedResponse: string;
uploadFilePermission: string[];
serverVersion: string;
}

interface IMessageBoxState {
Expand All @@ -124,6 +126,7 @@ interface IMessageBoxState {
};
tshow: boolean;
mentionLoading: boolean;
permissionToUpload: boolean;
}

class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
Expand Down Expand Up @@ -179,41 +182,13 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
showCommandPreview: false,
command: {},
tshow: false,
mentionLoading: false
mentionLoading: false,
permissionToUpload: true
};
this.text = '';
this.selection = { start: 0, end: 0 };
this.focused = false;

// MessageBox Actions
this.options = [
{
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
},
{
title: I18n.t('Create_Discussion'),
icon: 'discussions',
onPress: this.createDiscussion
}
];

const libPickerLabels = {
cropperChooseText: I18n.t('Choose'),
cropperCancelText: I18n.t('Cancel'),
Expand Down Expand Up @@ -277,6 +252,8 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
this.onChangeText(usedCannedResponse);
}

this.setOptions();

this.unsubscribeFocus = navigation.addListener('focus', () => {
// didFocus
// We should wait pushed views be dismissed
Expand Down Expand Up @@ -321,10 +298,20 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
}
}

shouldComponentUpdate(nextProps: any, nextState: any) {
const { showEmojiKeyboard, showSend, recording, mentions, commandPreview, tshow, mentionLoading, trackingType } = this.state;

const { roomType, replying, editing, isFocused, message, theme, usedCannedResponse } = this.props;
shouldComponentUpdate(nextProps: IMessageBoxProps, nextState: IMessageBoxState) {
const {
showEmojiKeyboard,
showSend,
recording,
mentions,
commandPreview,
tshow,
mentionLoading,
trackingType,
permissionToUpload
} = this.state;

const { roomType, replying, editing, isFocused, message, theme, usedCannedResponse, uploadFilePermission } = this.props;
if (nextProps.theme !== theme) {
return true;
}
Expand Down Expand Up @@ -358,6 +345,9 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
if (nextState.tshow !== tshow) {
return true;
}
if (nextState.permissionToUpload !== permissionToUpload) {
return true;
}
if (!dequal(nextState.mentions, mentions)) {
return true;
}
Expand All @@ -367,12 +357,22 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
if (!dequal(nextProps.message?.id, message?.id)) {
return true;
}
if (!dequal(nextProps.uploadFilePermission, uploadFilePermission)) {
return true;
}
if (nextProps.usedCannedResponse !== usedCannedResponse) {
return true;
}
return false;
}

componentDidUpdate(prevProps: IMessageBoxProps) {
const { uploadFilePermission } = this.props;
if (!dequal(prevProps.uploadFilePermission, uploadFilePermission)) {
this.setOptions();
}
}

componentWillUnmount() {
console.countReset(`${this.constructor.name}.render calls`);
if (this.onChangeText && this.onChangeText.stop) {
Expand Down Expand Up @@ -404,6 +404,19 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
}
}

setOptions = async () => {
const { uploadFilePermission, rid } = this.props;

// Servers older than 4.2
if (!uploadFilePermission) {
this.setState({ permissionToUpload: true });
return;
}

const permissionToUpload = await RocketChat.hasPermission([uploadFilePermission], rid);
this.setState({ permissionToUpload: permissionToUpload[0] });
};

onChangeText: any = (text: string): void => {
const isTextEmpty = text.length === 0;
this.setShowSend(!isTextEmpty);
Expand Down Expand Up @@ -766,8 +779,41 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {

showMessageBoxActions = () => {
logEvent(events.ROOM_SHOW_BOX_ACTIONS);
const { permissionToUpload } = this.state;
const { showActionSheet } = this.props;
showActionSheet({ options: this.options });

const options = [];
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
}
);
}

options.push({
title: I18n.t('Create_Discussion'),
icon: 'discussions',
onPress: this.createDiscussion
});
showActionSheet({ options });
};

editCancel = () => {
Expand Down Expand Up @@ -968,8 +1014,17 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
};

renderContent = () => {
const { recording, showEmojiKeyboard, showSend, mentions, trackingType, commandPreview, showCommandPreview, mentionLoading } =
this.state;
const {
recording,
showEmojiKeyboard,
showSend,
mentions,
trackingType,
commandPreview,
showCommandPreview,
mentionLoading,
permissionToUpload
} = this.state;
const {
editing,
message,
Expand All @@ -995,7 +1050,12 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {

const recordAudio =
showSend || !Message_AudioRecorderEnabled ? null : (
<RecordAudio theme={theme} recordingCallback={this.recordingCallback} onFinish={this.finishAudioMessage} />
<RecordAudio
theme={theme}
recordingCallback={this.recordingCallback}
onFinish={this.finishAudioMessage}
permissionToUpload={permissionToUpload}
/>
);

const commandsPreviewAndMentions = !recording ? (
Expand Down Expand Up @@ -1117,7 +1177,8 @@ const mapStateToProps = (state: any) => ({
user: getUserSelector(state),
FileUpload_MediaTypeWhiteList: state.settings.FileUpload_MediaTypeWhiteList,
FileUpload_MaxFileSize: state.settings.FileUpload_MaxFileSize,
Message_AudioRecorderEnabled: state.settings.Message_AudioRecorderEnabled
Message_AudioRecorderEnabled: state.settings.Message_AudioRecorderEnabled,
uploadFilePermission: state.permissions['mobile-upload-file']
});

const dispatchToProps = {
Expand Down
6 changes: 4 additions & 2 deletions app/containers/UIKit/Image.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React from 'react';
import React, { useContext } from 'react';
import { StyleSheet, View } from 'react-native';
import FastImage from '@rocket.chat/react-native-fast-image';
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';

import ImageContainer from '../message/Image';
import Navigation from '../../lib/Navigation';
import { KitContext } from './utils';

const styles = StyleSheet.create({
image: {
Expand Down Expand Up @@ -46,7 +47,8 @@ export const Thumb = ({ element, size = 88 }: IThumb) => (
);

export const Media = ({ element, theme }: IMedia) => {
const showAttachment = (attachment: any) => Navigation.navigate('AttachmentView', { attachment });
const { rid } = useContext(KitContext);
const showAttachment = (attachment: any) => Navigation.navigate('AttachmentView', { attachment, rid });
const { imageUrl } = element;
// @ts-ignore
return <ImageContainer file={{ image_url: imageUrl }} imageUrl={imageUrl} showAttachment={showAttachment} theme={theme} />;
Expand Down
1 change: 1 addition & 0 deletions app/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"error-save-video": "Error while saving video",
"error-field-unavailable": "{{field}} is already in use :(",
"error-file-too-large": "File is too large",
"error-not-permission-to-upload-file": "You don't have permission to upload files",
"error-importer-not-defined": "The importer was not defined correctly, it is missing the Import class.",
"error-input-is-not-a-valid-field": "{{input}} is not a valid {{field}}",
"error-invalid-actionlink": "Invalid action link",
Expand Down
4 changes: 3 additions & 1 deletion app/lib/methods/getPermissions.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ const PERMISSIONS = [
'convert-team',
'edit-omnichannel-contact',
'edit-livechat-room-customfields',
'view-canned-responses'
'view-canned-responses',
'mobile-upload-file',
'mobile-download-file'
];

export async function setPermissions() {
Expand Down
1 change: 1 addition & 0 deletions app/stacks/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ export type InsideStackParamList = {
E2EEnterYourPasswordStackNavigator: NavigatorScreenParams<E2EEnterYourPasswordStackParamList>;
AttachmentView: {
attachment: IAttachment;
rid: string;
};
StatusView: undefined;
ShareView: {
Expand Down
5 changes: 4 additions & 1 deletion app/utils/media.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
export const canUploadFile = (file, allowList, maxFileSize) => {
export const canUploadFile = (file, allowList, maxFileSize, permissionToUploadFile) => {
if (!(file && file.path)) {
return { success: true };
}
if (maxFileSize > -1 && file.size > maxFileSize) {
return { success: false, error: 'error-file-too-large' };
}
if (!permissionToUploadFile) {
return { success: false, error: 'error-not-permission-to-upload-file' };
}
// if white list is empty, all media types are enabled
if (!allowList || allowList === '*') {
return { success: true };
Expand Down
Loading