@fountain-ui/lab 2.0.0-beta.33 → 2.0.0-beta.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/commonjs/ComicViewer/ComicViewer.js +197 -142
- package/build/commonjs/ComicViewer/ComicViewer.js.map +1 -1
- package/build/commonjs/ComicViewer/ComicViewerProps.js +0 -12
- package/build/commonjs/ComicViewer/ComicViewerProps.js.map +1 -1
- package/build/commonjs/ComicViewer/ReloadButton.js +43 -0
- package/build/commonjs/ComicViewer/ReloadButton.js.map +1 -0
- package/build/commonjs/ComicViewer/ViewerItem.js +37 -152
- package/build/commonjs/ComicViewer/ViewerItem.js.map +1 -1
- package/build/commonjs/ComicViewer/checkered-loading.jpg +0 -0
- package/build/commonjs/ComicViewer/index.js.map +1 -1
- package/build/module/ComicViewer/ComicViewer.js +196 -142
- package/build/module/ComicViewer/ComicViewer.js.map +1 -1
- package/build/module/ComicViewer/ComicViewerProps.js +1 -6
- package/build/module/ComicViewer/ComicViewerProps.js.map +1 -1
- package/build/module/ComicViewer/ReloadButton.js +29 -0
- package/build/module/ComicViewer/ReloadButton.js.map +1 -0
- package/build/module/ComicViewer/ViewerItem.js +39 -154
- package/build/module/ComicViewer/ViewerItem.js.map +1 -1
- package/build/module/ComicViewer/checkered-loading.jpg +0 -0
- package/build/module/ComicViewer/index.js.map +1 -1
- package/build/typescript/ComicViewer/ComicViewer.d.ts +1 -1
- package/build/typescript/ComicViewer/ComicViewerProps.d.ts +15 -82
- package/build/typescript/ComicViewer/ReloadButton.d.ts +6 -0
- package/build/typescript/ComicViewer/ViewerItem.d.ts +37 -7
- package/build/typescript/ComicViewer/index.d.ts +2 -2
- package/package.json +2 -2
- package/src/ComicViewer/ComicViewer.tsx +210 -155
- package/src/ComicViewer/ComicViewerProps.ts +16 -98
- package/src/ComicViewer/ReloadButton.tsx +33 -0
- package/src/ComicViewer/ViewerItem.tsx +81 -169
- package/src/ComicViewer/checkered-loading.jpg +0 -0
- package/src/ComicViewer/index.ts +2 -2
- package/build/commonjs/ComicViewer/ComicViewerItemProps.js +0 -6
- package/build/commonjs/ComicViewer/ComicViewerItemProps.js.map +0 -1
- package/build/module/ComicViewer/ComicViewerItemProps.js +0 -2
- package/build/module/ComicViewer/ComicViewerItemProps.js.map +0 -1
- package/build/typescript/ComicViewer/ComicViewerItemProps.d.ts +0 -34
- package/src/ComicViewer/ComicViewerItemProps.ts +0 -42
|
@@ -3,188 +3,73 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.default =
|
|
6
|
+
exports.default = ViewerItem;
|
|
7
7
|
|
|
8
8
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
9
|
|
|
10
10
|
var _reactNative = require("react-native");
|
|
11
11
|
|
|
12
|
-
var R = _interopRequireWildcard(require("ramda"));
|
|
13
|
-
|
|
14
12
|
var _core = require("@fountain-ui/core");
|
|
15
13
|
|
|
16
|
-
var
|
|
14
|
+
var _ReloadButton = _interopRequireDefault(require("./ReloadButton"));
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
19
17
|
|
|
20
18
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
21
19
|
|
|
22
20
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
23
21
|
|
|
24
|
-
|
|
25
|
-
const theme = (0, _core.useTheme)();
|
|
26
|
-
return {
|
|
27
|
-
root: {
|
|
28
|
-
display: 'flex',
|
|
29
|
-
flexDirection: 'row',
|
|
30
|
-
justifyContent: 'center'
|
|
31
|
-
},
|
|
32
|
-
init: {
|
|
33
|
-
backgroundColor: theme.palette.paper.grey
|
|
34
|
-
},
|
|
35
|
-
failed: {
|
|
36
|
-
backgroundColor: theme.palette.paper.grey
|
|
37
|
-
},
|
|
38
|
-
reload: {
|
|
39
|
-
backgroundColor: theme.palette.paper.grey,
|
|
40
|
-
display: 'flex',
|
|
41
|
-
alignItems: 'center'
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
function ViewerItem(_ref) {
|
|
47
|
-
var _itemState$error;
|
|
48
|
-
|
|
49
|
-
let {
|
|
50
|
-
props
|
|
51
|
-
} = _ref;
|
|
22
|
+
function ViewerItem(props) {
|
|
52
23
|
const {
|
|
53
|
-
expiresAt,
|
|
54
|
-
errorRetryCount = 3,
|
|
55
24
|
height,
|
|
56
|
-
itemState,
|
|
57
|
-
isViewable,
|
|
58
|
-
sortKey,
|
|
59
25
|
url,
|
|
60
26
|
width,
|
|
61
|
-
getNextPage,
|
|
62
27
|
onError,
|
|
63
|
-
|
|
64
|
-
|
|
28
|
+
onLoad,
|
|
29
|
+
onPress,
|
|
30
|
+
onReloadPress,
|
|
31
|
+
reloadButtonVisible = false
|
|
65
32
|
} = props;
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const handleError = (0, _react.useCallback)(() => {
|
|
75
|
-
errorCount.current = errorCount.current + 1;
|
|
76
|
-
const now = new Date();
|
|
77
|
-
const utcNow = now.getTime() + now.getTimezoneOffset() * 60 * 1000;
|
|
78
|
-
const expired = new Date(expiresAt).getTime() <= utcNow;
|
|
79
|
-
onError && onError({
|
|
80
|
-
sortKey,
|
|
81
|
-
count: errorCount.current,
|
|
82
|
-
expired
|
|
83
|
-
});
|
|
84
|
-
}, [errorCount.current]);
|
|
85
|
-
const onReloadPress = (0, _react.useCallback)(() => {
|
|
86
|
-
errorCount.current = 1;
|
|
87
|
-
onError && onError({
|
|
88
|
-
sortKey,
|
|
89
|
-
count: errorCount.current,
|
|
90
|
-
expired: false
|
|
91
|
-
});
|
|
92
|
-
}, [sortKey]);
|
|
93
|
-
const viewStyle = {
|
|
94
|
-
width: '100%',
|
|
95
|
-
height,
|
|
96
|
-
..._reactNative.Platform.select({
|
|
97
|
-
web: {
|
|
98
|
-
'cursor': 'default'
|
|
99
|
-
}
|
|
100
|
-
})
|
|
101
|
-
};
|
|
102
|
-
const imageStyle = {
|
|
103
|
-
width,
|
|
104
|
-
height
|
|
105
|
-
};
|
|
106
|
-
const Placeholder = (0, _react.useCallback)(props => {
|
|
107
|
-
const {
|
|
108
|
-
children,
|
|
109
|
-
failed
|
|
110
|
-
} = props;
|
|
111
|
-
|
|
112
|
-
if (!(isViewable || isLoaded) || failed || (itemState === null || itemState === void 0 ? void 0 : itemState.state) === _ComicViewerProps.STATE.INIT) {
|
|
113
|
-
return /*#__PURE__*/_react.default.createElement(_reactNative.View, {
|
|
114
|
-
style: [viewStyle, styles.init]
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (errorCount.current >= errorRetryCount) {
|
|
119
|
-
return /*#__PURE__*/_react.default.createElement(_reactNative.View, {
|
|
120
|
-
style: [viewStyle, styles.reload]
|
|
121
|
-
}, /*#__PURE__*/_react.default.createElement(_core.Spacer, {
|
|
122
|
-
size: 20
|
|
123
|
-
}), /*#__PURE__*/_react.default.createElement(_core.IconButton, {
|
|
124
|
-
children: /*#__PURE__*/_react.default.createElement(_icons.Restart, {
|
|
125
|
-
fill: '#ffffff'
|
|
126
|
-
}),
|
|
127
|
-
style: {
|
|
128
|
-
width: 48,
|
|
129
|
-
height: 48,
|
|
130
|
-
borderRadius: 24,
|
|
131
|
-
color: '#ffffff',
|
|
132
|
-
backgroundColor: '#767676'
|
|
133
|
-
},
|
|
134
|
-
onPress: onReloadPress
|
|
135
|
-
}));
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return children;
|
|
139
|
-
}, [isViewable, isLoaded, errorCount.current, url, onItemPress]);
|
|
140
|
-
(0, _react.useEffect)(() => {
|
|
141
|
-
if ((itemState === null || itemState === void 0 ? void 0 : itemState.state) === _ComicViewerProps.STATE.INIT) {
|
|
142
|
-
getNextPage === null || getNextPage === void 0 ? void 0 : getNextPage(sortKey);
|
|
33
|
+
const styles = {
|
|
34
|
+
view: {
|
|
35
|
+
height,
|
|
36
|
+
width: '100%'
|
|
37
|
+
},
|
|
38
|
+
image: {
|
|
39
|
+
height,
|
|
40
|
+
width
|
|
143
41
|
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
42
|
+
};
|
|
43
|
+
const error = reloadButtonVisible ? /*#__PURE__*/_react.default.createElement(_ReloadButton.default, {
|
|
44
|
+
onPress: onReloadPress
|
|
45
|
+
}) : null;
|
|
46
|
+
const placeholder = (0, _react.useMemo)(() => /*#__PURE__*/_react.default.createElement(_reactNative.Image, {
|
|
47
|
+
source: require('./checkered-loading.jpg'),
|
|
48
|
+
resizeMode: "repeat",
|
|
49
|
+
style: styles.image
|
|
50
|
+
}), [width]);
|
|
51
|
+
return /*#__PURE__*/_react.default.createElement(_reactNative.TouchableWithoutFeedback, {
|
|
52
|
+
onPress: onPress
|
|
148
53
|
}, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
|
|
149
|
-
style:
|
|
54
|
+
style: styles.view
|
|
150
55
|
}, /*#__PURE__*/_react.default.createElement(_core.Image, {
|
|
151
|
-
disableOutline: true,
|
|
152
|
-
key: sortKey,
|
|
153
|
-
disableLongClick: true,
|
|
154
56
|
disableDrag: true,
|
|
57
|
+
disableLongClick: true,
|
|
58
|
+
disableOutline: true,
|
|
59
|
+
error: error,
|
|
60
|
+
onError: onError,
|
|
155
61
|
onLoad: onLoad,
|
|
156
|
-
onError: handleError,
|
|
157
62
|
loading: 'eager',
|
|
63
|
+
placeholder: placeholder,
|
|
158
64
|
source: {
|
|
159
65
|
uri: url
|
|
160
66
|
},
|
|
161
|
-
style: imageStyle,
|
|
162
67
|
square: true,
|
|
163
|
-
|
|
68
|
+
style: (0, _core.css)([{
|
|
69
|
+
alignSelf: 'center'
|
|
70
|
+
}, styles.image])
|
|
164
71
|
})));
|
|
165
72
|
}
|
|
166
73
|
|
|
167
|
-
|
|
168
|
-
var _prevProps$props$item, _nextProps$props$item;
|
|
169
|
-
|
|
170
|
-
if (prevProps.props.isViewable !== nextProps.props.isViewable) {
|
|
171
|
-
return false;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (prevProps.props.url !== nextProps.props.url) {
|
|
175
|
-
return false;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (prevProps.props.width !== nextProps.props.width) {
|
|
179
|
-
return false;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
if (((_prevProps$props$item = prevProps.props.itemState) === null || _prevProps$props$item === void 0 ? void 0 : _prevProps$props$item.state) !== ((_nextProps$props$item = nextProps.props.itemState) === null || _nextProps$props$item === void 0 ? void 0 : _nextProps$props$item.state)) {
|
|
183
|
-
return false;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return true;
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
exports.default = _default;
|
|
74
|
+
;
|
|
190
75
|
//# sourceMappingURL=ViewerItem.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useStyles","theme","useTheme","root","display","flexDirection","justifyContent","init","backgroundColor","palette","paper","grey","failed","reload","alignItems","ViewerItem","props","expiresAt","errorRetryCount","height","itemState","isViewable","sortKey","url","width","getNextPage","onError","onLoaded","onItemPress","isLoaded","setIsLoaded","useState","styles","errorCount","useRef","R","defaultTo","error","count","onLoad","useCallback","current","handleError","now","Date","utcNow","getTime","getTimezoneOffset","expired","onReloadPress","viewStyle","Platform","select","web","imageStyle","Placeholder","children","state","STATE","INIT","borderRadius","color","useEffect","uri","React","memo","prevProps","nextProps"],"sources":["ViewerItem.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { Platform, TouchableOpacity, View } from 'react-native';\nimport * as R from 'ramda';\nimport type { PlaceholderProps } from '@fountain-ui/core';\nimport { IconButton, Image, Spacer, useTheme } from '@fountain-ui/core';\nimport { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';\nimport { Restart } from '@fountain-ui/icons';\nimport ComicViewerItemProps from './ComicViewerItemProps';\nimport { STATE } from './ComicViewerProps';\n\ntype PlaceholderStyles = NamedStylesStringUnion<'init' | 'failed' | 'reload' | 'root'>;\n\nconst useStyles: UseStyles<PlaceholderStyles> = function (): PlaceholderStyles {\n const theme = useTheme();\n\n return {\n root: {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'center',\n },\n init: {\n backgroundColor: theme.palette.paper.grey,\n },\n failed: {\n backgroundColor: theme.palette.paper.grey,\n },\n reload: {\n backgroundColor: theme.palette.paper.grey,\n display: 'flex',\n alignItems: 'center',\n },\n };\n};\n\nfunction ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {\n const {\n expiresAt,\n errorRetryCount = 3,\n height,\n itemState,\n isViewable,\n sortKey,\n url,\n width,\n getNextPage,\n onError,\n onLoaded,\n onItemPress,\n } = props;\n\n const [isLoaded, setIsLoaded] = useState(false);\n\n const styles = useStyles();\n\n const errorCount = useRef<number>(R.defaultTo(0)(itemState?.error?.count));\n\n const onLoad = useCallback(() => {\n errorCount.current = 0;\n\n setIsLoaded(true);\n\n onLoaded && onLoaded(sortKey);\n }, [sortKey]);\n\n const handleError = useCallback(() => {\n errorCount.current = errorCount.current + 1;\n\n const now = new Date();\n const utcNow = now.getTime() + (now.getTimezoneOffset() * 60 * 1000);\n const expired = new Date(expiresAt).getTime() <= utcNow;\n\n onError && onError({\n sortKey,\n count: errorCount.current,\n expired,\n });\n }, [errorCount.current]);\n\n const onReloadPress = useCallback(() => {\n errorCount.current = 1;\n\n onError && onError({\n sortKey,\n count: errorCount.current,\n expired: false,\n });\n }, [sortKey]);\n\n const viewStyle = {\n width: '100%',\n height,\n ...Platform.select({\n web: { 'cursor': 'default' },\n }),\n };\n\n const imageStyle = { width, height };\n\n const Placeholder = useCallback((props: PlaceholderProps) => {\n const { children, failed } = props;\n\n if (!(isViewable || isLoaded)\n || failed\n || itemState?.state === STATE.INIT\n ) {\n return <View style={[\n viewStyle,\n styles.init,\n ]}/>;\n }\n\n if (errorCount.current >= errorRetryCount) {\n return <View style={[\n viewStyle,\n styles.reload,\n ]}>\n <Spacer size={20}/>\n\n <IconButton\n children={<Restart fill={'#ffffff'}/>}\n style={{\n width: 48,\n height: 48,\n borderRadius: 24,\n color: '#ffffff',\n backgroundColor: '#767676',\n }}\n onPress={onReloadPress}\n />\n </View>;\n }\n\n return children;\n }, [isViewable, isLoaded, errorCount.current, url, onItemPress]);\n\n useEffect(() => {\n if (itemState?.state === STATE.INIT) {\n getNextPage?.(sortKey);\n }\n }, []);\n\n return (\n <TouchableOpacity\n activeOpacity={1}\n onPress={onItemPress}\n >\n <View\n style={[\n styles.root,\n viewStyle,\n ]}\n >\n <Image\n disableOutline={true}\n key={sortKey}\n disableLongClick={true}\n disableDrag={true}\n onLoad={onLoad}\n onError={handleError}\n loading={'eager'}\n source={{ uri: url }}\n style={imageStyle}\n square={true}\n Placeholder={Placeholder}\n />\n </View>\n </TouchableOpacity>\n );\n}\n\nexport default React.memo(ViewerItem, (prevProps, nextProps) => {\n if (prevProps.props.isViewable !== nextProps.props.isViewable) {\n return false;\n }\n\n if (prevProps.props.url !== nextProps.props.url) {\n return false;\n }\n\n if (prevProps.props.width !== nextProps.props.width) {\n return false;\n }\n\n if (prevProps.props.itemState?.state !== nextProps.props.itemState?.state) {\n return false;\n }\n\n return true;\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["ViewerItem","props","height","url","width","onError","onLoad","onPress","onReloadPress","reloadButtonVisible","styles","view","image","error","placeholder","useMemo","require","uri","css","alignSelf"],"sources":["ViewerItem.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\nimport { Image, TouchableWithoutFeedback, View } from 'react-native';\nimport { css, Image as FuiImage, ImageProps } from '@fountain-ui/core';\nimport ReloadButton from './ReloadButton';\n\nexport interface ViewerItemProps {\n /**\n * Image width.\n */\n width: number;\n\n /**\n * Image height.\n */\n height: number;\n\n /**\n * Image sourceUrl for displaying.\n */\n url?: string;\n\n /**\n * Error handler.\n */\n onError?: ImageProps['onError'];\n\n /**\n * Load handler.\n */\n onLoad?: ImageProps['onLoad'];\n\n /**\n * Handle Reload button press event.\n */\n onReloadPress?: ImageProps['onError'];\n\n /**\n * Handle item press event.\n */\n onPress?: () => void;\n\n /**\n * If true, reload button visible.\n * @default false\n */\n reloadButtonVisible?: boolean;\n}\n\nexport default function ViewerItem(props: ViewerItemProps) {\n const {\n height,\n url,\n width,\n onError,\n onLoad,\n onPress,\n onReloadPress,\n reloadButtonVisible = false,\n } = props;\n\n const styles = {\n view: {\n height,\n width: '100%',\n },\n image: {\n height,\n width,\n },\n };\n\n const error = reloadButtonVisible ? <ReloadButton onPress={onReloadPress}/> : null;\n\n const placeholder = useMemo(() => <Image\n source={require('./checkered-loading.jpg')}\n resizeMode=\"repeat\"\n style={styles.image}\n />, [width]);\n\n return (\n <TouchableWithoutFeedback onPress={onPress}>\n <View style={styles.view}>\n <FuiImage\n disableDrag={true}\n disableLongClick={true}\n disableOutline={true}\n error={error}\n onError={onError}\n onLoad={onLoad}\n loading={'eager'}\n placeholder={placeholder}\n source={{ uri: url }}\n square={true}\n style={css([\n { alignSelf: 'center' },\n styles.image,\n ])}\n />\n </View>\n </TouchableWithoutFeedback>\n );\n};\n"],"mappings":";;;;;;;AAAA;;AACA;;AACA;;AACA;;;;;;;;AA6Ce,SAASA,UAAT,CAAoBC,KAApB,EAA4C;EACvD,MAAM;IACFC,MADE;IAEFC,GAFE;IAGFC,KAHE;IAIFC,OAJE;IAKFC,MALE;IAMFC,OANE;IAOFC,aAPE;IAQFC,mBAAmB,GAAG;EARpB,IASFR,KATJ;EAWA,MAAMS,MAAM,GAAG;IACXC,IAAI,EAAE;MACFT,MADE;MAEFE,KAAK,EAAE;IAFL,CADK;IAKXQ,KAAK,EAAE;MACHV,MADG;MAEHE;IAFG;EALI,CAAf;EAWA,MAAMS,KAAK,GAAGJ,mBAAmB,gBAAG,6BAAC,qBAAD;IAAc,OAAO,EAAED;EAAvB,EAAH,GAA6C,IAA9E;EAEA,MAAMM,WAAW,GAAG,IAAAC,cAAA,EAAQ,mBAAM,6BAAC,kBAAD;IAC9B,MAAM,EAAEC,OAAO,CAAC,yBAAD,CADe;IAE9B,UAAU,EAAC,QAFmB;IAG9B,KAAK,EAAEN,MAAM,CAACE;EAHgB,EAAd,EAIhB,CAACR,KAAD,CAJgB,CAApB;EAMA,oBACI,6BAAC,qCAAD;IAA0B,OAAO,EAAEG;EAAnC,gBACI,6BAAC,iBAAD;IAAM,KAAK,EAAEG,MAAM,CAACC;EAApB,gBACI,6BAAC,WAAD;IACI,WAAW,EAAE,IADjB;IAEI,gBAAgB,EAAE,IAFtB;IAGI,cAAc,EAAE,IAHpB;IAII,KAAK,EAAEE,KAJX;IAKI,OAAO,EAAER,OALb;IAMI,MAAM,EAAEC,MANZ;IAOI,OAAO,EAAE,OAPb;IAQI,WAAW,EAAEQ,WARjB;IASI,MAAM,EAAE;MAAEG,GAAG,EAAEd;IAAP,CATZ;IAUI,MAAM,EAAE,IAVZ;IAWI,KAAK,EAAE,IAAAe,SAAA,EAAI,CACP;MAAEC,SAAS,EAAE;IAAb,CADO,EAEPT,MAAM,CAACE,KAFA,CAAJ;EAXX,EADJ,CADJ,CADJ;AAsBH;;AAAA"}
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export { default } from './ComicViewer';\nexport type {
|
|
1
|
+
{"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export { default } from './ComicViewer';\nexport type { Dimension, default as ComicViewerProps } from './ComicViewerProps';\nexport type { ViewerItemProps } from './ViewerItem';\n"],"mappings":";;;;;;;;;;;;AAAA"}
|
|
@@ -3,183 +3,238 @@ function _extends() { _extends = Object.assign ? Object.assign.bind() : function
|
|
|
3
3
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
4
|
import { FlatList } from 'react-native';
|
|
5
5
|
import * as R from 'ramda';
|
|
6
|
-
import {
|
|
6
|
+
import { useDebounce } from '@fountain-ui/core';
|
|
7
7
|
import ViewerItem from './ViewerItem';
|
|
8
8
|
|
|
9
|
-
const getItemHeights = items => R.map(content => content.height)(items);
|
|
10
|
-
|
|
11
9
|
const appender = (left, right) => [left + right, left + right];
|
|
12
10
|
|
|
13
|
-
const getHeightAccum =
|
|
11
|
+
const getHeightAccum = heights => R.mapAccum(appender, 0, heights);
|
|
12
|
+
|
|
13
|
+
const keyExtractor = item => String(item.index);
|
|
14
|
+
|
|
15
|
+
const createInitialImageState = dimension => ({
|
|
16
|
+
isNewUrlIncoming: false,
|
|
17
|
+
totalErrorCount: 0,
|
|
18
|
+
dimension
|
|
19
|
+
});
|
|
14
20
|
|
|
15
|
-
const
|
|
21
|
+
const mapImageStateToItemState = (index, imageState, autoHandleErrorCount) => {
|
|
22
|
+
var _imageState$urlState, _imageState$urlState2;
|
|
16
23
|
|
|
24
|
+
return {
|
|
25
|
+
index,
|
|
26
|
+
url: (_imageState$urlState = imageState.urlState) === null || _imageState$urlState === void 0 ? void 0 : _imageState$urlState.url,
|
|
27
|
+
reloadButtonVisible: ((_imageState$urlState2 = imageState.urlState) === null || _imageState$urlState2 === void 0 ? void 0 : _imageState$urlState2.validity) !== 'valid' && imageState.totalErrorCount >= autoHandleErrorCount,
|
|
28
|
+
dimension: imageState.dimension
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const MAXIMUM_WIDTH = 720;
|
|
33
|
+
const NUMBER_OF_ADJACENT_ITEM = 5;
|
|
17
34
|
export default function ComicViewer(props) {
|
|
18
35
|
const {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
36
|
+
debounceMillis = 100,
|
|
37
|
+
autoHandleErrorCount = 3,
|
|
38
|
+
getUrlByIndex,
|
|
22
39
|
initialNumToRender = 1,
|
|
23
40
|
initialScrollPercentage = 0,
|
|
24
41
|
itemVisiblePercentThreshold = 0,
|
|
25
|
-
|
|
26
|
-
onScroll,
|
|
42
|
+
intrinsicDimensions,
|
|
27
43
|
onItemPress,
|
|
28
|
-
|
|
29
|
-
viewerWidth,
|
|
44
|
+
viewportWidth,
|
|
30
45
|
windowSize = 3,
|
|
31
|
-
pageUnit,
|
|
32
|
-
ListFooterComponent,
|
|
33
46
|
...otherProps
|
|
34
47
|
} = props;
|
|
35
48
|
const flatListRef = useRef(null);
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
const debounceTimeout = useRef(null);
|
|
50
|
+
const maybeLoadableItemsIndexRange = useRef([-1, 0]);
|
|
51
|
+
const actualImageWidth = Math.min(viewportWidth, MAXIMUM_WIDTH);
|
|
52
|
+
const initialImageStates = useMemo(() => R.map(createInitialImageState, intrinsicDimensions), []);
|
|
53
|
+
const imageStatesRef = useRef(initialImageStates);
|
|
54
|
+
|
|
55
|
+
const mapImageStatesToItemStates = imageStates => {
|
|
56
|
+
return imageStates.map((image, index) => mapImageStateToItemState(index, image, autoHandleErrorCount));
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const [itemStates, setItemStates] = useState(() => {
|
|
60
|
+
return mapImageStatesToItemStates(imageStatesRef.current);
|
|
61
|
+
});
|
|
62
|
+
const renderedDimensions = useMemo(() => {
|
|
63
|
+
return R.map(intrinsicDimension => ({
|
|
64
|
+
width: actualImageWidth,
|
|
65
|
+
height: intrinsicDimension.height * actualImageWidth / intrinsicDimension.width
|
|
66
|
+
}), intrinsicDimensions);
|
|
67
|
+
}, [actualImageWidth]);
|
|
68
|
+
const layoutFromDimensions = useCallback(() => {
|
|
69
|
+
const itemHeights = R.map(dimension => dimension.height, renderedDimensions);
|
|
70
|
+
const [totalHeight, heightAccum] = getHeightAccum(itemHeights);
|
|
71
|
+
const itemOffsets = R.prepend(0, heightAccum);
|
|
72
|
+
|
|
73
|
+
const getItemLayout = (data, index) => ({
|
|
74
|
+
index,
|
|
75
|
+
length: itemHeights[index],
|
|
76
|
+
offset: itemOffsets[index]
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
totalHeight,
|
|
81
|
+
getItemLayout
|
|
82
|
+
};
|
|
83
|
+
}, [renderedDimensions]);
|
|
84
|
+
const {
|
|
85
|
+
totalHeight,
|
|
86
|
+
getItemLayout
|
|
87
|
+
} = layoutFromDimensions();
|
|
53
88
|
const viewabilityConfig = useMemo(() => ({
|
|
54
89
|
itemVisiblePercentThreshold
|
|
55
90
|
}), [itemVisiblePercentThreshold]);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
91
|
+
|
|
92
|
+
const updateImageState = updateFunction => {
|
|
93
|
+
const prevImageStates = imageStatesRef.current;
|
|
94
|
+
const newImageStates = prevImageStates.map(updateFunction);
|
|
95
|
+
imageStatesRef.current = newImageStates;
|
|
96
|
+
setItemStates(prevItemStates => {
|
|
97
|
+
const newItemStates = mapImageStatesToItemStates(newImageStates);
|
|
98
|
+
return R.equals(prevItemStates, newItemStates) ? prevItemStates : newItemStates;
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const loadUrlByIndex = async indexes => {
|
|
103
|
+
const filteredIndexes = R.filter(index => {
|
|
104
|
+
var _state$urlState;
|
|
105
|
+
|
|
106
|
+
const state = imageStatesRef.current[index];
|
|
107
|
+
return R.isNil(state.urlState) || ((_state$urlState = state.urlState) === null || _state$urlState === void 0 ? void 0 : _state$urlState.validity) === 'invalid' && !state.isNewUrlIncoming;
|
|
108
|
+
}, indexes);
|
|
109
|
+
updateImageState((imageState, i) => {
|
|
110
|
+
return R.includes(i, filteredIndexes) ? { ...imageState,
|
|
111
|
+
isNewUrlIncoming: true
|
|
112
|
+
} : imageState;
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
const urls = await getUrlByIndex(filteredIndexes);
|
|
117
|
+
updateImageState((imageState, i) => {
|
|
118
|
+
const newUrl = urls === null || urls === void 0 ? void 0 : urls.get(i);
|
|
119
|
+
const urlState = imageState.urlState;
|
|
120
|
+
|
|
121
|
+
if (newUrl !== undefined && (urlState === null || urlState === void 0 ? void 0 : urlState.validity) !== 'valid') {
|
|
122
|
+
return { ...imageState,
|
|
123
|
+
urlState: {
|
|
124
|
+
url: newUrl,
|
|
125
|
+
validity: 'unknown'
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return imageState;
|
|
131
|
+
});
|
|
132
|
+
} finally {
|
|
133
|
+
updateImageState((imageState, i) => {
|
|
134
|
+
return R.includes(i, filteredIndexes) ? { ...imageState,
|
|
135
|
+
isNewUrlIncoming: false
|
|
136
|
+
} : imageState;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const loadMaybeLoadableItems = async () => {
|
|
142
|
+
const [startIndex, endIndex] = maybeLoadableItemsIndexRange.current;
|
|
143
|
+
const affectedIndexes = R.range(startIndex, endIndex);
|
|
144
|
+
await loadUrlByIndex(affectedIndexes);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const loadItemsDebounce = useDebounce(loadMaybeLoadableItems, debounceMillis);
|
|
64
148
|
const onViewableItemsChanged = useRef(_ref => {
|
|
149
|
+
var _R$head, _R$last;
|
|
150
|
+
|
|
65
151
|
let {
|
|
66
152
|
viewableItems
|
|
67
153
|
} = _ref;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const lastViewableItemSortKey = R.last(viewableItemSortKeys);
|
|
72
|
-
const firstItem = R.head(prev);
|
|
73
|
-
const lastItem = R.last(prev);
|
|
74
|
-
|
|
75
|
-
if (R.isNil(firstViewableSortKey) || R.isNil(lastViewableItemSortKey) || R.isNil(firstItem) || R.isNil(lastItem)) {
|
|
76
|
-
return prev;
|
|
77
|
-
}
|
|
154
|
+
const orderedViewableItems = R.sort((a, b) => (a.index || 0) - (b.index || 0), viewableItems);
|
|
155
|
+
const firstViewableIndex = (_R$head = R.head(orderedViewableItems)) === null || _R$head === void 0 ? void 0 : _R$head.index;
|
|
156
|
+
const lastViewableItemIndex = (_R$last = R.last(orderedViewableItems)) === null || _R$last === void 0 ? void 0 : _R$last.index;
|
|
78
157
|
|
|
79
|
-
|
|
80
|
-
const backBoundary = R.min(lastItem.sortKey, lastViewableItemSortKey + 1);
|
|
81
|
-
const viewableItemBoundary = R.range(frontBoundary, backBoundary + 1);
|
|
82
|
-
const newItems = R.map(prevItem => ({ ...prevItem,
|
|
83
|
-
isViewable: R.includes(prevItem.sortKey, viewableItemBoundary)
|
|
84
|
-
}))([...prev]);
|
|
85
|
-
return newItems;
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
const itemLoadedHandler = useCallback(sortKey => {
|
|
89
|
-
const itemState = R.find(state => state.sortKey === sortKey)(itemStates.current);
|
|
90
|
-
|
|
91
|
-
if (R.isNil(itemState)) {
|
|
158
|
+
if (R.isNil(firstViewableIndex) || R.isNil(lastViewableItemIndex)) {
|
|
92
159
|
return;
|
|
93
160
|
}
|
|
94
161
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
} = errorInfo;
|
|
162
|
+
const startIndex = R.max(firstViewableIndex - NUMBER_OF_ADJACENT_ITEM, 0);
|
|
163
|
+
const endIndex = R.min(lastViewableItemIndex + NUMBER_OF_ADJACENT_ITEM, itemStates.length - 1);
|
|
164
|
+
maybeLoadableItemsIndexRange.current = [startIndex, endIndex + 1];
|
|
165
|
+
loadItemsDebounce();
|
|
166
|
+
});
|
|
167
|
+
const renderItem = useCallback(_ref2 => {
|
|
168
|
+
var _renderedDimensions$i, _renderedDimensions$i2;
|
|
103
169
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
170
|
+
let {
|
|
171
|
+
item,
|
|
172
|
+
index
|
|
173
|
+
} = _ref2;
|
|
107
174
|
|
|
108
|
-
|
|
109
|
-
|
|
175
|
+
const onError = () => {
|
|
176
|
+
updateImageState((imageState, i) => {
|
|
177
|
+
const urlState = imageState.urlState;
|
|
110
178
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
179
|
+
if (i === index && urlState !== undefined) {
|
|
180
|
+
return { ...imageState,
|
|
181
|
+
totalErrorCount: imageState.totalErrorCount + 1,
|
|
182
|
+
urlState: { ...urlState,
|
|
183
|
+
validity: 'invalid'
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return imageState;
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
if (item.reloadButtonVisible) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
114
194
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const errorsInfo = R.map(_ref2 => {
|
|
121
|
-
let [key, value] = _ref2;
|
|
122
|
-
return value;
|
|
123
|
-
})(errorsArray);
|
|
124
|
-
onError && onError([...errorsInfo]);
|
|
125
|
-
errors.current.clear();
|
|
195
|
+
const [startIndex, endIndex] = maybeLoadableItemsIndexRange.current;
|
|
196
|
+
|
|
197
|
+
if (index >= startIndex || index < endIndex) {
|
|
198
|
+
loadItemsDebounce();
|
|
199
|
+
}
|
|
126
200
|
};
|
|
127
201
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}
|
|
202
|
+
const onReloadPress = () => {
|
|
203
|
+
const [startIndex, endIndex] = maybeLoadableItemsIndexRange.current;
|
|
131
204
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
debounceTimeOut.current = setTimeout(handleError, errorDebounceMillis);
|
|
136
|
-
}
|
|
137
|
-
}, [errors.current, itemStates]);
|
|
138
|
-
const renderItem = useCallback(_ref3 => {
|
|
139
|
-
let {
|
|
140
|
-
item
|
|
141
|
-
} = _ref3;
|
|
142
|
-
const itemState = R.find(state => state.sortKey === item.sortKey)(itemStates.current);
|
|
143
|
-
const props = { ...item,
|
|
144
|
-
itemState,
|
|
145
|
-
errorRetryCount,
|
|
146
|
-
onError: itemErrorHandler,
|
|
147
|
-
onLoaded: itemLoadedHandler,
|
|
148
|
-
onItemPress,
|
|
149
|
-
getNextPage
|
|
205
|
+
if (index >= startIndex || index < endIndex) {
|
|
206
|
+
loadUrlByIndex([index]);
|
|
207
|
+
}
|
|
150
208
|
};
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (currentData && itemState && itemState.state !== STATE.LOADED && currentData.url !== prevItem.url) {
|
|
162
|
-
itemState.state = STATE.URL_LOADED;
|
|
163
|
-
return { ...prevItem,
|
|
164
|
-
url: currentData.url,
|
|
165
|
-
expiresAt: currentData.expiresAt
|
|
209
|
+
|
|
210
|
+
const onLoad = () => {
|
|
211
|
+
updateImageState((imageState, i) => {
|
|
212
|
+
const urlState = imageState.urlState;
|
|
213
|
+
|
|
214
|
+
if (i === index && urlState !== undefined) {
|
|
215
|
+
return { ...imageState,
|
|
216
|
+
urlState: { ...urlState,
|
|
217
|
+
validity: 'valid'
|
|
218
|
+
}
|
|
166
219
|
};
|
|
167
220
|
}
|
|
168
221
|
|
|
169
|
-
return
|
|
170
|
-
})
|
|
171
|
-
|
|
222
|
+
return imageState;
|
|
223
|
+
});
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
return /*#__PURE__*/React.createElement(ViewerItem, {
|
|
227
|
+
onError: onError,
|
|
228
|
+
onLoad: onLoad,
|
|
229
|
+
onPress: onItemPress,
|
|
230
|
+
onReloadPress: onReloadPress,
|
|
231
|
+
url: item.url,
|
|
232
|
+
width: ((_renderedDimensions$i = renderedDimensions[index]) === null || _renderedDimensions$i === void 0 ? void 0 : _renderedDimensions$i.width) ?? 0,
|
|
233
|
+
height: ((_renderedDimensions$i2 = renderedDimensions[index]) === null || _renderedDimensions$i2 === void 0 ? void 0 : _renderedDimensions$i2.height) ?? 0,
|
|
234
|
+
reloadButtonVisible: item.reloadButtonVisible
|
|
172
235
|
});
|
|
173
|
-
}, [
|
|
174
|
-
useEffect(() => {
|
|
175
|
-
const newItems = R.map(item => ({ ...item,
|
|
176
|
-
width: imageWidth,
|
|
177
|
-
height: item.height * imageWidth / item.width
|
|
178
|
-
}))(items);
|
|
179
|
-
setItems(newItems);
|
|
180
|
-
}, [imageWidth]);
|
|
236
|
+
}, [onItemPress, renderedDimensions]);
|
|
181
237
|
useEffect(() => {
|
|
182
|
-
const totalHeight = itemHeightAccum[0];
|
|
183
238
|
const offset = Math.floor(initialScrollPercentage / 100 * totalHeight);
|
|
184
239
|
|
|
185
240
|
if (flatListRef.current) {
|
|
@@ -188,19 +243,18 @@ export default function ComicViewer(props) {
|
|
|
188
243
|
animated: false
|
|
189
244
|
});
|
|
190
245
|
}
|
|
191
|
-
}, [
|
|
246
|
+
}, []);
|
|
192
247
|
return /*#__PURE__*/React.createElement(FlatList, _extends({
|
|
193
|
-
data:
|
|
248
|
+
data: itemStates,
|
|
194
249
|
getItemLayout: getItemLayout,
|
|
195
250
|
initialNumToRender: initialNumToRender,
|
|
196
251
|
keyExtractor: keyExtractor,
|
|
197
252
|
onViewableItemsChanged: onViewableItemsChanged.current,
|
|
198
|
-
onScroll: onScroll,
|
|
199
253
|
ref: flatListRef,
|
|
254
|
+
removeClippedSubviews: false,
|
|
200
255
|
renderItem: renderItem,
|
|
201
256
|
viewabilityConfig: viewabilityConfig,
|
|
202
|
-
windowSize: windowSize
|
|
203
|
-
ListFooterComponent: ListFooterComponent
|
|
257
|
+
windowSize: windowSize
|
|
204
258
|
}, otherProps));
|
|
205
259
|
}
|
|
206
260
|
;
|