Add retriable FastImage component (#5167)

This commit is contained in:
Miguel Alatzar 2021-02-10 14:41:30 -07:00 committed by GitHub
parent ed4b100962
commit e33a16d4f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 95 additions and 2 deletions

View file

@ -4,14 +4,14 @@
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {Animated, ImageBackground, Image, Platform, View, StyleSheet} from 'react-native';
import FastImage from 'react-native-fast-image';
import thumb from '@assets/images/thumb.png';
import CustomPropTypes from '@constants/custom_prop_types';
import RetriableFastImage from '@components/retriable_fast_image';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
const AnimatedImageBackground = Animated.createAnimatedComponent(ImageBackground);
const AnimatedFastImage = Animated.createAnimatedComponent(FastImage);
const AnimatedFastImage = Animated.createAnimatedComponent(RetriableFastImage);
export default class ProgressiveImage extends PureComponent {
static propTypes = {

View file

@ -0,0 +1,41 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {PureComponent} from 'react';
import FastImage, {FastImageProps} from 'react-native-fast-image';
export const FAST_IMAGE_MAX_RETRIES = 3;
type RetriableFastImageProps = FastImageProps & {
id: string
}
type RetriableFastImageState = {
retry: number
}
export default class RetriableFastImage extends PureComponent<RetriableFastImageProps, RetriableFastImageState> {
state = {
retry: 0,
}
onError = () => {
const retry = this.state.retry + 1;
if (retry > FAST_IMAGE_MAX_RETRIES && this.props.onError) {
this.props.onError();
return;
}
this.setState({retry});
}
render() {
return (
<FastImage
{...this.props}
key={`${this.props.id}-${this.state.retry}`}
onError={this.onError}
/>
);
}
}

View file

@ -0,0 +1,52 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {shallow} from 'enzyme';
import FastImage from 'react-native-fast-image';
import RetriableFastImage, {FAST_IMAGE_MAX_RETRIES} from './index';
describe('RetriableFastImage', () => {
const baseProps = {
id: 'id',
onError: jest.fn(),
};
it('should update the FastImage element key on error until max retries has been reached', () => {
const wrapper = shallow(
<RetriableFastImage {...baseProps}/>,
);
const instance = wrapper.instance();
let retry = 0;
expect(wrapper.containsMatchingElement(<FastImage key={`${baseProps.id}-${retry}`}/>)).toEqual(true);
while (instance.state.retry < FAST_IMAGE_MAX_RETRIES) {
instance.onError();
retry += 1;
expect(wrapper.containsMatchingElement(<FastImage key={`${baseProps.id}-${retry}`}/>)).toEqual(true);
}
instance.onError();
expect(wrapper.containsMatchingElement(<FastImage key={`${baseProps.id}-${retry}`}/>)).toEqual(true);
});
it('should call props.onError only after max retries has been reached', () => {
const wrapper = shallow(
<RetriableFastImage {...baseProps}/>,
);
const instance = wrapper.instance();
let retry = 0;
while (instance.state.retry < FAST_IMAGE_MAX_RETRIES) {
instance.onError();
retry += 1;
expect(instance.state.retry).toEqual(retry);
expect(baseProps.onError).not.toHaveBeenCalled();
}
instance.onError();
expect(instance.state.retry).toEqual(retry);
expect(baseProps.onError).toHaveBeenCalled();
});
});