Instantly share code, notes, and snippets.
Created
April 9, 2020 08:30
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save kukiron/efcae2776e2b0add0c85cef60d9fa622 to your computer and use it in GitHub Desktop.
Component to show shared file list between users or in groups
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import flatten from 'lodash/flatten'; | |
import React, { Component } from 'react'; | |
import PropTypes from 'prop-types'; | |
import { connect } from 'react-redux'; | |
import { | |
StyleSheet, | |
FlatList, | |
SectionList, | |
TouchableOpacity, | |
ActivityIndicator, | |
} from 'react-native'; | |
import { | |
View, | |
Container, | |
Tab, | |
Tabs, | |
Text, | |
} from 'native-base'; | |
import { translateString } from 'yeppik-common/lib/i18n'; | |
import { H2 } from './translated'; | |
import { Media, Document } from '../conversation/conversation/attachment/PreviewInList'; | |
import dimensions from '../../common/dimensions'; | |
import { getFilesWithTimeLine } from '../../common/dates'; | |
import { getDownloadedAttachments, navigateToAttachment } from '../../common/attachments'; | |
import { playClicker } from '../../actions/sounds'; | |
import variables from '../../theme/variables/platform'; | |
const mediaDimension = dimensions.attachment.gallery.display; | |
const styles = StyleSheet.create({ | |
view: { | |
flex: 1, | |
justifyContent: 'center', | |
alignItems: 'center', | |
backgroundColor: '#FFFFFF', | |
}, | |
tabBarUnderline: { | |
height: 0, | |
}, | |
tab: { | |
backgroundColor: '#FFFFFF', | |
}, | |
text: { | |
color: '#00536C', | |
}, | |
activeTab: { | |
borderBottomColor: '#00536C', | |
borderBottomWidth: 2, | |
backgroundColor: '#F5F5F5', | |
}, | |
containerHeader: { | |
marginTop: 10, | |
marginBottom: 10, | |
marginLeft: 10, | |
}, | |
mediaContainer: { | |
margin: variables.sharedMediaGallery.margin, | |
marginTop: 0, | |
width: variables.deviceWidth, | |
paddingBottom: 30, | |
}, | |
documentContainer: { | |
paddingBottom: 30, | |
}, | |
mediaFile: { | |
borderWidth: 1, | |
borderColor: '#FFFFFF', | |
width: mediaDimension, | |
height: mediaDimension, | |
}, | |
textContainer: { | |
flex: 1, | |
justifyContent: 'center', | |
alignItems: 'center', | |
backgroundColor: '#FFFFFF', | |
}, | |
noContentText: { | |
textAlign: 'center', | |
color: '#00536C', | |
}, | |
}); | |
const isMediaFile = ({ category }) => ['image', 'video', 'audio'].includes(category); | |
const isDocument = ({ category }) => category === 'document'; | |
const renderMediaList = ({ | |
title, | |
isFetching, | |
attachments, | |
onAttachmentOpen, | |
}) => ( | |
<> | |
<Text style={[styles.text, styles.containerHeader]}>{title}</Text> | |
<FlatList | |
data={attachments} | |
numColumns={3} | |
keyExtractor={item => item.id} | |
renderItem={({ item: attachment }) => ( | |
<TouchableOpacity onPress={() => onAttachmentOpen(attachment)}> | |
<Media | |
attachment={attachment} | |
isFetching={isFetching} | |
style={styles.mediaFile} | |
/> | |
</TouchableOpacity> | |
)} | |
/> | |
</> | |
); | |
renderMediaList.propTypes = { | |
title: PropTypes.string.isRequired, | |
isFetching: PropTypes.bool.isRequired, | |
attachments: PropTypes.arrayOf(PropTypes.shape({})).isRequired, | |
onAttachmentOpen: PropTypes.func.isRequired, | |
}; | |
const renderDocumentList = ({ | |
locale, | |
title, | |
attachments, | |
onAttachmentOpen, | |
}) => ( | |
<> | |
<Text style={[styles.text, styles.containerHeader]}>{title}</Text> | |
<FlatList | |
data={attachments} | |
keyExtractor={item => item.id} | |
renderItem={({ item: attachment }) => ( | |
<Document | |
attachment={attachment} | |
locale={locale} | |
onPress={() => onAttachmentOpen(attachment)} | |
/> | |
)} | |
/> | |
</> | |
); | |
renderDocumentList.propTypes = { | |
locale: PropTypes.string.isRequired, | |
title: PropTypes.string.isRequired, | |
attachments: PropTypes.arrayOf(PropTypes.shape({})).isRequired, | |
onAttachmentOpen: PropTypes.func.isRequired, | |
}; | |
class SharedFileList extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
mediaFiles: [], | |
documents: [], | |
isFetching: false, | |
}; | |
this.handleOpenAttachment = this.handleOpenAttachment.bind(this); | |
} | |
async componentDidMount() { | |
this.setState({ isFetching: true }); | |
const { locale, messages } = this.props; | |
const attachments = await getDownloadedAttachments(messages); | |
const mediaFiles = getFilesWithTimeLine({ locale, files: attachments.filter(isMediaFile) }); | |
const documents = getFilesWithTimeLine({ locale, files: attachments.filter(isDocument) }); | |
this.setState({ | |
mediaFiles, | |
documents, | |
isFetching: false, | |
}); | |
} | |
async handleOpenAttachment(attachment) { | |
const { locale, handlePlayClicker } = this.props; | |
const { user, createdDate: createdAt } = attachment; | |
handlePlayClicker(); | |
await navigateToAttachment({ | |
locale, | |
attachment, | |
headerDetails: { createdAt, user }, | |
}); | |
} | |
render() { | |
const { locale } = this.props; | |
const { mediaFiles, documents, isFetching } = this.state; | |
const mediaFileCount = flatten(Object.values(mediaFiles)).length; | |
const documentFileCount = flatten(Object.values(documents)).length; | |
return ( | |
<Container> | |
{isFetching ? ( | |
<View style={styles.view}> | |
<ActivityIndicator color="#039BE5" size="large" /> | |
</View> | |
) : ( | |
<Tabs tabBarUnderlineStyle={styles.tabBarUnderline}> | |
<Tab | |
heading={`${translateString(locale)('Media')} (${mediaFileCount})`} | |
tabStyle={styles.tab} | |
textStyle={styles.text} | |
activeTabStyle={styles.activeTab} | |
activeTextStyle={styles.text} | |
> | |
{mediaFileCount ? ( | |
<SectionList | |
sections={Object.values(mediaFiles).map((attachments, index) => { | |
const title = Object.keys(mediaFiles)[index]; | |
const customKey = `media-files-${title.toLowerCase()}`; | |
return { | |
key: customKey, | |
data: [{ id: customKey }], | |
keyExtractor: ({ id }) => id, | |
renderItem: () => renderMediaList({ | |
title, | |
attachments, | |
isFetching, | |
onAttachmentOpen: this.handleOpenAttachment, | |
}), | |
}; | |
})} | |
contentContainerStyle={styles.mediaContainer} | |
/> | |
) : ( | |
<View style={styles.textContainer}> | |
<H2 style={styles.noContentText}>No shared media...</H2> | |
</View> | |
)} | |
</Tab> | |
<Tab | |
heading={`${translateString(locale)('Documents')} (${documentFileCount})`} | |
tabStyle={styles.tab} | |
textStyle={styles.text} | |
activeTabStyle={styles.activeTab} | |
activeTextStyle={styles.text} | |
> | |
{documentFileCount ? ( | |
<SectionList | |
sections={Object.values(documents).map((attachments, index) => { | |
const title = Object.keys(documents)[index]; | |
const customKey = `documents-${title.toLowerCase()}`; | |
return { | |
key: customKey, | |
data: [{ id: customKey }], | |
keyExtractor: ({ id }) => id, | |
renderItem: () => renderDocumentList({ | |
title, | |
locale, | |
attachments, | |
onAttachmentOpen: this.handleOpenAttachment, | |
}), | |
}; | |
})} | |
contentContainerStyle={styles.documentContainer} | |
/> | |
) : ( | |
<View style={styles.textContainer}> | |
<H2 style={styles.noContentText}>No shared document...</H2> | |
</View> | |
)} | |
</Tab> | |
</Tabs> | |
)} | |
</Container> | |
); | |
} | |
} | |
SharedFileList.propTypes = { | |
locale: PropTypes.string.isRequired, | |
messages: PropTypes.arrayOf(PropTypes.shape({})), | |
handlePlayClicker: PropTypes.func.isRequired, | |
}; | |
SharedFileList.defaultProps = { | |
messages: [], | |
}; | |
const mapStateToProps = ({ locale, currentConversation, messages }) => ({ | |
locale, | |
messages: messages[currentConversation.id], | |
}); | |
export { SharedFileList as UnconnectedSharedFileList }; | |
export default connect(mapStateToProps, { handlePlayClicker: playClicker })(SharedFileList); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment