Skip to content

Commit 59618ad

Browse files
Merge pull request #253 from virdesai/crns-107/decouple-actionsheet-from-message-input
CRNS-107: decoupled action sheet from message input
2 parents 3d71ea0 + d92850f commit 59618ad

File tree

6 files changed

+133
-82
lines changed

6 files changed

+133
-82
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: 22 additions & 81 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 ActionSheetAttachment from './ActionSheetAttachment';
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,15 @@ 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 ActionSheetAttachment.
184+
*
185+
* Defaults to and accepts same props as: [ActionSheetAttachment](https://getstream.github.io/stream-chat-react-native/#actionsheetattachment)
186+
* */
187+
ActionSheetAttachment: PropTypes.oneOfType([
188+
PropTypes.node,
189+
PropTypes.elementType,
190+
]),
213191
/**
214192
* Additional props for underlying TextInput component. These props will be forwarded as it is to TextInput component.
215193
*
@@ -238,12 +216,13 @@ class MessageInput extends PureComponent {
238216
};
239217

240218
static defaultProps = {
241-
hasImagePicker: true,
242-
hasFilePicker: true,
219+
ActionSheetAttachment,
220+
AttachButton,
243221
disabled: false,
244-
sendImageAsync: false,
222+
hasFilePicker: true,
223+
hasImagePicker: true,
245224
SendButton,
246-
AttachButton,
225+
sendImageAsync: false,
247226
};
248227

249228
getMessageDetailsForState = (message, initialValue) => {
@@ -840,7 +819,8 @@ class MessageInput extends PureComponent {
840819
text: this.state.text + text,
841820
});
842821
};
843-
setInputBoxRef = (o) => (this.inputBox = o);
822+
823+
setInputBoxRef = (o) => (this.attachActionSheet = o);
844824

845825
closeAttachActionSheet = () => {
846826
this.attachActionSheet.hide();
@@ -892,43 +872,11 @@ class MessageInput extends PureComponent {
892872
work well with async onPress operations. So find a solution.
893873
*/}
894874

895-
<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-
}}
875+
<ActionSheetAttachment
876+
setAttachActionSheetRef={this.setInputBoxRef}
877+
closeAttachActionSheet={this.closeAttachActionSheet}
878+
pickFile={this._pickFile}
879+
pickImage={this._pickImage}
932880
styles={this.props.actionSheetStyles}
933881
/>
934882
<InputBoxContainer ref={this.props.setInputBoxContainerRef}>
@@ -1044,10 +992,3 @@ export default withTranslationContext(
1044992
withSuggestionsContext(withChannelContext(themed(MessageInput))),
1045993
),
1046994
);
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 ActionSheetAttachment } from './ActionSheetAttachment';
12
export { default as AttachButton } from './AttachButton';
23
export { default as FileUploadPreview } from './FileUploadPreview';
34
export { default as ImageUploadPreview } from './ImageUploadPreview';

src/components/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from './Attachment';
2+
export * from './AutoCompleteInput';
23
export * from './Avatar';
34
export * from './Channel';
45
export * from './ChannelList';
@@ -9,7 +10,6 @@ export * from './Indicators';
910
export * from './KeyboardCompatibleView';
1011
export * from './Message';
1112
export * from './MessageInput';
12-
export * from './AutoCompleteInput';
1313
export * from './MessageList';
1414
export * from './Reaction';
1515
export * from './Spinner';

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/ActionSheetAttachment.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: 16 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+
ActionSheetAttachment?: React.ElementType<ActionSheetAttachmentProps>;
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 ActionSheetAttachmentProps 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,10 @@ 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 ActionSheetAttachment extends React.PureComponent<
1274+
ActionSheetAttachmentProps,
1275+
any
1276+
> {}
12611277
export class SendButton extends React.PureComponent<SendButtonProps> {}
12621278
export class MessageSimple extends React.PureComponent<
12631279
MessageUIComponentProps,

0 commit comments

Comments
 (0)