Previewer (#1246)
* Fix heic * Change previwer to use the swiper instead a simple ScrollView
This commit is contained in:
parent
bd39fa5b43
commit
bf4463b866
4 changed files with 141 additions and 128 deletions
|
|
@ -16,6 +16,7 @@ export function handleUploadFiles(files, rootId) {
|
|||
const channelId = state.entities.channels.currentChannelId;
|
||||
const formData = new FormData();
|
||||
const clientIds = [];
|
||||
const re = /heic/i;
|
||||
|
||||
files.forEach((file) => {
|
||||
let name = file.fileName;
|
||||
|
|
@ -24,9 +25,9 @@ export function handleUploadFiles(files, rootId) {
|
|||
const uri = file.uri;
|
||||
const clientId = generateId();
|
||||
|
||||
if (extension === 'HEIC') {
|
||||
if (re.test(extension)) {
|
||||
extension = 'JPG';
|
||||
name = name.replace(/HEIC/, 'jpg');
|
||||
name = name.replace(re, 'jpg');
|
||||
mimeType = 'image/jpeg';
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
InteractionManager,
|
||||
View,
|
||||
ScrollView,
|
||||
ViewPagerAndroid,
|
||||
|
|
@ -30,7 +29,8 @@ export default class Swiper extends PureComponent {
|
|||
PropTypes.object,
|
||||
PropTypes.number
|
||||
]),
|
||||
width: PropTypes.number
|
||||
width: PropTypes.number,
|
||||
onScrollBegin: PropTypes.func
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
|
|
@ -38,7 +38,8 @@ export default class Swiper extends PureComponent {
|
|||
keyboardShouldPersistTaps: 'handled',
|
||||
onIndexChanged: () => null,
|
||||
scrollEnabled: true,
|
||||
showsPagination: true
|
||||
showsPagination: true,
|
||||
onScrollBegin: () => true
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
|
|
@ -84,6 +85,7 @@ export default class Swiper extends PureComponent {
|
|||
|
||||
onScrollBegin = () => {
|
||||
this.isScrolling = true;
|
||||
this.props.onScrollBegin();
|
||||
};
|
||||
|
||||
onScrollEnd = (e) => {
|
||||
|
|
@ -98,11 +100,15 @@ export default class Swiper extends PureComponent {
|
|||
this.updateIndex(e.nativeEvent.contentOffset.x);
|
||||
};
|
||||
|
||||
scrollToStart = () => {
|
||||
if (Platform.OS === 'ios') {
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
this.scrollView.scrollTo({x: 0, animated: false});
|
||||
});
|
||||
onPageScrollStateChanged = (e) => {
|
||||
switch (e) {
|
||||
case 'idle':
|
||||
this.isScrolling = false;
|
||||
break;
|
||||
case 'dragging':
|
||||
this.isScrolling = true;
|
||||
this.props.onScrollBegin();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -141,8 +147,8 @@ export default class Swiper extends PureComponent {
|
|||
<ViewPagerAndroid
|
||||
ref={this.refScrollView}
|
||||
initialPage={this.props.initialPage}
|
||||
onScrollBeginDrag={this.onScrollBegin}
|
||||
onPageSelected={this.onScrollEnd}
|
||||
onPageScrollStateChanged={this.onPageScrollStateChanged}
|
||||
scrollEnabled={scrollEnabled}
|
||||
key={pages.length}
|
||||
style={[styles.wrapperAndroid, this.props.style]}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import {
|
|||
InteractionManager,
|
||||
PanResponder,
|
||||
Platform,
|
||||
ScrollView,
|
||||
StatusBar,
|
||||
StyleSheet,
|
||||
Text,
|
||||
|
|
@ -27,6 +26,7 @@ import {DeviceTypes} from 'app/constants/';
|
|||
import FileAttachmentDocument, {SUPPORTED_DOCS_FORMAT} from 'app/components/file_attachment_list/file_attachment_document';
|
||||
import FileAttachmentIcon from 'app/components/file_attachment_list/file_attachment_icon';
|
||||
import SafeAreaView from 'app/components/safe_area_view';
|
||||
import Swiper from 'app/components/swiper';
|
||||
import {NavigationTypes} from 'app/constants';
|
||||
import {emptyFunction} from 'app/utils/general';
|
||||
|
||||
|
|
@ -83,7 +83,8 @@ export default class ImagePreview extends PureComponent {
|
|||
footerOpacity: new Animated.Value(1),
|
||||
pagingEnabled: true,
|
||||
showFileInfo: true,
|
||||
wrapperViewOpacity: new Animated.Value(0)
|
||||
wrapperViewOpacity: new Animated.Value(0),
|
||||
limitOpacity: new Animated.Value(0)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -101,10 +102,6 @@ export default class ImagePreview extends PureComponent {
|
|||
|
||||
componentDidMount() {
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
if (this.scrollView) {
|
||||
this.scrollView.scrollTo({x: (this.state.currentFile) * this.props.deviceWidth, animated: false});
|
||||
}
|
||||
|
||||
Animated.timing(this.state.wrapperViewOpacity, {
|
||||
toValue: 1,
|
||||
duration: 100
|
||||
|
|
@ -113,12 +110,6 @@ export default class ImagePreview extends PureComponent {
|
|||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.deviceWidth !== nextProps.deviceWidth) {
|
||||
if (this.scrollView) {
|
||||
this.scrollView.scrollTo({x: (this.state.currentFile * nextProps.deviceWidth), animated: true});
|
||||
}
|
||||
}
|
||||
|
||||
if (!nextProps.files.length) {
|
||||
this.showDeletedFilesAlert();
|
||||
}
|
||||
|
|
@ -130,14 +121,40 @@ export default class ImagePreview extends PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
attachScrollView = (c) => {
|
||||
this.scrollView = c;
|
||||
};
|
||||
|
||||
close = () => {
|
||||
this.props.navigator.dismissModal({animationType: 'none'});
|
||||
};
|
||||
|
||||
getPreviews = () => {
|
||||
return this.state.files.map((file, index) => {
|
||||
let mime = file.mime_type;
|
||||
if (mime && mime.includes(';')) {
|
||||
mime = mime.split(';')[0];
|
||||
}
|
||||
|
||||
let component;
|
||||
|
||||
if (file.has_preview_image || file.mime_type === 'image/gif') {
|
||||
component = this.renderPreviewer(file, index);
|
||||
} else if (SUPPORTED_DOCS_FORMAT.includes(mime)) {
|
||||
component = this.renderAttachmentDocument(file);
|
||||
} else if (SUPPORTED_VIDEO_FORMAT.includes(file.mime_type)) {
|
||||
component = this.renderVideoPreview(file);
|
||||
} else {
|
||||
component = this.renderAttachmentIcon(file);
|
||||
}
|
||||
|
||||
return (
|
||||
<AnimatedView
|
||||
key={file.id}
|
||||
style={[style.pageWrapper, {height: this.props.deviceHeight, width: this.props.deviceWidth, opacity: index === this.state.currentFile ? 1 : this.state.limitOpacity}]}
|
||||
>
|
||||
{component}
|
||||
</AnimatedView>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
handleClose = () => {
|
||||
if (this.state.showFileInfo) {
|
||||
this.close();
|
||||
|
|
@ -151,6 +168,12 @@ export default class ImagePreview extends PureComponent {
|
|||
}
|
||||
};
|
||||
|
||||
handleLayout = () => {
|
||||
if (this.refs.swiper) {
|
||||
this.refs.swiper.runOnLayout = true;
|
||||
}
|
||||
};
|
||||
|
||||
handleImageDoubleTap = (x, y) => {
|
||||
this.zoomableImages[this.state.currentFile].toggleZoom(x, y);
|
||||
};
|
||||
|
|
@ -160,25 +183,17 @@ export default class ImagePreview extends PureComponent {
|
|||
this.setHeaderAndFileInfoVisible(!this.state.showFileInfo);
|
||||
};
|
||||
|
||||
handleScroll = (event) => {
|
||||
const offset = event.nativeEvent.contentOffset.x / this.props.deviceWidth;
|
||||
const wholeNumber = Number((offset).toFixed(0));
|
||||
|
||||
if (Math.abs(offset - wholeNumber) < 0.01) {
|
||||
this.setState({
|
||||
currentFile: wholeNumber,
|
||||
pagingEnabled: true,
|
||||
shouldShrinkImages: false
|
||||
});
|
||||
} else if (!this.state.shouldShrinkImages && !this.state.isZooming) {
|
||||
this.setState({
|
||||
shouldShrinkImages: true
|
||||
});
|
||||
handleIndexChanged = (currentFile) => {
|
||||
if (Number.isInteger(currentFile)) {
|
||||
this.setState({currentFile, limitOpacity: new Animated.Value(0)});
|
||||
}
|
||||
};
|
||||
|
||||
handleScrollStopped = () => {
|
||||
EventEmitter.emit('stop-video-playback');
|
||||
handleScroll = () => {
|
||||
Animated.timing(this.state.limitOpacity, {
|
||||
toValue: 1,
|
||||
duration: 100
|
||||
}).start();
|
||||
};
|
||||
|
||||
handleVideoSeek = (seeking) => {
|
||||
|
|
@ -399,42 +414,46 @@ export default class ImagePreview extends PureComponent {
|
|||
|
||||
renderDownloadButton = () => {
|
||||
const {canDownloadFiles} = this.props;
|
||||
const {files} = this.state;
|
||||
const {currentFile, files} = this.state;
|
||||
|
||||
const file = files[this.state.currentFile];
|
||||
const file = files[currentFile];
|
||||
|
||||
let icon;
|
||||
let action = emptyFunction;
|
||||
if (canDownloadFiles) {
|
||||
if (Platform.OS === 'android') {
|
||||
action = this.showDownloadOptions;
|
||||
icon = (
|
||||
<Icon
|
||||
name='md-more'
|
||||
size={32}
|
||||
color='#fff'
|
||||
/>
|
||||
);
|
||||
} else if (file.has_preview_image || SUPPORTED_VIDEO_FORMAT.includes(file.mime_type)) {
|
||||
action = this.showDownloadOptions;
|
||||
icon = (
|
||||
<Icon
|
||||
name='ios-download-outline'
|
||||
size={26}
|
||||
color='#fff'
|
||||
/>
|
||||
);
|
||||
if (file) {
|
||||
let icon;
|
||||
let action = emptyFunction;
|
||||
if (canDownloadFiles) {
|
||||
if (Platform.OS === 'android') {
|
||||
action = this.showDownloadOptions;
|
||||
icon = (
|
||||
<Icon
|
||||
name='md-more'
|
||||
size={32}
|
||||
color='#fff'
|
||||
/>
|
||||
);
|
||||
} else if (file.has_preview_image || SUPPORTED_VIDEO_FORMAT.includes(file.mime_type)) {
|
||||
action = this.showDownloadOptions;
|
||||
icon = (
|
||||
<Icon
|
||||
name='ios-download-outline'
|
||||
size={26}
|
||||
color='#fff'
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
onPress={action}
|
||||
style={style.headerIcon}
|
||||
>
|
||||
{icon}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
onPress={action}
|
||||
style={style.headerIcon}
|
||||
>
|
||||
{icon}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
return null;
|
||||
};
|
||||
|
||||
renderPreviewer = (file, index) => {
|
||||
|
|
@ -476,56 +495,48 @@ export default class ImagePreview extends PureComponent {
|
|||
);
|
||||
};
|
||||
|
||||
renderSwiper = () => {
|
||||
return (
|
||||
<Swiper
|
||||
ref='swiper'
|
||||
initialPage={this.state.currentFile}
|
||||
onIndexChanged={this.handleIndexChanged}
|
||||
width={this.props.deviceWidth}
|
||||
activeDotColor={this.props.theme.sidebarBg}
|
||||
dotColor={this.props.theme.sidebarText}
|
||||
scrollEnabled={!this.state.isZooming}
|
||||
showsPagination={false}
|
||||
onScrollBegin={this.handleScroll}
|
||||
>
|
||||
{this.getPreviews()}
|
||||
</Swiper>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {currentFile, files} = this.state;
|
||||
const file = files[currentFile];
|
||||
|
||||
if (!file) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fileName = file ? file.name : '';
|
||||
|
||||
return (
|
||||
<SafeAreaView
|
||||
backgroundColor='#000'
|
||||
navBarBackgroundColor='#000'
|
||||
>
|
||||
<View style={[style.wrapper]}>
|
||||
<View
|
||||
style={[style.wrapper]}
|
||||
onLayout={this.handleLayout}
|
||||
>
|
||||
<AnimatedView
|
||||
style={[this.state.drag.getLayout(), {opacity: this.state.wrapperViewOpacity}]}
|
||||
style={[this.state.drag.getLayout(), {opacity: this.state.wrapperViewOpacity, flex: 1}]}
|
||||
{...this.mainViewPanResponder.panHandlers}
|
||||
>
|
||||
<ScrollView
|
||||
ref={this.attachScrollView}
|
||||
style={[style.ScrollView]}
|
||||
contentContainerStyle={style.scrollViewContent}
|
||||
scrollEnabled={!this.state.isZooming}
|
||||
horizontal={true}
|
||||
pagingEnabled={!this.state.isZooming}
|
||||
bounces={false}
|
||||
onScroll={this.handleScroll}
|
||||
onMomentumScrollEnd={this.handleScrollStopped}
|
||||
scrollEventThrottle={2}
|
||||
>
|
||||
{this.state.files.map((file, index) => {
|
||||
let mime = file.mime_type;
|
||||
if (mime && mime.includes(';')) {
|
||||
mime = mime.split(';')[0];
|
||||
}
|
||||
|
||||
let component;
|
||||
if (file.has_preview_image || file.mime_type === 'image/gif') {
|
||||
component = this.renderPreviewer(file, index);
|
||||
} else if (SUPPORTED_DOCS_FORMAT.includes(mime)) {
|
||||
component = this.renderAttachmentDocument(file);
|
||||
} else if (SUPPORTED_VIDEO_FORMAT.includes(file.mime_type)) {
|
||||
component = this.renderVideoPreview(file);
|
||||
} else {
|
||||
component = this.renderAttachmentIcon(file);
|
||||
}
|
||||
|
||||
return (
|
||||
<View
|
||||
key={file.id}
|
||||
style={[style.pageWrapper, {height: this.props.deviceHeight, width: this.props.deviceWidth}]}
|
||||
>
|
||||
{component}
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</ScrollView>
|
||||
{this.renderSwiper()}
|
||||
<AnimatedView style={[style.headerContainer, {width: this.props.deviceWidth, opacity: this.state.footerOpacity}]}>
|
||||
<View style={style.header}>
|
||||
<View style={style.headerControls}>
|
||||
|
|
@ -540,7 +551,7 @@ export default class ImagePreview extends PureComponent {
|
|||
/>
|
||||
</TouchableOpacity>
|
||||
<Text style={style.title}>
|
||||
{`${this.state.currentFile + 1}/${this.state.files.length}`}
|
||||
{`${currentFile + 1}/${files.length}`}
|
||||
</Text>
|
||||
{this.renderDownloadButton()}
|
||||
</View>
|
||||
|
|
@ -555,7 +566,7 @@ export default class ImagePreview extends PureComponent {
|
|||
pointerEvents='none'
|
||||
>
|
||||
<Text style={style.filename}>
|
||||
{this.state.files[this.state.currentFile].name}
|
||||
{fileName}
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
</AnimatedView>
|
||||
|
|
@ -563,7 +574,7 @@ export default class ImagePreview extends PureComponent {
|
|||
<Downloader
|
||||
ref='downloader'
|
||||
show={this.state.showDownloader}
|
||||
file={this.state.files[this.state.currentFile]}
|
||||
file={file}
|
||||
deviceHeight={this.props.deviceHeight}
|
||||
deviceWidth={this.props.deviceWidth}
|
||||
onDownloadCancel={this.hideDownloader}
|
||||
|
|
@ -628,7 +639,7 @@ const style = StyleSheet.create({
|
|||
footerContainer: {
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
height: 70,
|
||||
height: 40,
|
||||
zIndex: 2
|
||||
},
|
||||
footer: {
|
||||
|
|
@ -636,18 +647,13 @@ const style = StyleSheet.create({
|
|||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: 70,
|
||||
height: 40,
|
||||
justifyContent: 'flex-end',
|
||||
paddingHorizontal: 24,
|
||||
paddingBottom: 16,
|
||||
...Platform.select({
|
||||
android: {
|
||||
marginBottom: 13
|
||||
}
|
||||
})
|
||||
paddingBottom: 5
|
||||
},
|
||||
filename: {
|
||||
color: 'white',
|
||||
fontSize: 15
|
||||
fontSize: 14
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ export default class Previewer extends Component {
|
|||
onResponderRelease={this.handleResponderRelease}
|
||||
style={[style.fileImageWrapper, {height: '100%', width: '100%'}]}
|
||||
>
|
||||
<AnimatedView style={{height: imageHeight, width: this.state.imageWidth, backgroundColor: '#000', opacity}}>
|
||||
<AnimatedView style={{flex: 1, backgroundColor: '#000', opacity}}>
|
||||
<ImageView
|
||||
ref={this.attachImageView}
|
||||
source={source}
|
||||
|
|
|
|||
Loading…
Reference in a new issue