[IMPROVE] Add emoji picker to iOS (#4366)
* [IMPROVE] Add emoji picker to iOS * clean left and right buttons * fix the redux in emojipicker * fix behavior when emoji keyboard is openning * added isIOS * fix show reactions when emoji is open * minor tweak * add provider * fix baseurl * minor tweak * create closeEmojiAndAction and added to record * fix actionsheet for omnichannel * fix action sheet * fix close emoji when navigate to other screen * added iactionsheetprovider to roomview * clean variables * fix theme * close the emojikeyboard when click on message * apoint package.json to new pr * fix branch * fix package.json
This commit is contained in:
parent
a4f171a12d
commit
e38aedcbff
|
@ -65,6 +65,7 @@ class EmojiCategory extends React.Component<IEmojiCategory> {
|
||||||
initialNumToRender={45}
|
initialNumToRender={45}
|
||||||
removeClippedSubviews
|
removeClippedSubviews
|
||||||
{...scrollPersistTaps}
|
{...scrollPersistTaps}
|
||||||
|
keyboardDismissMode={'none'}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ import protectedFunction from '../../lib/methods/helpers/protectedFunction';
|
||||||
import shortnameToUnicode from '../../lib/methods/helpers/shortnameToUnicode';
|
import shortnameToUnicode from '../../lib/methods/helpers/shortnameToUnicode';
|
||||||
import log from '../../lib/methods/helpers/log';
|
import log from '../../lib/methods/helpers/log';
|
||||||
import { themes } from '../../lib/constants';
|
import { themes } from '../../lib/constants';
|
||||||
import { TSupportedThemes, withTheme } from '../../theme';
|
import { TSupportedThemes } from '../../theme';
|
||||||
import { IEmoji, TGetCustomEmoji, IApplicationState, ICustomEmojis, TFrequentlyUsedEmojiModel } from '../../definitions';
|
import { IEmoji, TGetCustomEmoji, IApplicationState, ICustomEmojis, TFrequentlyUsedEmojiModel } from '../../definitions';
|
||||||
|
|
||||||
interface IEmojiPickerProps {
|
interface IEmojiPickerProps {
|
||||||
|
@ -198,7 +198,8 @@ class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: IApplicationState) => ({
|
const mapStateToProps = (state: IApplicationState) => ({
|
||||||
customEmojis: state.customEmojis
|
customEmojis: state.customEmojis,
|
||||||
|
baseUrl: state.share.server.server || state.server.server
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps)(withTheme(EmojiPicker));
|
export default connect(mapStateToProps)(EmojiPicker);
|
||||||
|
|
|
@ -1,39 +1,28 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View } from 'react-native';
|
import { View } from 'react-native';
|
||||||
import { KeyboardRegistry } from 'react-native-ui-lib/keyboard';
|
import { KeyboardRegistry } from 'react-native-ui-lib/keyboard';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
|
||||||
import { store } from '../../lib/store/auxStore';
|
import store from '../../lib/store';
|
||||||
import EmojiPicker from '../EmojiPicker';
|
import EmojiPicker from '../EmojiPicker';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import { themes } from '../../lib/constants';
|
import { themes } from '../../lib/constants';
|
||||||
import { TSupportedThemes, withTheme } from '../../theme';
|
import { TSupportedThemes } from '../../theme';
|
||||||
|
|
||||||
interface IMessageBoxEmojiKeyboard {
|
const EmojiKeyboard = ({ theme }: { theme: TSupportedThemes }) => {
|
||||||
theme: TSupportedThemes;
|
const onEmojiSelected = (emoji: string) => {
|
||||||
}
|
|
||||||
|
|
||||||
export default class EmojiKeyboard extends React.PureComponent<IMessageBoxEmojiKeyboard, any> {
|
|
||||||
private readonly baseUrl: string;
|
|
||||||
|
|
||||||
constructor(props: IMessageBoxEmojiKeyboard) {
|
|
||||||
super(props);
|
|
||||||
const state = store.getState();
|
|
||||||
this.baseUrl = state.share.server.server || state.server.server;
|
|
||||||
}
|
|
||||||
|
|
||||||
onEmojiSelected = (emoji: string) => {
|
|
||||||
KeyboardRegistry.onItemSelected('EmojiKeyboard', { emoji });
|
KeyboardRegistry.onItemSelected('EmojiKeyboard', { emoji });
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
return (
|
||||||
const { theme } = this.props;
|
<Provider store={store}>
|
||||||
return (
|
|
||||||
<View
|
<View
|
||||||
style={[styles.emojiKeyboardContainer, { borderTopColor: themes[theme].borderColor }]}
|
style={[styles.emojiKeyboardContainer, { borderTopColor: themes[theme].borderColor }]}
|
||||||
testID='messagebox-keyboard-emoji'>
|
testID='messagebox-keyboard-emoji'>
|
||||||
<EmojiPicker onEmojiSelected={this.onEmojiSelected} baseUrl={this.baseUrl} theme={theme} />
|
<EmojiPicker onEmojiSelected={onEmojiSelected} theme={theme} />
|
||||||
</View>
|
</View>
|
||||||
);
|
</Provider>
|
||||||
}
|
);
|
||||||
}
|
};
|
||||||
KeyboardRegistry.registerKeyboard('EmojiKeyboard', () => withTheme(EmojiKeyboard));
|
|
||||||
|
KeyboardRegistry.registerKeyboard('EmojiKeyboard', () => EmojiKeyboard);
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { View } from 'react-native';
|
|
||||||
|
|
||||||
import { ActionsButton, CancelEditingButton } from './buttons';
|
|
||||||
import styles from './styles';
|
|
||||||
|
|
||||||
interface IMessageBoxLeftButtons {
|
|
||||||
showMessageBoxActions(): void;
|
|
||||||
editing: boolean;
|
|
||||||
editCancel(): void;
|
|
||||||
isActionsEnabled: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const LeftButtons = React.memo(({ showMessageBoxActions, editing, editCancel, isActionsEnabled }: IMessageBoxLeftButtons) => {
|
|
||||||
if (editing) {
|
|
||||||
return <CancelEditingButton onPress={editCancel} />;
|
|
||||||
}
|
|
||||||
if (isActionsEnabled) {
|
|
||||||
return <ActionsButton onPress={showMessageBoxActions} />;
|
|
||||||
}
|
|
||||||
return <View style={styles.buttonsWhitespace} />;
|
|
||||||
});
|
|
||||||
|
|
||||||
export default LeftButtons;
|
|
|
@ -17,6 +17,7 @@ interface IMessageBoxRecordAudioProps {
|
||||||
permissionToUpload: boolean;
|
permissionToUpload: boolean;
|
||||||
recordingCallback: Function;
|
recordingCallback: Function;
|
||||||
onFinish: Function;
|
onFinish: Function;
|
||||||
|
onStart: Function;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RECORDING_EXTENSION = '.m4a';
|
const RECORDING_EXTENSION = '.m4a';
|
||||||
|
@ -116,6 +117,9 @@ export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAu
|
||||||
};
|
};
|
||||||
|
|
||||||
startRecordingAudio = async () => {
|
startRecordingAudio = async () => {
|
||||||
|
const { onStart } = this.props;
|
||||||
|
onStart();
|
||||||
|
|
||||||
logEvent(events.ROOM_AUDIO_RECORD);
|
logEvent(events.ROOM_AUDIO_RECORD);
|
||||||
if (!this.isRecorderBusy) {
|
if (!this.isRecorderBusy) {
|
||||||
this.isRecorderBusy = true;
|
this.isRecorderBusy = true;
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { SendButton } from './buttons';
|
|
||||||
|
|
||||||
interface IMessageBoxRightButtons {
|
|
||||||
showSend: boolean;
|
|
||||||
submit(): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const RightButtons = ({ showSend, submit }: IMessageBoxRightButtons) => {
|
|
||||||
if (showSend) {
|
|
||||||
return <SendButton onPress={submit} />;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default RightButtons;
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View } from 'react-native';
|
import { View } from 'react-native';
|
||||||
|
|
||||||
|
import { isIOS } from '../../lib/methods/helpers';
|
||||||
import { ActionsButton, SendButton } from './buttons';
|
import { ActionsButton, SendButton } from './buttons';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
|
||||||
|
@ -18,7 +19,7 @@ const RightButtons = React.memo(({ showSend, submit, showMessageBoxActions, isAc
|
||||||
if (isActionsEnabled) {
|
if (isActionsEnabled) {
|
||||||
return <ActionsButton onPress={showMessageBoxActions} />;
|
return <ActionsButton onPress={showMessageBoxActions} />;
|
||||||
}
|
}
|
||||||
return <View style={styles.buttonsWhitespace} />;
|
return !isIOS ? <View style={styles.buttonsWhitespace} /> : null;
|
||||||
});
|
});
|
||||||
|
|
||||||
export default RightButtons;
|
export default RightButtons;
|
|
@ -4,3 +4,5 @@ export const MENTIONS_TRACKING_TYPE_COMMANDS = '/';
|
||||||
export const MENTIONS_TRACKING_TYPE_ROOMS = '#';
|
export const MENTIONS_TRACKING_TYPE_ROOMS = '#';
|
||||||
export const MENTIONS_TRACKING_TYPE_CANNED = '!';
|
export const MENTIONS_TRACKING_TYPE_CANNED = '!';
|
||||||
export const MENTIONS_COUNT_TO_DISPLAY = 4;
|
export const MENTIONS_COUNT_TO_DISPLAY = 4;
|
||||||
|
|
||||||
|
export const TIMEOUT_CLOSE_EMOJI = 300;
|
||||||
|
|
|
@ -19,11 +19,7 @@ import RecordAudio from './RecordAudio';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import ReplyPreview from './ReplyPreview';
|
import ReplyPreview from './ReplyPreview';
|
||||||
import { themes } from '../../lib/constants';
|
import { themes } from '../../lib/constants';
|
||||||
// @ts-ignore
|
|
||||||
// eslint-disable-next-line import/extensions,import/no-unresolved
|
|
||||||
import LeftButtons from './LeftButtons';
|
import LeftButtons from './LeftButtons';
|
||||||
// @ts-ignore
|
|
||||||
// eslint-disable-next-line import/extensions,import/no-unresolved
|
|
||||||
import RightButtons from './RightButtons';
|
import RightButtons from './RightButtons';
|
||||||
import { canUploadFile } from '../../lib/methods/helpers/media';
|
import { canUploadFile } from '../../lib/methods/helpers/media';
|
||||||
import EventEmiter from '../../lib/methods/helpers/events';
|
import EventEmiter from '../../lib/methods/helpers/events';
|
||||||
|
@ -37,12 +33,13 @@ import {
|
||||||
MENTIONS_TRACKING_TYPE_COMMANDS,
|
MENTIONS_TRACKING_TYPE_COMMANDS,
|
||||||
MENTIONS_TRACKING_TYPE_EMOJIS,
|
MENTIONS_TRACKING_TYPE_EMOJIS,
|
||||||
MENTIONS_TRACKING_TYPE_ROOMS,
|
MENTIONS_TRACKING_TYPE_ROOMS,
|
||||||
MENTIONS_TRACKING_TYPE_USERS
|
MENTIONS_TRACKING_TYPE_USERS,
|
||||||
|
TIMEOUT_CLOSE_EMOJI
|
||||||
} from './constants';
|
} from './constants';
|
||||||
import CommandsPreview from './CommandsPreview';
|
import CommandsPreview from './CommandsPreview';
|
||||||
import { getUserSelector } from '../../selectors/login';
|
import { getUserSelector } from '../../selectors/login';
|
||||||
import Navigation from '../../lib/navigation/appNavigation';
|
import Navigation from '../../lib/navigation/appNavigation';
|
||||||
import { withActionSheet } from '../ActionSheet';
|
import { TActionSheetOptionsItem, withActionSheet } from '../ActionSheet';
|
||||||
import { sanitizeLikeString } from '../../lib/database/utils';
|
import { sanitizeLikeString } from '../../lib/database/utils';
|
||||||
import { CustomIcon } from '../CustomIcon';
|
import { CustomIcon } from '../CustomIcon';
|
||||||
import { forceJpgExtension } from './forceJpgExtension';
|
import { forceJpgExtension } from './forceJpgExtension';
|
||||||
|
@ -58,14 +55,12 @@ import {
|
||||||
} from '../../definitions';
|
} from '../../definitions';
|
||||||
import { MasterDetailInsideStackParamList } from '../../stacks/MasterDetailStack/types';
|
import { MasterDetailInsideStackParamList } from '../../stacks/MasterDetailStack/types';
|
||||||
import { getPermalinkMessage, search, sendFileMessage } from '../../lib/methods';
|
import { getPermalinkMessage, search, sendFileMessage } from '../../lib/methods';
|
||||||
import { hasPermission, debounce, isAndroid, isTablet } from '../../lib/methods/helpers';
|
import { hasPermission, debounce, isAndroid, isIOS, isTablet } from '../../lib/methods/helpers';
|
||||||
import { Services } from '../../lib/services';
|
import { Services } from '../../lib/services';
|
||||||
import { TSupportedThemes } from '../../theme';
|
import { TSupportedThemes } from '../../theme';
|
||||||
import { ChatsStackParamList } from '../../stacks/types';
|
import { ChatsStackParamList } from '../../stacks/types';
|
||||||
|
|
||||||
if (isAndroid) {
|
require('./EmojiKeyboard');
|
||||||
require('./EmojiKeyboard');
|
|
||||||
}
|
|
||||||
|
|
||||||
const imagePickerConfig = {
|
const imagePickerConfig = {
|
||||||
cropping: true,
|
cropping: true,
|
||||||
|
@ -270,6 +265,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
}, 500);
|
}, 500);
|
||||||
});
|
});
|
||||||
this.unsubscribeBlur = navigation.addListener('blur', () => {
|
this.unsubscribeBlur = navigation.addListener('blur', () => {
|
||||||
|
this.closeEmoji();
|
||||||
this.component?.blur();
|
this.component?.blur();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -330,6 +326,9 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
if (nextProps.theme !== theme) {
|
if (nextProps.theme !== theme) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (nextState.showEmojiKeyboard !== showEmojiKeyboard) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (!isFocused()) {
|
if (!isFocused()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -342,9 +341,6 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
if (nextProps.editing !== editing) {
|
if (nextProps.editing !== editing) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (nextState.showEmojiKeyboard !== showEmojiKeyboard) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (nextState.trackingType !== trackingType) {
|
if (nextState.trackingType !== trackingType) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -809,7 +805,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
const { permissionToUpload } = this.state;
|
const { permissionToUpload } = this.state;
|
||||||
const { showActionSheet, goToCannedResponses } = this.props;
|
const { showActionSheet, goToCannedResponses } = this.props;
|
||||||
|
|
||||||
const options = [];
|
const options: TActionSheetOptionsItem[] = [];
|
||||||
if (goToCannedResponses) {
|
if (goToCannedResponses) {
|
||||||
options.push({
|
options.push({
|
||||||
title: I18n.t('Canned_Responses'),
|
title: I18n.t('Canned_Responses'),
|
||||||
|
@ -847,7 +843,8 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
icon: 'discussions',
|
icon: 'discussions',
|
||||||
onPress: this.createDiscussion
|
onPress: this.createDiscussion
|
||||||
});
|
});
|
||||||
showActionSheet({ options });
|
|
||||||
|
this.closeEmojiAndAction(showActionSheet, { options });
|
||||||
};
|
};
|
||||||
|
|
||||||
editCancel = () => {
|
editCancel = () => {
|
||||||
|
@ -883,6 +880,13 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
this.setState({ showEmojiKeyboard: false });
|
this.setState({ showEmojiKeyboard: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
closeEmojiAndAction = (action?: Function, params?: any) => {
|
||||||
|
const { showEmojiKeyboard } = this.state;
|
||||||
|
|
||||||
|
this.closeEmoji();
|
||||||
|
setTimeout(() => action && action(params), showEmojiKeyboard && isIOS ? TIMEOUT_CLOSE_EMOJI : null);
|
||||||
|
};
|
||||||
|
|
||||||
submit = async () => {
|
submit = async () => {
|
||||||
const { tshow } = this.state;
|
const { tshow } = this.state;
|
||||||
const { onSubmit, rid: roomId, tmid, showSend, sharing } = this.props;
|
const { onSubmit, rid: roomId, tmid, showSend, sharing } = this.props;
|
||||||
|
@ -1089,6 +1093,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
recordingCallback={this.recordingCallback}
|
recordingCallback={this.recordingCallback}
|
||||||
onFinish={this.finishAudioMessage}
|
onFinish={this.finishAudioMessage}
|
||||||
permissionToUpload={permissionToUpload}
|
permissionToUpload={permissionToUpload}
|
||||||
|
onStart={this.closeEmoji}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1112,14 +1117,11 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
const textInputAndButtons = !recording ? (
|
const textInputAndButtons = !recording ? (
|
||||||
<>
|
<>
|
||||||
<LeftButtons
|
<LeftButtons
|
||||||
theme={theme}
|
|
||||||
showEmojiKeyboard={showEmojiKeyboard}
|
showEmojiKeyboard={showEmojiKeyboard}
|
||||||
editing={editing}
|
editing={editing}
|
||||||
showMessageBoxActions={this.showMessageBoxActions}
|
|
||||||
editCancel={this.editCancel}
|
editCancel={this.editCancel}
|
||||||
openEmoji={this.openEmoji}
|
openEmoji={this.openEmoji}
|
||||||
closeEmoji={this.closeEmoji}
|
closeEmoji={this.closeEmoji}
|
||||||
isActionsEnabled={isActionsEnabled}
|
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
ref={component => (this.component = component)}
|
ref={component => (this.component = component)}
|
||||||
|
@ -1138,7 +1140,6 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
{...isAndroidTablet}
|
{...isAndroidTablet}
|
||||||
/>
|
/>
|
||||||
<RightButtons
|
<RightButtons
|
||||||
theme={theme}
|
|
||||||
showSend={showSend}
|
showSend={showSend}
|
||||||
submit={this.submit}
|
submit={this.submit}
|
||||||
showMessageBoxActions={this.showMessageBoxActions}
|
showMessageBoxActions={this.showMessageBoxActions}
|
||||||
|
@ -1187,6 +1188,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
renderContent={this.renderContent}
|
renderContent={this.renderContent}
|
||||||
kbInputRef={this.component}
|
kbInputRef={this.component}
|
||||||
kbComponent={showEmojiKeyboard ? 'EmojiKeyboard' : null}
|
kbComponent={showEmojiKeyboard ? 'EmojiKeyboard' : null}
|
||||||
|
kbInitialProps={{ theme }}
|
||||||
onKeyboardResigned={this.onKeyboardResigned}
|
onKeyboardResigned={this.onKeyboardResigned}
|
||||||
onItemSelected={this.onEmojiSelected}
|
onItemSelected={this.onEmojiSelected}
|
||||||
trackInteractive
|
trackInteractive
|
||||||
|
|
|
@ -58,6 +58,7 @@ interface IMessageContainerProps {
|
||||||
jumpToMessage?: (link: string) => void;
|
jumpToMessage?: (link: string) => void;
|
||||||
onPress?: () => void;
|
onPress?: () => void;
|
||||||
theme: TSupportedThemes;
|
theme: TSupportedThemes;
|
||||||
|
closeEmojiAndAction?: (action?: Function, params?: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IMessageContainerState {
|
interface IMessageContainerState {
|
||||||
|
@ -114,6 +115,14 @@ class MessageContainer extends React.Component<IMessageContainerProps, IMessageC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closeEmojiAndAction = () => {
|
||||||
|
const { closeEmojiAndAction } = this.props;
|
||||||
|
|
||||||
|
if (closeEmojiAndAction) {
|
||||||
|
closeEmojiAndAction(this.onPress);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
onPress = debounce(
|
onPress = debounce(
|
||||||
() => {
|
() => {
|
||||||
const { onPress } = this.props;
|
const { onPress } = this.props;
|
||||||
|
@ -373,7 +382,7 @@ class MessageContainer extends React.Component<IMessageContainerProps, IMessageC
|
||||||
value={{
|
value={{
|
||||||
user,
|
user,
|
||||||
baseUrl,
|
baseUrl,
|
||||||
onPress: this.onPress,
|
onPress: this.closeEmojiAndAction,
|
||||||
onLongPress: this.onLongPress,
|
onLongPress: this.onLongPress,
|
||||||
reactionInit: this.reactionInit,
|
reactionInit: this.reactionInit,
|
||||||
onErrorPress: this.onErrorPress,
|
onErrorPress: this.onErrorPress,
|
||||||
|
|
|
@ -14,7 +14,6 @@ const margin = isAndroid ? 40 : 20;
|
||||||
const maxSize = 400;
|
const maxSize = 400;
|
||||||
|
|
||||||
interface IReactionPickerProps {
|
interface IReactionPickerProps {
|
||||||
baseUrl: string;
|
|
||||||
message?: any;
|
message?: any;
|
||||||
show: boolean;
|
show: boolean;
|
||||||
isMasterDetail: boolean;
|
isMasterDetail: boolean;
|
||||||
|
@ -42,7 +41,7 @@ class ReactionPicker extends React.Component<IReactionPickerProps> {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { width, height, show, baseUrl, reactionClose, isMasterDetail, theme } = this.props;
|
const { width, height, show, reactionClose, isMasterDetail, theme } = this.props;
|
||||||
|
|
||||||
let widthStyle = width - margin;
|
let widthStyle = width - margin;
|
||||||
let heightStyle = Math.min(width, height) - margin * 2;
|
let heightStyle = Math.min(width, height) - margin * 2;
|
||||||
|
@ -70,7 +69,7 @@ class ReactionPicker extends React.Component<IReactionPickerProps> {
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
testID='reaction-picker'>
|
testID='reaction-picker'>
|
||||||
<EmojiPicker theme={theme} onEmojiSelected={this.onEmojiSelected} baseUrl={baseUrl} />
|
<EmojiPicker theme={theme} onEmojiSelected={this.onEmojiSelected} />
|
||||||
</View>
|
</View>
|
||||||
</Modal>
|
</Modal>
|
||||||
) : null;
|
) : null;
|
||||||
|
@ -78,7 +77,6 @@ class ReactionPicker extends React.Component<IReactionPickerProps> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: IApplicationState) => ({
|
const mapStateToProps = (state: IApplicationState) => ({
|
||||||
baseUrl: state.server.server,
|
|
||||||
isMasterDetail: state.app.isMasterDetail
|
isMasterDetail: state.app.isMasterDetail
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { events, logEvent } from '../../lib/methods/helpers/log';
|
||||||
import { isTeamRoom } from '../../lib/methods/helpers/room';
|
import { isTeamRoom } from '../../lib/methods/helpers/room';
|
||||||
import { IApplicationState, SubscriptionType, TMessageModel, TSubscriptionModel } from '../../definitions';
|
import { IApplicationState, SubscriptionType, TMessageModel, TSubscriptionModel } from '../../definitions';
|
||||||
import { ChatsStackParamList } from '../../stacks/types';
|
import { ChatsStackParamList } from '../../stacks/types';
|
||||||
import { IActionSheetProvider, TActionSheetOptionsItem, withActionSheet } from '../../containers/ActionSheet';
|
import { TActionSheetOptionsItem } from '../../containers/ActionSheet';
|
||||||
import i18n from '../../i18n';
|
import i18n from '../../i18n';
|
||||||
import { showConfirmationAlert, showErrorAlert } from '../../lib/methods/helpers';
|
import { showConfirmationAlert, showErrorAlert } from '../../lib/methods/helpers';
|
||||||
import { onHoldLivechat, returnLivechat } from '../../lib/services/restApi';
|
import { onHoldLivechat, returnLivechat } from '../../lib/services/restApi';
|
||||||
|
@ -21,10 +21,10 @@ import { closeLivechat as closeLivechatService } from '../../lib/methods/helpers
|
||||||
import { Services } from '../../lib/services';
|
import { Services } from '../../lib/services';
|
||||||
import { ILivechatDepartment } from '../../definitions/ILivechatDepartment';
|
import { ILivechatDepartment } from '../../definitions/ILivechatDepartment';
|
||||||
|
|
||||||
interface IRightButtonsProps extends IActionSheetProvider {
|
interface IRightButtonsProps {
|
||||||
userId?: string;
|
userId?: string;
|
||||||
threadsEnabled: boolean;
|
threadsEnabled: boolean;
|
||||||
rid: string;
|
rid?: string;
|
||||||
t: string;
|
t: string;
|
||||||
tmid?: string;
|
tmid?: string;
|
||||||
teamId?: string;
|
teamId?: string;
|
||||||
|
@ -34,7 +34,6 @@ interface IRightButtonsProps extends IActionSheetProvider {
|
||||||
status?: string;
|
status?: string;
|
||||||
dispatch: Dispatch;
|
dispatch: Dispatch;
|
||||||
encrypted?: boolean;
|
encrypted?: boolean;
|
||||||
transferLivechatGuestPermission: boolean;
|
|
||||||
navigation: StackNavigationProp<ChatsStackParamList, 'RoomView'>;
|
navigation: StackNavigationProp<ChatsStackParamList, 'RoomView'>;
|
||||||
omnichannelPermissions: {
|
omnichannelPermissions: {
|
||||||
canForwardGuest: boolean;
|
canForwardGuest: boolean;
|
||||||
|
@ -42,6 +41,7 @@ interface IRightButtonsProps extends IActionSheetProvider {
|
||||||
canPlaceLivechatOnHold: boolean;
|
canPlaceLivechatOnHold: boolean;
|
||||||
};
|
};
|
||||||
livechatRequestComment: boolean;
|
livechatRequestComment: boolean;
|
||||||
|
showActionSheet: Function;
|
||||||
departmentId?: string;
|
departmentId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,34 +187,38 @@ class RightButtonsContainer extends Component<IRightButtonsProps, IRigthButtonsS
|
||||||
|
|
||||||
returnLivechat = () => {
|
returnLivechat = () => {
|
||||||
const { rid } = this.props;
|
const { rid } = this.props;
|
||||||
showConfirmationAlert({
|
if (rid) {
|
||||||
message: i18n.t('Would_you_like_to_return_the_inquiry'),
|
showConfirmationAlert({
|
||||||
confirmationText: i18n.t('Yes'),
|
message: i18n.t('Would_you_like_to_return_the_inquiry'),
|
||||||
onPress: async () => {
|
confirmationText: i18n.t('Yes'),
|
||||||
try {
|
onPress: async () => {
|
||||||
await returnLivechat(rid);
|
try {
|
||||||
} catch (e: any) {
|
await returnLivechat(rid);
|
||||||
showErrorAlert(e.reason, i18n.t('Oops'));
|
} catch (e: any) {
|
||||||
|
showErrorAlert(e.reason, i18n.t('Oops'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
placeOnHoldLivechat = () => {
|
placeOnHoldLivechat = () => {
|
||||||
const { navigation, rid } = this.props;
|
const { navigation, rid } = this.props;
|
||||||
showConfirmationAlert({
|
if (rid) {
|
||||||
title: i18n.t('Are_you_sure_question_mark'),
|
showConfirmationAlert({
|
||||||
message: i18n.t('Would_like_to_place_on_hold'),
|
title: i18n.t('Are_you_sure_question_mark'),
|
||||||
confirmationText: i18n.t('Yes'),
|
message: i18n.t('Would_like_to_place_on_hold'),
|
||||||
onPress: async () => {
|
confirmationText: i18n.t('Yes'),
|
||||||
try {
|
onPress: async () => {
|
||||||
await onHoldLivechat(rid);
|
try {
|
||||||
navigation.navigate('RoomsListView');
|
await onHoldLivechat(rid);
|
||||||
} catch (e: any) {
|
navigation.navigate('RoomsListView');
|
||||||
showErrorAlert(e.data?.error, i18n.t('Oops'));
|
} catch (e: any) {
|
||||||
|
showErrorAlert(e.data?.error, i18n.t('Oops'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
closeLivechat = async () => {
|
closeLivechat = async () => {
|
||||||
|
@ -234,18 +238,20 @@ class RightButtonsContainer extends Component<IRightButtonsProps, IRigthButtonsS
|
||||||
tagsList = await Services.getTagsList();
|
tagsList = await Services.getTagsList();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!livechatRequestComment && !departmentInfo?.requestTagBeforeClosingChat) {
|
if (rid) {
|
||||||
const comment = i18n.t('Chat_closed_by_agent');
|
if (!livechatRequestComment && !departmentInfo?.requestTagBeforeClosingChat) {
|
||||||
return closeLivechatService({ rid, isMasterDetail, comment });
|
const comment = i18n.t('Chat_closed_by_agent');
|
||||||
}
|
return closeLivechatService({ rid, isMasterDetail, comment });
|
||||||
|
}
|
||||||
|
|
||||||
if (isMasterDetail) {
|
if (isMasterDetail) {
|
||||||
navigation.navigate('ModalStackNavigator', {
|
navigation.navigate('ModalStackNavigator', {
|
||||||
screen: 'CloseLivechatView',
|
screen: 'CloseLivechatView',
|
||||||
params: { rid, departmentId, departmentInfo, tagsList }
|
params: { rid, departmentId, departmentInfo, tagsList }
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
navigation.navigate('CloseLivechatView', { rid, departmentId, departmentInfo, tagsList });
|
navigation.navigate('CloseLivechatView', { rid, departmentId, departmentInfo, tagsList });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -267,13 +273,15 @@ class RightButtonsContainer extends Component<IRightButtonsProps, IRigthButtonsS
|
||||||
title: i18n.t('Forward_Chat'),
|
title: i18n.t('Forward_Chat'),
|
||||||
icon: 'chat-forward',
|
icon: 'chat-forward',
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
if (isMasterDetail) {
|
if (rid) {
|
||||||
navigation.navigate('ModalStackNavigator', {
|
if (isMasterDetail) {
|
||||||
screen: 'ForwardLivechatView',
|
navigation.navigate('ModalStackNavigator', {
|
||||||
params: { rid }
|
screen: 'ForwardLivechatView',
|
||||||
});
|
params: { rid }
|
||||||
} else {
|
});
|
||||||
navigation.navigate('ForwardLivechatView', { rid });
|
} else {
|
||||||
|
navigation.navigate('ForwardLivechatView', { rid });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -379,4 +387,4 @@ const mapStateToProps = (state: IApplicationState) => ({
|
||||||
livechatRequestComment: state.settings.Livechat_request_comment_when_closing_conversation as boolean
|
livechatRequestComment: state.settings.Livechat_request_comment_when_closing_conversation as boolean
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps)(withActionSheet(RightButtonsContainer));
|
export default connect(mapStateToProps)(RightButtonsContainer);
|
||||||
|
|
|
@ -99,7 +99,7 @@ import {
|
||||||
hasPermission
|
hasPermission
|
||||||
} from '../../lib/methods/helpers';
|
} from '../../lib/methods/helpers';
|
||||||
import { Services } from '../../lib/services';
|
import { Services } from '../../lib/services';
|
||||||
import { withActionSheet, TActionSheetOptions } from '../../containers/ActionSheet';
|
import { withActionSheet, IActionSheetProvider } from '../../containers/ActionSheet';
|
||||||
|
|
||||||
type TStateAttrsUpdate = keyof IRoomViewState;
|
type TStateAttrsUpdate = keyof IRoomViewState;
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ const roomAttrsUpdate = [
|
||||||
't'
|
't'
|
||||||
] as TRoomUpdate[];
|
] as TRoomUpdate[];
|
||||||
|
|
||||||
interface IRoomViewProps extends IBaseScreen<ChatsStackParamList, 'RoomView'> {
|
interface IRoomViewProps extends IActionSheetProvider, IBaseScreen<ChatsStackParamList, 'RoomView'> {
|
||||||
user: Pick<ILoggedUser, 'id' | 'username' | 'token' | 'showMessageInMainThread'>;
|
user: Pick<ILoggedUser, 'id' | 'username' | 'token' | 'showMessageInMainThread'>;
|
||||||
appState: string;
|
appState: string;
|
||||||
useRealName?: boolean;
|
useRealName?: boolean;
|
||||||
|
@ -170,7 +170,6 @@ interface IRoomViewProps extends IBaseScreen<ChatsStackParamList, 'RoomView'> {
|
||||||
transferLivechatGuestPermission?: string[]; // TODO: Check if its the correct type
|
transferLivechatGuestPermission?: string[]; // TODO: Check if its the correct type
|
||||||
viewCannedResponsesPermission?: string[]; // TODO: Check if its the correct type
|
viewCannedResponsesPermission?: string[]; // TODO: Check if its the correct type
|
||||||
livechatAllowManualOnHold?: boolean;
|
livechatAllowManualOnHold?: boolean;
|
||||||
showActionSheet: (options: TActionSheetOptions) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IRoomViewState {
|
interface IRoomViewState {
|
||||||
|
@ -185,7 +184,7 @@ interface IRoomViewState {
|
||||||
fname?: string;
|
fname?: string;
|
||||||
prid?: string;
|
prid?: string;
|
||||||
joinCodeRequired?: boolean;
|
joinCodeRequired?: boolean;
|
||||||
status?: boolean;
|
status?: string;
|
||||||
lastMessage?: ILastMessage;
|
lastMessage?: ILastMessage;
|
||||||
sysMes?: boolean;
|
sysMes?: boolean;
|
||||||
onHold?: boolean;
|
onHold?: boolean;
|
||||||
|
@ -635,6 +634,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
encrypted={encrypted}
|
encrypted={encrypted}
|
||||||
navigation={navigation}
|
navigation={navigation}
|
||||||
toggleFollowThread={this.toggleFollowThread}
|
toggleFollowThread={this.toggleFollowThread}
|
||||||
|
showActionSheet={this.showActionSheet}
|
||||||
departmentId={departmentId}
|
departmentId={departmentId}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -785,7 +785,12 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
errorActionsShow = (message: TAnyMessageModel) => {
|
errorActionsShow = (message: TAnyMessageModel) => {
|
||||||
this.messageErrorActions?.showMessageErrorActions(message);
|
this.messagebox?.current?.closeEmojiAndAction(this.messageErrorActions?.showMessageErrorActions, message);
|
||||||
|
};
|
||||||
|
|
||||||
|
showActionSheet = (options: any) => {
|
||||||
|
const { showActionSheet } = this.props;
|
||||||
|
this.messagebox?.current?.closeEmojiAndAction(showActionSheet, options);
|
||||||
};
|
};
|
||||||
|
|
||||||
onEditInit = (message: TAnyMessageModel) => {
|
onEditInit = (message: TAnyMessageModel) => {
|
||||||
|
@ -834,7 +839,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
onMessageLongPress = (message: TAnyMessageModel) => {
|
onMessageLongPress = (message: TAnyMessageModel) => {
|
||||||
this.messageActions?.showMessageActions(message);
|
this.messagebox?.current?.closeEmojiAndAction(this.messageActions?.showMessageActions, message);
|
||||||
};
|
};
|
||||||
|
|
||||||
showAttachment = (attachment: IAttachment) => {
|
showAttachment = (attachment: IAttachment) => {
|
||||||
|
@ -857,7 +862,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
this.setState({ selectedMessage: message });
|
this.setState({ selectedMessage: message });
|
||||||
const { showActionSheet, baseUrl, width } = this.props;
|
const { showActionSheet, baseUrl, width } = this.props;
|
||||||
const { selectedMessage } = this.state;
|
const { selectedMessage } = this.state;
|
||||||
showActionSheet({
|
this.messagebox?.current?.closeEmojiAndAction(showActionSheet, {
|
||||||
children: (
|
children: (
|
||||||
<ReactionsList
|
<ReactionsList
|
||||||
reactions={selectedMessage?.reactions}
|
reactions={selectedMessage?.reactions}
|
||||||
|
@ -1346,6 +1351,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
jumpToMessage={this.jumpToMessageByUrl}
|
jumpToMessage={this.jumpToMessageByUrl}
|
||||||
highlighted={highlightedMessage === item.id}
|
highlighted={highlightedMessage === item.id}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
|
closeEmojiAndAction={this.messagebox?.current?.closeEmojiAndAction}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@
|
||||||
"react-native-simple-crypto": "RocketChat/react-native-simple-crypto#0.5.0",
|
"react-native-simple-crypto": "RocketChat/react-native-simple-crypto#0.5.0",
|
||||||
"react-native-slowlog": "^1.0.2",
|
"react-native-slowlog": "^1.0.2",
|
||||||
"react-native-svg": "^12.3.0",
|
"react-native-svg": "^12.3.0",
|
||||||
"react-native-ui-lib": "RocketChat/react-native-ui-lib#minor-improvements",
|
"react-native-ui-lib": "RocketChat/react-native-ui-lib",
|
||||||
"react-native-unimodules": "^0.14.8",
|
"react-native-unimodules": "^0.14.8",
|
||||||
"react-native-vector-icons": "9.1.0",
|
"react-native-vector-icons": "9.1.0",
|
||||||
"react-native-webview": "10.3.2",
|
"react-native-webview": "10.3.2",
|
||||||
|
|
|
@ -15491,9 +15491,9 @@ react-native-text-size@4.0.0-rc.1:
|
||||||
resolved "https://registry.yarnpkg.com/react-native-text-size/-/react-native-text-size-4.0.0-rc.1.tgz#1e048d345dd6a5a8e1269e0585c1a5948c478da5"
|
resolved "https://registry.yarnpkg.com/react-native-text-size/-/react-native-text-size-4.0.0-rc.1.tgz#1e048d345dd6a5a8e1269e0585c1a5948c478da5"
|
||||||
integrity sha512-CysqjU2jK6Yc+a+kEI222pUyTY2ywcU2HqbFqf1KHymW6OPTdvBBHqbEJKL0QiLhQaFYDbqicM+h990s9TP00g==
|
integrity sha512-CysqjU2jK6Yc+a+kEI222pUyTY2ywcU2HqbFqf1KHymW6OPTdvBBHqbEJKL0QiLhQaFYDbqicM+h990s9TP00g==
|
||||||
|
|
||||||
react-native-ui-lib@RocketChat/react-native-ui-lib#minor-improvements:
|
react-native-ui-lib@RocketChat/react-native-ui-lib:
|
||||||
version "4.2.1"
|
version "4.2.0"
|
||||||
resolved "https://codeload.github.com/RocketChat/react-native-ui-lib/tar.gz/a80f38aaa947849736ce8643253991cdcb639414"
|
resolved "https://codeload.github.com/RocketChat/react-native-ui-lib/tar.gz/d20c1bcd09b694fc5133fc2232fd510f5f4ba581"
|
||||||
dependencies:
|
dependencies:
|
||||||
babel-plugin-transform-inline-environment-variables "^0.0.2"
|
babel-plugin-transform-inline-environment-variables "^0.0.2"
|
||||||
color "^3.1.0"
|
color "^3.1.0"
|
||||||
|
|
Loading…
Reference in New Issue