-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
125 lines (116 loc) · 3.23 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import React, {useState, useEffect, useCallback} from "react";
import PropTypes from "prop-types";
import {ActivityIndicator, View, Image, StyleSheet} from "react-native";
import {typeCheck} from "type-check";
import useDeepCompareEffect from "use-deep-compare-effect";
const getMimeType = (uri, method) => new Promise(
(resolve, error) => {
const xhttp = new XMLHttpRequest();
xhttp.open(method, uri);
Object.assign(
xhttp,
{
onreadystatechange: function () {
if (this.readyState == this.DONE) {
return resolve(this.getResponseHeader('Content-Type'));
}
},
error,
},
);
xhttp.send();
},
);
const ImageComponent = ({ ...extraProps }) => (
<Image
resizeMode="cover"
{...extraProps}
/>
);
export const LookUpTable = {
['image/png']: ImageComponent,
['image/jpg']: ImageComponent,
['image/jpeg']: ImageComponent,
['image/gif']: ImageComponent,
['image/webp']: ImageComponent,
};
const styles = StyleSheet.create({container: {flex: 1}});
const UriBox = ({ Component, style, LoadingComponent, UnsupportedComponent, source, lookUpTable, optimized, inefficient, ...extraProps }) => {
const [mimeType, setMimeType] = useState(null);
const [{width, height}, setLayout] = useState({width: 0, height: 0});
const onLayout = useCallback(
({nativeEvent: {layout}}) => setLayout(layout),
);
useDeepCompareEffect(
() => {
if (typeCheck("{uri:String,...}", source)) {
const {uri} = source;
return getMimeType(uri, inefficient ? "GET" : "HEAD")
.then((mimeType) => {
if (typeCheck("String", mimeType)) {
return setMimeType(mimeType);
}
return Promise.reject(new Error(`${uri} does not support the HEAD request.`));
})
&& undefined;
}
return undefined;
},
[source, setMimeType, inefficient],
);
const Implementation = lookUpTable[mimeType];
const sourceIsKnown = typeCheck("String", mimeType) && typeCheck("Function", Implementation);
return (
<Component
style={style}
onLayout={onLayout}
>
{(!!sourceIsKnown) && (
<Implementation
style={{
width,
height,
}}
{...extraProps}
source={source}
/>
)}
{(!sourceIsKnown && mimeType) && (
<UnsupportedComponent
source={source}
/>
)}
{(!sourceIsKnown && (!!source)) && (
<LoadingComponent
/>
)}
</Component>
);
};
UriBox.propTypes = {
Component: PropTypes.elementType,
LoadingComponent: PropTypes.elementType,
UnsupportedComponent: PropTypes.elementType,
style: PropTypes.shape({}),
source: PropTypes.oneOfType([PropTypes.shape({uri: PropTypes.string.isRequired})]),
lookUpTable: PropTypes.shape({}),
inefficient: PropTypes.bool,
};
UriBox.defaultProps = {
Component: View,
LoadingComponent: ActivityIndicator,
UnsupportedComponent: ({ ...extraProps }) => (
<View
style={{
flex: 1,
borderWidth: 1,
borderColor: 'lightgrey',
}}
/>
),
style: styles.container,
source: null,
lookUpTable: LookUpTable,
inefficient: false,
};
export default UriBox;