* Fix Gallery crash
* fix file type icons
* memoize gallery files
(cherry picked from commit 1b285dac49)
Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
This commit is contained in:
parent
2e71fcc226
commit
456208d223
6 changed files with 45 additions and 46 deletions
|
|
@ -25,21 +25,21 @@ const BLUE_ICON = '#338AFF';
|
|||
const RED_ICON = '#ED522A';
|
||||
const GREEN_ICON = '#1CA660';
|
||||
const GRAY_ICON = '#999999';
|
||||
const FAILED_ICON_NAME_AND_COLOR = ['jumbo-attachment-image-broken', GRAY_ICON];
|
||||
const FAILED_ICON_NAME_AND_COLOR = ['file-image-broken-outline-large', GRAY_ICON];
|
||||
const ICON_NAME_AND_COLOR_FROM_FILE_TYPE: Record<string, string[]> = {
|
||||
audio: ['jumbo-attachment-audio', BLUE_ICON],
|
||||
code: ['jumbo-attachment-code', BLUE_ICON],
|
||||
image: ['jumbo-attachment-image', BLUE_ICON],
|
||||
audio: ['file-audio-outline-large', BLUE_ICON],
|
||||
code: ['file-code-outline-large', BLUE_ICON],
|
||||
image: ['file-image-outline-large', BLUE_ICON],
|
||||
smallImage: ['image-outline', BLUE_ICON],
|
||||
other: ['jumbo-attachment-generic', BLUE_ICON],
|
||||
patch: ['jumbo-attachment-patch', BLUE_ICON],
|
||||
pdf: ['jumbo-attachment-pdf', RED_ICON],
|
||||
presentation: ['jumbo-attachment-powerpoint', RED_ICON],
|
||||
spreadsheet: ['jumbo-attachment-excel', GREEN_ICON],
|
||||
text: ['jumbo-attachment-text', GRAY_ICON],
|
||||
video: ['jumbo-attachment-video', BLUE_ICON],
|
||||
word: ['jumbo-attachment-word', BLUE_ICON],
|
||||
zip: ['jumbo-attachment-zip', BLUE_ICON],
|
||||
other: ['file-generic-outline-large', BLUE_ICON],
|
||||
patch: ['file-patch-outline-large', BLUE_ICON],
|
||||
pdf: ['file-pdf-outline-large', RED_ICON],
|
||||
presentation: ['file-powerpoint-outline-large', RED_ICON],
|
||||
spreadsheet: ['file-excel-outline-large', GREEN_ICON],
|
||||
text: ['file-text-outline-large', GRAY_ICON],
|
||||
video: ['file-video-outline-large', BLUE_ICON],
|
||||
word: ['file-word-outline-large', BLUE_ICON],
|
||||
zip: ['file-zip-outline-large', BLUE_ICON],
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useEffect, useRef, useState} from 'react';
|
||||
import React, {useEffect, useMemo, useState} from 'react';
|
||||
import {DeviceEventEmitter, StyleProp, StyleSheet, View, ViewStyle} from 'react-native';
|
||||
|
||||
import {Client4} from '@client/rest';
|
||||
|
|
@ -46,10 +46,10 @@ const Files = ({canDownloadFiles, failed, files, isReplyPost, postId, theme}: Fi
|
|||
const [inViewPort, setInViewPort] = useState(false);
|
||||
const permanentSidebar = usePermanentSidebar();
|
||||
const isSplitView = useSplitView();
|
||||
const imageAttachments = useRef<FileInfo[]>([]).current;
|
||||
const nonImageAttachments = useRef<FileInfo[]>([]).current;
|
||||
const {imageAttachments, nonImageAttachments} = useMemo(() => {
|
||||
const images: FileInfo[] = [];
|
||||
const nonImages: FileInfo[] = [];
|
||||
|
||||
if (!imageAttachments.length && !nonImageAttachments.length) {
|
||||
files.reduce((info, file) => {
|
||||
if (isImage(file)) {
|
||||
let uri;
|
||||
|
|
@ -58,15 +58,17 @@ const Files = ({canDownloadFiles, failed, files, isReplyPost, postId, theme}: Fi
|
|||
} else {
|
||||
uri = isGif(file) ? Client4.getFileUrl(file.id, 0) : Client4.getFilePreviewUrl(file.id, 0);
|
||||
}
|
||||
info.imageAttachments.push({...file, uri});
|
||||
info.images.push({...file, uri});
|
||||
} else {
|
||||
info.nonImageAttachments.push(file);
|
||||
info.nonImages.push(file);
|
||||
}
|
||||
return info;
|
||||
}, {imageAttachments, nonImageAttachments});
|
||||
}
|
||||
}, {images, nonImages});
|
||||
|
||||
const filesForGallery = useRef<FileInfo[]>(imageAttachments.concat(nonImageAttachments)).current;
|
||||
return {imageAttachments: images, nonImageAttachments: nonImages};
|
||||
}, [files]);
|
||||
|
||||
const filesForGallery = imageAttachments.concat(nonImageAttachments);
|
||||
const attachmentIndex = (fileId: string) => {
|
||||
return filesForGallery.findIndex((file) => file.id === fileId) || 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -16,8 +16,6 @@ import GalleryViewer from './gallery_viewer';
|
|||
export default class Gallery extends PureComponent {
|
||||
static propTypes = {
|
||||
componentId: PropTypes.string.isRequired,
|
||||
deviceHeight: PropTypes.number.isRequired,
|
||||
deviceWidth: PropTypes.number.isRequired,
|
||||
files: PropTypes.array,
|
||||
index: PropTypes.number.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
|
|
@ -152,19 +150,15 @@ export default class Gallery extends PureComponent {
|
|||
};
|
||||
|
||||
render() {
|
||||
const {deviceHeight, deviceWidth, files, theme} = this.props;
|
||||
const {files, theme} = this.props;
|
||||
const {index, footerVisible} = this.state;
|
||||
|
||||
return (
|
||||
<>
|
||||
<GalleryViewer
|
||||
key={`gallery-${deviceWidth}`}
|
||||
files={files}
|
||||
footerVisible={footerVisible}
|
||||
width={deviceWidth}
|
||||
height={deviceHeight}
|
||||
initialIndex={index}
|
||||
isLandscape={deviceWidth > deviceHeight}
|
||||
onClose={this.close}
|
||||
onPageSelected={this.handlePageSelected}
|
||||
onTap={this.handleTapped}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useEffect, useMemo, useRef, useState} from 'react';
|
||||
import {Platform, StyleSheet, View} from 'react-native';
|
||||
import {Platform, StyleSheet, useWindowDimensions, View} from 'react-native';
|
||||
import {PanGestureHandler, PinchGestureHandler, State, TapGestureHandler, TapGestureHandlerStateChangeEvent} from 'react-native-gesture-handler';
|
||||
import Animated, {abs, add, and, call, clockRunning, cond, divide, eq, greaterOrEq, greaterThan, multiply, neq, not, onChange, set, sub, useCode, EasingNode, ceil} from 'react-native-reanimated';
|
||||
import {clamp, snapPoint, timing, useClock, usePanGestureHandler, usePinchGestureHandler, useTapGestureHandler, useValue, vec} from 'react-native-redash/lib/module/v1';
|
||||
|
|
@ -18,34 +18,40 @@ import GalleryVideo from './gallery_video';
|
|||
|
||||
import type {GalleryProps} from '@mm-types/screens/gallery';
|
||||
|
||||
const itemTopStyle = (props: GalleryProps): number => {
|
||||
type GalleryStyle = {
|
||||
count: number;
|
||||
height: number;
|
||||
width: number;
|
||||
}
|
||||
|
||||
const itemTopStyle = (footerVisible: boolean, isLandscape: boolean): number => {
|
||||
if (Platform.OS === 'android') {
|
||||
if (props.footerVisible) {
|
||||
return props.isLandscape ? -64 : -99;
|
||||
if (footerVisible) {
|
||||
return isLandscape ? -64 : -99;
|
||||
}
|
||||
|
||||
return props.isLandscape ? -6 : -41;
|
||||
return isLandscape ? -6 : -41;
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
const getStyles = makeStyleSheetFromTheme((props: GalleryProps) => ({
|
||||
const getStyles = makeStyleSheetFromTheme(({count, width, height}: GalleryStyle) => ({
|
||||
container: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
},
|
||||
items: {
|
||||
width: (props.width * props.files.length),
|
||||
height: props.height,
|
||||
width: (width * count),
|
||||
height,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
item: {
|
||||
alignItems: 'center',
|
||||
height: props.height,
|
||||
height,
|
||||
justifyContent: 'center',
|
||||
overflow: 'hidden',
|
||||
width: props.width,
|
||||
width,
|
||||
},
|
||||
center: {
|
||||
justifyContent: 'center',
|
||||
|
|
@ -53,12 +59,13 @@ const getStyles = makeStyleSheetFromTheme((props: GalleryProps) => ({
|
|||
}));
|
||||
|
||||
const GalleryViewer = (props: GalleryProps) => {
|
||||
const {files, height, initialIndex, width} = props;
|
||||
const {files, initialIndex} = props;
|
||||
const [enabled, setEnabled] = useState(false);
|
||||
const [tapEnabled, setTapEnabled] = useState(true);
|
||||
const [currentIndex, setCurrentIndex] = useState(initialIndex);
|
||||
const styles = getStyles(props);
|
||||
const topValue = itemTopStyle(props);
|
||||
const {height, width} = useWindowDimensions();
|
||||
const styles = getStyles({width, height, count: files.length});
|
||||
const topValue = itemTopStyle(props.footerVisible, width > height);
|
||||
const top = useRef(useValue(topValue)).current;
|
||||
|
||||
const canvas = useMemo(() => vec.create(width, height), [width]);
|
||||
|
|
|
|||
|
|
@ -4,13 +4,11 @@
|
|||
import {connect} from 'react-redux';
|
||||
|
||||
import {getTheme} from '@mm-redux/selectors/entities/preferences';
|
||||
import {getDimensions} from '@selectors/device';
|
||||
|
||||
import Gallery from './gallery';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
...getDimensions(state),
|
||||
theme: getTheme(state),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
2
types/screens/gallery.d.ts
vendored
2
types/screens/gallery.d.ts
vendored
|
|
@ -61,13 +61,11 @@ export interface FooterRef {
|
|||
export interface GalleryProps {
|
||||
files: Array<FileInfo>;
|
||||
footerVisible: boolean;
|
||||
height: number;
|
||||
initialIndex: number;
|
||||
isLandscape: boolean;
|
||||
onClose: CallbackFunctionWithoutArguments;
|
||||
onPageSelected: (index: number) => void;
|
||||
onTap: CallbackFunctionWithoutArguments;
|
||||
width: number;
|
||||
theme: Theme;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue