125 lines
4.0 KiB
TypeScript
125 lines
4.0 KiB
TypeScript
import { requireNativeViewManager } from 'expo-modules-core';
|
|
import React from 'react';
|
|
import { NativeSyntheticEvent, StyleSheet, Platform, processColor } from 'react-native';
|
|
|
|
import {
|
|
ImageErrorEventData,
|
|
ImageLoadEventData,
|
|
ImageNativeProps,
|
|
ImageProgressEventData,
|
|
} from './Image.types';
|
|
|
|
const NativeExpoImage = requireNativeViewManager('ExpoImage');
|
|
|
|
function withDeprecatedNativeEvent<NativeEvent>(
|
|
event: NativeSyntheticEvent<NativeEvent>
|
|
): NativeEvent {
|
|
Object.defineProperty(event.nativeEvent, 'nativeEvent', {
|
|
get() {
|
|
console.warn(
|
|
'[expo-image]: Accessing event payload through "nativeEvent" is deprecated, it is now part of the event object itself'
|
|
);
|
|
return event.nativeEvent;
|
|
},
|
|
});
|
|
return event.nativeEvent;
|
|
}
|
|
|
|
class ExpoImage extends React.PureComponent<ImageNativeProps> {
|
|
// NOTE(@kitten): native methods
|
|
startAnimating!: () => Promise<unknown> | unknown;
|
|
stopAnimating!: () => Promise<unknown> | unknown;
|
|
lockResourceAsync!: () => Promise<void>;
|
|
unlockResourceAsync!: () => Promise<void>;
|
|
reloadAsync!: () => Promise<void>;
|
|
|
|
onLoadStart = () => {
|
|
this.props.onLoadStart?.();
|
|
};
|
|
|
|
onLoad = (event: NativeSyntheticEvent<ImageLoadEventData>) => {
|
|
this.props.onLoad?.(withDeprecatedNativeEvent(event));
|
|
this.onLoadEnd();
|
|
};
|
|
|
|
onProgress = (event: NativeSyntheticEvent<ImageProgressEventData>) => {
|
|
this.props.onProgress?.(withDeprecatedNativeEvent(event));
|
|
};
|
|
|
|
onError = (event: NativeSyntheticEvent<ImageErrorEventData>) => {
|
|
this.props.onError?.(withDeprecatedNativeEvent(event));
|
|
this.onLoadEnd();
|
|
};
|
|
|
|
onLoadEnd = () => {
|
|
this.props.onLoadEnd?.();
|
|
};
|
|
|
|
render() {
|
|
const { style, accessibilityLabel, alt, ...props } = this.props;
|
|
const resolvedStyle = StyleSheet.flatten(style);
|
|
|
|
// Shadows behave different on iOS, Android & Web.
|
|
// Android uses the `elevation` prop, whereas iOS
|
|
// and web use the regular `shadow...` props.
|
|
if (Platform.OS === 'android') {
|
|
delete resolvedStyle.shadowColor;
|
|
delete resolvedStyle.shadowOffset;
|
|
delete resolvedStyle.shadowOpacity;
|
|
delete resolvedStyle.shadowRadius;
|
|
} else {
|
|
// @ts-expect-error
|
|
delete resolvedStyle.elevation;
|
|
}
|
|
|
|
// @ts-ignore
|
|
const backgroundColor = processColor(resolvedStyle.backgroundColor);
|
|
// On Android, we have to set the `backgroundColor` directly on the correct component.
|
|
// So we have to remove it from styles. Otherwise, the background color won't take into consideration the border-radius.
|
|
if (Platform.OS === 'android') {
|
|
delete resolvedStyle.backgroundColor;
|
|
}
|
|
|
|
const tintColor = processColor(props.tintColor || resolvedStyle.tintColor);
|
|
|
|
const borderColor = processColor(resolvedStyle.borderColor);
|
|
// @ts-ignore
|
|
const borderStartColor = processColor(resolvedStyle.borderStartColor);
|
|
// @ts-ignore
|
|
const borderEndColor = processColor(resolvedStyle.borderEndColor);
|
|
// @ts-ignore
|
|
const borderLeftColor = processColor(resolvedStyle.borderLeftColor);
|
|
// @ts-ignore
|
|
const borderRightColor = processColor(resolvedStyle.borderRightColor);
|
|
// @ts-ignore
|
|
const borderTopColor = processColor(resolvedStyle.borderTopColor);
|
|
// @ts-ignore
|
|
const borderBottomColor = processColor(resolvedStyle.borderBottomColor);
|
|
|
|
return (
|
|
<NativeExpoImage
|
|
{...props}
|
|
{...resolvedStyle}
|
|
accessibilityLabel={accessibilityLabel ?? alt}
|
|
style={resolvedStyle}
|
|
onLoadStart={this.onLoadStart}
|
|
onLoad={this.onLoad}
|
|
onProgress={this.onProgress}
|
|
onError={this.onError}
|
|
tintColor={tintColor}
|
|
borderColor={borderColor}
|
|
borderLeftColor={borderLeftColor}
|
|
borderRightColor={borderRightColor}
|
|
borderTopColor={borderTopColor}
|
|
borderBottomColor={borderBottomColor}
|
|
borderStartColor={borderStartColor}
|
|
borderEndColor={borderEndColor}
|
|
backgroundColor={backgroundColor}
|
|
ref={props.nativeViewRef}
|
|
/>
|
|
);
|
|
}
|
|
}
|
|
|
|
export default ExpoImage;
|