Skip to content

Commit 35775a8

Browse files
author
Vir Desai
committed
CRNS-107: decoupled action sheet from message input
1 parent 2385db7 commit 35775a8

File tree

5 files changed

+125
-80
lines changed

5 files changed

+125
-80
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import React from 'react';
2+
import { ActionSheetCustom } from 'react-native-actionsheet';
3+
import styled from '@stream-io/styled-components';
4+
5+
import { IconSquare } from '../IconSquare';
6+
7+
import { withTranslationContext } from '../../context';
8+
9+
import iconGallery from '../../images/icons/icon_attach-media.png';
10+
import iconClose from '../../images/icons/icon_close.png';
11+
import iconFolder from '../../images/icons/icon_folder.png';
12+
13+
const ActionSheetButtonContainer = styled.View`
14+
align-items: center;
15+
flex-direction: row;
16+
justify-content: flex-start;
17+
padding-left: 20px;
18+
width: 100%;
19+
${({ theme }) => theme.messageInput.actionSheet.buttonContainer.css};
20+
`;
21+
22+
const ActionSheetButtonText = styled.Text`
23+
${({ theme }) => theme.messageInput.actionSheet.buttonText.css};
24+
`;
25+
26+
const ActionSheetTitleContainer = styled.View`
27+
align-items: center;
28+
flex-direction: row;
29+
height: 100%;
30+
justify-content: space-between;
31+
padding-left: 20px;
32+
padding-right: 20px;
33+
width: 100%;
34+
${({ theme }) => theme.messageInput.actionSheet.titleContainer.css};
35+
`;
36+
37+
const ActionSheetTitleText = styled.Text`
38+
font-weight: bold;
39+
${({ theme }) => theme.messageInput.actionSheet.titleText.css};
40+
`;
41+
42+
const ActionSheet = ({
43+
closeAttachActionSheet,
44+
pickFile,
45+
pickImage,
46+
setInputBoxRef,
47+
styles,
48+
t,
49+
}) => (
50+
<ActionSheetCustom
51+
ref={setInputBoxRef}
52+
title={
53+
<ActionSheetTitleContainer>
54+
<ActionSheetTitleText>{t('Add a file')}</ActionSheetTitleText>
55+
<IconSquare icon={iconClose} onPress={closeAttachActionSheet} />
56+
</ActionSheetTitleContainer>
57+
}
58+
options={[
59+
/* eslint-disable */
60+
<AttachmentActionSheetItem
61+
icon={iconGallery}
62+
text={t('Upload a photo')}
63+
/>,
64+
<AttachmentActionSheetItem icon={iconFolder} text={t('Upload a file')} />,
65+
/* eslint-enable */
66+
]}
67+
onPress={(index) => {
68+
// https://github.com/beefe/react-native-actionsheet/issues/36
69+
setTimeout(() => {
70+
switch (index) {
71+
case 0:
72+
pickImage();
73+
break;
74+
case 1:
75+
pickFile();
76+
break;
77+
default:
78+
}
79+
}, 201); // 201ms to fire after the animation is complete https://github.com/beefe/react-native-actionsheet/blob/master/lib/ActionSheetCustom.js#L78
80+
}}
81+
styles={styles}
82+
/>
83+
);
84+
85+
const AttachmentActionSheetItem = ({ icon, text }) => (
86+
<ActionSheetButtonContainer>
87+
<IconSquare icon={icon} />
88+
<ActionSheetButtonText>{text}</ActionSheetButtonText>
89+
</ActionSheetButtonContainer>
90+
);
91+
92+
export default withTranslationContext(ActionSheet);

src/components/MessageInput/MessageInput.js

Lines changed: 18 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import Immutable from 'seamless-immutable';
55
import PropTypes from 'prop-types';
66
import uniq from 'lodash/uniq';
77
import styled from '@stream-io/styled-components';
8-
import { ActionSheetCustom as ActionSheet } from 'react-native-actionsheet';
98

109
import { logChatPromiseExecution } from 'stream-chat';
1110

@@ -21,14 +20,13 @@ import { pickImage, pickDocument } from '../../native';
2120
import { FileState, ACITriggerSettings } from '../../utils';
2221
import { themed } from '../../styles/theme';
2322

23+
import ActionSheet from './ActionSheet';
2424
import SendButton from './SendButton';
2525
import AttachButton from './AttachButton';
2626
import ImageUploadPreview from './ImageUploadPreview';
2727
import FileUploadPreview from './FileUploadPreview';
2828
import { AutoCompleteInput } from '../AutoCompleteInput';
2929

30-
import iconGallery from '../../images/icons/icon_attach-media.png';
31-
import iconFolder from '../../images/icons/icon_folder.png';
3230
import iconClose from '../../images/icons/icon_close.png';
3331

3432
// https://stackoverflow.com/a/6860916/2570866
@@ -87,35 +85,6 @@ const InputBoxContainer = styled.View`
8785
${({ theme }) => theme.messageInput.inputBoxContainer.css}
8886
`;
8987

90-
const ActionSheetTitleContainer = styled.View`
91-
flex-direction: row;
92-
justify-content: space-between;
93-
align-items: center;
94-
width: 100%;
95-
height: 100%;
96-
padding-left: 20;
97-
padding-right: 20;
98-
${({ theme }) => theme.messageInput.actionSheet.titleContainer.css};
99-
`;
100-
101-
const ActionSheetTitleText = styled.Text`
102-
font-weight: bold;
103-
${({ theme }) => theme.messageInput.actionSheet.titleText.css};
104-
`;
105-
106-
const ActionSheetButtonContainer = styled.View`
107-
flex-direction: row;
108-
align-items: center;
109-
justify-content: flex-start;
110-
width: 100%;
111-
padding-left: 20;
112-
${({ theme }) => theme.messageInput.actionSheet.buttonContainer.css};
113-
`;
114-
115-
const ActionSheetButtonText = styled.Text`
116-
${({ theme }) => theme.messageInput.actionSheet.buttonText.css};
117-
`;
118-
11988
/**
12089
* UI Component for message input
12190
* Its a consumer of [Channel Context](https://getstream.github.io/stream-chat-react-native/#channelcontext)
@@ -210,6 +179,12 @@ class MessageInput extends PureComponent {
210179
* Defaults to and accepts same props as: [AttachButton](https://getstream.github.io/stream-chat-react-native/#attachbutton)
211180
* */
212181
AttachButton: PropTypes.oneOfType([PropTypes.node, PropTypes.elementType]),
182+
/**
183+
* Custom UI component for ActionSheet.
184+
*
185+
* Defaults to and accepts same props as: [ActionSheet](https://getstream.github.io/stream-chat-react-native/#actionsheet)
186+
* */
187+
ActionSheet: PropTypes.oneOfType([PropTypes.node, PropTypes.elementType]),
213188
/**
214189
* Additional props for underlying TextInput component. These props will be forwarded as it is to TextInput component.
215190
*
@@ -238,12 +213,13 @@ class MessageInput extends PureComponent {
238213
};
239214

240215
static defaultProps = {
241-
hasImagePicker: true,
242-
hasFilePicker: true,
216+
ActionSheet,
217+
AttachButton,
243218
disabled: false,
244-
sendImageAsync: false,
219+
hasFilePicker: true,
220+
hasImagePicker: true,
245221
SendButton,
246-
AttachButton,
222+
sendImageAsync: false,
247223
};
248224

249225
getMessageDetailsForState = (message, initialValue) => {
@@ -840,7 +816,8 @@ class MessageInput extends PureComponent {
840816
text: this.state.text + text,
841817
});
842818
};
843-
setInputBoxRef = (o) => (this.inputBox = o);
819+
820+
setInputBoxRef = (o) => (this.attachActionSheet = o);
844821

845822
closeAttachActionSheet = () => {
846823
this.attachActionSheet.hide();
@@ -893,42 +870,10 @@ class MessageInput extends PureComponent {
893870
*/}
894871

895872
<ActionSheet
896-
ref={(o) => (this.attachActionSheet = o)}
897-
title={
898-
<ActionSheetTitleContainer>
899-
<ActionSheetTitleText>{t('Add a file')}</ActionSheetTitleText>
900-
<IconSquare
901-
icon={iconClose}
902-
onPress={this.closeAttachActionSheet}
903-
/>
904-
</ActionSheetTitleContainer>
905-
}
906-
options={[
907-
/* eslint-disable */
908-
<AttachmentActionSheetItem
909-
icon={iconGallery}
910-
text={t('Upload a photo')}
911-
/>,
912-
<AttachmentActionSheetItem
913-
icon={iconFolder}
914-
text={t('Upload a file')}
915-
/>,
916-
/* eslint-enable */
917-
]}
918-
onPress={(index) => {
919-
// https://github.com/beefe/react-native-actionsheet/issues/36
920-
setTimeout(() => {
921-
switch (index) {
922-
case 0:
923-
this._pickImage();
924-
break;
925-
case 1:
926-
this._pickFile();
927-
break;
928-
default:
929-
}
930-
}, 201); // 201ms to fire after the animation is complete https://github.com/beefe/react-native-actionsheet/blob/master/lib/ActionSheetCustom.js#L78
931-
}}
873+
setAttachActionSheetRef={this.setInputBoxRef}
874+
closeAttachActionSheet={this.closeAttachActionSheet}
875+
pickFile={this._pickFile}
876+
pickImage={this._pickImage}
932877
styles={this.props.actionSheetStyles}
933878
/>
934879
<InputBoxContainer ref={this.props.setInputBoxContainerRef}>
@@ -1044,10 +989,3 @@ export default withTranslationContext(
1044989
withSuggestionsContext(withChannelContext(themed(MessageInput))),
1045990
),
1046991
);
1047-
1048-
const AttachmentActionSheetItem = ({ icon, text }) => (
1049-
<ActionSheetButtonContainer>
1050-
<IconSquare icon={icon} />
1051-
<ActionSheetButtonText>{text}</ActionSheetButtonText>
1052-
</ActionSheetButtonContainer>
1053-
);

src/components/MessageInput/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export { default as ActionSheet } from './ActionSheet';
12
export { default as AttachButton } from './AttachButton';
23
export { default as FileUploadPreview } from './FileUploadPreview';
34
export { default as ImageUploadPreview } from './ImageUploadPreview';

styleguide.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ module.exports = {
108108
'src/components/MessageInput/ImageUploadPreview.js',
109109
'src/components/MessageInput/FileUploadPreview.js',
110110
'src/components/MessageInput/SendButton.js',
111+
'src/components/MessageInput/ActionSheet.js',
111112
'src/components/MessageInput/AttachButton.js',
112113
'src/components/AutoCompleteInput/AutoCompleteInput.js',
113114
'src/components/AutoCompleteInput/CommandsItem.js',

types/index.d.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ export interface MessageInputProps
288288
actionSheetStyles?: object;
289289
AttachmentFileIcon?: React.ElementType<FileIconUIComponentProps>;
290290
AttachButton?: React.ElementType<AttachButtonProps>;
291+
ActionSheet?: React.ElementType<ActionSheetProps>;
291292
SendButton: React.ElementType<SendButtonProps>;
292293
additionalTextInputProps?: object;
293294
}
@@ -1152,6 +1153,17 @@ export interface AttachButtonProps extends StyledComponentProps {
11521153
handleOnPress(): void;
11531154
}
11541155

1156+
export interface ActionSheetProps extends StyledComponentProps {
1157+
/** Hides the attach actionsheet */
1158+
closeAttachActionSheet?(): void;
1159+
/** Handler for attach file functionality */
1160+
pickFile?(): void;
1161+
/** Handler for attach image functionality */
1162+
pickImage?(): Promise<void>;
1163+
/** object the ref via callback - https://reactjs.org/docs/refs-and-the-dom.html#callback-refs */
1164+
setAttachActionSheetRef?(ref: any): void;
1165+
}
1166+
11551167
export interface SendButtonProps extends StyledComponentProps {
11561168
title: string;
11571169
editing: Client.MessageResponse | boolean;
@@ -1258,6 +1270,7 @@ export class TypingIndicator extends React.PureComponent<
12581270
export class MessageInput extends React.PureComponent<MessageInputProps, any> {}
12591271

12601272
export class AttachButton extends React.PureComponent<AttachButtonProps, any> {}
1273+
export class ActionSheet extends React.PureComponent<ActionSheetProps, any> {}
12611274
export class SendButton extends React.PureComponent<SendButtonProps> {}
12621275
export class MessageSimple extends React.PureComponent<
12631276
MessageUIComponentProps,

0 commit comments

Comments
 (0)