@fountain-ui/lab 2.0.0-beta.34 → 2.0.0-beta.36
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 +196 -143
- 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/EncodedTile.js +10 -0
- package/build/commonjs/ComicViewer/EncodedTile.js.map +1 -0
- package/build/commonjs/ComicViewer/ReloadButton.js +48 -0
- package/build/commonjs/ComicViewer/ReloadButton.js.map +1 -0
- package/build/commonjs/ComicViewer/ViewerItem.js +41 -173
- package/build/commonjs/ComicViewer/ViewerItem.js.map +1 -1
- package/build/commonjs/ComicViewer/index.js.map +1 -1
- package/build/module/ComicViewer/ComicViewer.js +195 -143
- 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/EncodedTile.js +3 -0
- package/build/module/ComicViewer/EncodedTile.js.map +1 -0
- package/build/module/ComicViewer/ReloadButton.js +33 -0
- package/build/module/ComicViewer/ReloadButton.js.map +1 -0
- package/build/module/ComicViewer/ViewerItem.js +42 -173
- package/build/module/ComicViewer/ViewerItem.js.map +1 -1
- 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 -90
- package/build/typescript/ComicViewer/EncodedTile.d.ts +2 -0
- 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 -157
- package/src/ComicViewer/ComicViewerProps.ts +15 -107
- package/src/ComicViewer/EncodedTile.ts +3 -0
- package/src/ComicViewer/ReloadButton.tsx +36 -0
- package/src/ComicViewer/ViewerItem.tsx +82 -184
- 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
|
@@ -1,237 +1,290 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import { FlatList, ListRenderItem, ViewToken } from 'react-native';
|
|
3
3
|
import * as R from 'ramda';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
ComicViewerItemState,
|
|
7
|
-
default as ComicViewerProps,
|
|
8
|
-
ErrorInfo,
|
|
9
|
-
STATE,
|
|
10
|
-
} from './ComicViewerProps';
|
|
11
|
-
import type ComicViewerItemProps from './ComicViewerItemProps';
|
|
4
|
+
import { useDebounce } from '@fountain-ui/core';
|
|
5
|
+
import { default as ComicViewerProps, Dimension } from './ComicViewerProps';
|
|
12
6
|
import ViewerItem from './ViewerItem';
|
|
13
7
|
|
|
14
|
-
const getItemHeights = <T, >(items: ComicViewerItemProps<T>[]): number[] => R.map((content: ComicViewerItemProps<T>) => content.height)(items);
|
|
15
8
|
const appender = (left: number, right: number): [number, number] => [left + right, left + right];
|
|
16
|
-
const getHeightAccum = (
|
|
17
|
-
|
|
18
|
-
const keyExtractor = <T, >(item:
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
const getHeightAccum = (heights: number[]): [number, number[]] => R.mapAccum(appender, 0, heights);
|
|
10
|
+
|
|
11
|
+
const keyExtractor = <T, >(item: ItemState) => String(item.index);
|
|
12
|
+
|
|
13
|
+
interface UrlState {
|
|
14
|
+
url: string;
|
|
15
|
+
validity: 'valid' | 'invalid' | 'unknown';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface ImageState {
|
|
19
|
+
urlState?: UrlState;
|
|
20
|
+
isNewUrlIncoming: boolean;
|
|
21
|
+
totalErrorCount: number;
|
|
22
|
+
dimension: Dimension;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface ItemState {
|
|
26
|
+
index: number;
|
|
27
|
+
url?: string;
|
|
28
|
+
reloadButtonVisible: boolean;
|
|
29
|
+
dimension: Dimension;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const createInitialImageState = (dimension: Dimension): ImageState => ({
|
|
33
|
+
isNewUrlIncoming: false,
|
|
34
|
+
totalErrorCount: 0,
|
|
35
|
+
dimension,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const mapImageStateToItemState = (
|
|
39
|
+
index: number,
|
|
40
|
+
imageState: ImageState,
|
|
41
|
+
autoHandleErrorCount: number,
|
|
42
|
+
): ItemState => ({
|
|
43
|
+
index,
|
|
44
|
+
url: imageState.urlState?.url,
|
|
45
|
+
reloadButtonVisible: (imageState.urlState?.validity !== 'valid') && imageState.totalErrorCount >= autoHandleErrorCount,
|
|
46
|
+
dimension: imageState.dimension,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const MAXIMUM_WIDTH = 720;
|
|
50
|
+
|
|
51
|
+
const NUMBER_OF_ADJACENT_ITEM = 5;
|
|
52
|
+
|
|
53
|
+
export default function ComicViewer(props: ComicViewerProps) {
|
|
21
54
|
const {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
responseTimestamp,
|
|
55
|
+
debounceMillis = 100,
|
|
56
|
+
autoHandleErrorCount = 3,
|
|
57
|
+
getUrlByIndex,
|
|
26
58
|
initialNumToRender = 1,
|
|
27
59
|
initialScrollPercentage = 0,
|
|
28
60
|
itemVisiblePercentThreshold = 0,
|
|
29
|
-
|
|
30
|
-
onScroll,
|
|
61
|
+
intrinsicDimensions,
|
|
31
62
|
onItemPress,
|
|
32
|
-
|
|
33
|
-
viewerWidth,
|
|
63
|
+
viewportWidth,
|
|
34
64
|
windowSize = 3,
|
|
35
|
-
pageUnit,
|
|
36
|
-
ListFooterComponent,
|
|
37
65
|
...otherProps
|
|
38
66
|
} = props;
|
|
39
67
|
|
|
40
68
|
const flatListRef = useRef<FlatList>(null);
|
|
41
69
|
|
|
42
|
-
const
|
|
70
|
+
const maybeLoadableItemsIndexRange = useRef<[number, number]>([-1, 0]);
|
|
71
|
+
|
|
72
|
+
const actualImageWidth = Math.min(viewportWidth, MAXIMUM_WIDTH);
|
|
43
73
|
|
|
44
|
-
const
|
|
74
|
+
const initialImageStates = useMemo<Array<ImageState>>(() => R.map(createInitialImageState, intrinsicDimensions), []);
|
|
75
|
+
const imageStatesRef = useRef<Array<ImageState>>(initialImageStates);
|
|
76
|
+
|
|
77
|
+
const mapImageStatesToItemStates = (imageStates: Array<ImageState>): Array<ItemState> => {
|
|
78
|
+
return imageStates.map((image, index) => mapImageStateToItemState(
|
|
79
|
+
index, image, autoHandleErrorCount,
|
|
80
|
+
));
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const [itemStates, setItemStates] = useState<Array<ItemState>>(() => {
|
|
84
|
+
return mapImageStatesToItemStates(imageStatesRef.current);
|
|
85
|
+
});
|
|
45
86
|
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}))(data);
|
|
87
|
+
const renderedDimensions = useMemo<Array<Dimension>>(() => {
|
|
88
|
+
return R.map(intrinsicDimension => ({
|
|
89
|
+
width: actualImageWidth,
|
|
90
|
+
height: (intrinsicDimension.height * actualImageWidth) / intrinsicDimension.width,
|
|
91
|
+
}), intrinsicDimensions);
|
|
92
|
+
}, [actualImageWidth]);
|
|
53
93
|
|
|
54
|
-
const
|
|
94
|
+
const layoutFromDimensions = useCallback(() => {
|
|
95
|
+
const itemHeights = R.map(dimension => dimension.height, renderedDimensions);
|
|
96
|
+
const [totalHeight, heightAccum] = getHeightAccum(itemHeights);
|
|
97
|
+
const itemOffsets = R.prepend(0, heightAccum);
|
|
55
98
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
99
|
+
const getItemLayout = (data: any, index: number) => ({
|
|
100
|
+
index,
|
|
101
|
+
length: itemHeights[index],
|
|
102
|
+
offset: itemOffsets[index],
|
|
103
|
+
});
|
|
60
104
|
|
|
61
|
-
|
|
105
|
+
return {
|
|
106
|
+
totalHeight,
|
|
107
|
+
getItemLayout,
|
|
108
|
+
};
|
|
109
|
+
}, [renderedDimensions]);
|
|
62
110
|
|
|
63
|
-
const
|
|
64
|
-
const itemHeightAccum = getHeightAccum(itemHeights);
|
|
111
|
+
const { totalHeight, getItemLayout } = layoutFromDimensions();
|
|
65
112
|
|
|
66
113
|
const viewabilityConfig = useMemo(() => ({
|
|
67
114
|
itemVisiblePercentThreshold,
|
|
68
115
|
}), [itemVisiblePercentThreshold]);
|
|
69
116
|
|
|
70
|
-
const
|
|
71
|
-
const
|
|
117
|
+
const updateImageState = (updateFunction: (prev: ImageState, index: number) => ImageState) => {
|
|
118
|
+
const prevImageStates = imageStatesRef.current;
|
|
119
|
+
const newImageStates = prevImageStates.map(updateFunction);
|
|
72
120
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
viewableItems: Array<ViewToken>,
|
|
82
|
-
}) => {
|
|
83
|
-
setItems((prev: ComicViewerItemProps<T>[]) => {
|
|
84
|
-
const viewableItemSortKeys: number[] = R.map((viewableItem: ViewToken) => viewableItem.item.sortKey)(viewableItems);
|
|
85
|
-
const firstViewableSortKey = R.head(viewableItemSortKeys);
|
|
86
|
-
const lastViewableItemSortKey = R.last(viewableItemSortKeys);
|
|
87
|
-
const firstItem = R.head(prev);
|
|
88
|
-
const lastItem = R.last(prev);
|
|
89
|
-
|
|
90
|
-
if (R.isNil(firstViewableSortKey)
|
|
91
|
-
|| R.isNil(lastViewableItemSortKey)
|
|
92
|
-
|| R.isNil(firstItem)
|
|
93
|
-
|| R.isNil(lastItem)
|
|
94
|
-
) {
|
|
95
|
-
return prev;
|
|
96
|
-
}
|
|
121
|
+
imageStatesRef.current = newImageStates;
|
|
122
|
+
|
|
123
|
+
setItemStates(prevItemStates => {
|
|
124
|
+
const newItemStates = mapImageStatesToItemStates(newImageStates);
|
|
125
|
+
|
|
126
|
+
return R.equals(prevItemStates, newItemStates) ? prevItemStates : newItemStates;
|
|
127
|
+
});
|
|
128
|
+
};
|
|
97
129
|
|
|
98
|
-
|
|
99
|
-
|
|
130
|
+
const loadUrlByIndex = async (indexes: number[]) => {
|
|
131
|
+
const filteredIndexes = R.filter(index => {
|
|
132
|
+
const state = imageStatesRef.current[index];
|
|
100
133
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
isViewable: R.includes(prevItem.sortKey, viewableItemBoundary),
|
|
105
|
-
}))([...prev]);
|
|
134
|
+
return R.isNil(state.urlState)
|
|
135
|
+
|| (state.urlState?.validity === 'invalid' && !state.isNewUrlIncoming);
|
|
136
|
+
}, indexes);
|
|
106
137
|
|
|
107
|
-
|
|
138
|
+
updateImageState((imageState, i) => {
|
|
139
|
+
return R.includes(i, filteredIndexes)
|
|
140
|
+
? { ...imageState, isNewUrlIncoming: true }
|
|
141
|
+
: imageState;
|
|
108
142
|
});
|
|
109
|
-
});
|
|
110
143
|
|
|
111
|
-
|
|
112
|
-
|
|
144
|
+
try {
|
|
145
|
+
const urls = await getUrlByIndex(filteredIndexes);
|
|
113
146
|
|
|
114
|
-
|
|
115
|
-
|
|
147
|
+
updateImageState((imageState, i) => {
|
|
148
|
+
const newUrl = urls?.get(i);
|
|
149
|
+
const urlState = imageState.urlState;
|
|
150
|
+
|
|
151
|
+
if (newUrl !== undefined && urlState?.validity !== 'valid') {
|
|
152
|
+
return {
|
|
153
|
+
...imageState,
|
|
154
|
+
urlState: {
|
|
155
|
+
url: newUrl,
|
|
156
|
+
validity: 'unknown',
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return imageState;
|
|
162
|
+
});
|
|
163
|
+
} finally {
|
|
164
|
+
updateImageState((imageState, i) => {
|
|
165
|
+
return R.includes(i, filteredIndexes)
|
|
166
|
+
? { ...imageState, isNewUrlIncoming: false }
|
|
167
|
+
: imageState;
|
|
168
|
+
});
|
|
116
169
|
}
|
|
170
|
+
};
|
|
117
171
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
172
|
+
const loadMaybeLoadableItems = async () => {
|
|
173
|
+
const [startIndex, endIndex] = maybeLoadableItemsIndexRange.current;
|
|
174
|
+
const affectedIndexes = R.range(startIndex, endIndex);
|
|
121
175
|
|
|
122
|
-
|
|
123
|
-
|
|
176
|
+
await loadUrlByIndex(affectedIndexes);
|
|
177
|
+
};
|
|
124
178
|
|
|
125
|
-
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
179
|
+
const loadItemsDebounce = useDebounce(loadMaybeLoadableItems, debounceMillis);
|
|
128
180
|
|
|
129
|
-
|
|
181
|
+
const onViewableItemsChanged = useRef(({ viewableItems }: { viewableItems: Array<ViewToken> }) => {
|
|
182
|
+
const orderedViewableItems = R.sort((a, b) => (a.index || 0) - (b.index || 0), viewableItems);
|
|
130
183
|
|
|
131
|
-
const
|
|
184
|
+
const firstViewableIndex = R.head(orderedViewableItems)?.index;
|
|
185
|
+
const lastViewableItemIndex = R.last(orderedViewableItems)?.index;
|
|
132
186
|
|
|
133
|
-
if (R.isNil(
|
|
187
|
+
if (R.isNil(firstViewableIndex) || R.isNil(lastViewableItemIndex)) {
|
|
134
188
|
return;
|
|
135
189
|
}
|
|
136
190
|
|
|
137
|
-
|
|
138
|
-
|
|
191
|
+
const startIndex = R.max(firstViewableIndex - NUMBER_OF_ADJACENT_ITEM, 0);
|
|
192
|
+
const endIndex = R.min(lastViewableItemIndex + NUMBER_OF_ADJACENT_ITEM, itemStates.length - 1);
|
|
139
193
|
|
|
140
|
-
|
|
141
|
-
const errorsArray = Array.from(errors.current.entries());
|
|
142
|
-
const errorsInfo = R.map(([key, value]: [number, ErrorInfo]) => value)(errorsArray);
|
|
194
|
+
maybeLoadableItemsIndexRange.current = [startIndex, endIndex + 1];
|
|
143
195
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
};
|
|
196
|
+
loadItemsDebounce();
|
|
197
|
+
});
|
|
147
198
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
199
|
+
const renderItem: ListRenderItem<ItemState> = useCallback(({ item, index }) => {
|
|
200
|
+
const onError = () => {
|
|
201
|
+
updateImageState((imageState, i) => {
|
|
202
|
+
const urlState = imageState.urlState;
|
|
151
203
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const props = {
|
|
163
|
-
...item,
|
|
164
|
-
itemState,
|
|
165
|
-
responseTimestamp,
|
|
166
|
-
errorRetryCount,
|
|
167
|
-
onError: itemErrorHandler,
|
|
168
|
-
onLoaded: itemLoadedHandler,
|
|
169
|
-
onItemPress,
|
|
170
|
-
getNextPage,
|
|
171
|
-
};
|
|
204
|
+
if (i === index && urlState !== undefined) {
|
|
205
|
+
return {
|
|
206
|
+
...imageState,
|
|
207
|
+
totalErrorCount: imageState.totalErrorCount + 1,
|
|
208
|
+
urlState: {
|
|
209
|
+
...urlState,
|
|
210
|
+
validity: 'invalid',
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
}
|
|
172
214
|
|
|
173
|
-
|
|
174
|
-
|
|
215
|
+
return imageState;
|
|
216
|
+
});
|
|
175
217
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const currentData: ComicViewerItemData | undefined = R.find((currentItemData: ComicViewerItemData<T>) => prevItem.sortKey === currentItemData.sortKey)(data);
|
|
180
|
-
const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === currentData?.sortKey)(itemStates.current);
|
|
218
|
+
if (item.reloadButtonVisible) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
181
221
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
222
|
+
const [startIndex, endIndex] = maybeLoadableItemsIndexRange.current;
|
|
223
|
+
if (index >= startIndex || index < endIndex) {
|
|
224
|
+
loadItemsDebounce();
|
|
225
|
+
}
|
|
226
|
+
};
|
|
186
227
|
|
|
187
|
-
|
|
228
|
+
const onReloadPress = () => {
|
|
229
|
+
const [startIndex, endIndex] = maybeLoadableItemsIndexRange.current;
|
|
230
|
+
if (index >= startIndex || index < endIndex) {
|
|
231
|
+
loadUrlByIndex([index]);
|
|
232
|
+
}
|
|
233
|
+
};
|
|
188
234
|
|
|
235
|
+
const onLoad = () => {
|
|
236
|
+
updateImageState((imageState, i) => {
|
|
237
|
+
const urlState = imageState.urlState;
|
|
238
|
+
|
|
239
|
+
if (i === index && urlState !== undefined) {
|
|
189
240
|
return {
|
|
190
|
-
...
|
|
191
|
-
|
|
192
|
-
|
|
241
|
+
...imageState,
|
|
242
|
+
urlState: {
|
|
243
|
+
...urlState,
|
|
244
|
+
validity: 'valid',
|
|
245
|
+
},
|
|
193
246
|
};
|
|
194
247
|
}
|
|
195
248
|
|
|
196
|
-
return
|
|
197
|
-
})
|
|
198
|
-
|
|
199
|
-
});
|
|
200
|
-
}, [responseTimestamp]);
|
|
201
|
-
|
|
202
|
-
useEffect(() => {
|
|
203
|
-
const newItems = R.map((item: ComicViewerItemProps<T>) => ({
|
|
204
|
-
...item,
|
|
205
|
-
width: imageWidth,
|
|
206
|
-
height: (item.height * imageWidth) / item.width,
|
|
207
|
-
}))(items);
|
|
249
|
+
return imageState;
|
|
250
|
+
});
|
|
251
|
+
};
|
|
208
252
|
|
|
209
|
-
|
|
210
|
-
|
|
253
|
+
return (
|
|
254
|
+
<ViewerItem
|
|
255
|
+
onError={onError}
|
|
256
|
+
onLoad={onLoad}
|
|
257
|
+
onPress={onItemPress}
|
|
258
|
+
onReloadPress={onReloadPress}
|
|
259
|
+
url={item.url}
|
|
260
|
+
width={renderedDimensions[index]?.width ?? 0}
|
|
261
|
+
height={renderedDimensions[index]?.height ?? 0}
|
|
262
|
+
reloadButtonVisible={item.reloadButtonVisible}
|
|
263
|
+
/>
|
|
264
|
+
);
|
|
265
|
+
}, [onItemPress, renderedDimensions]);
|
|
211
266
|
|
|
212
267
|
useEffect(() => {
|
|
213
|
-
const totalHeight = itemHeightAccum[0];
|
|
214
268
|
const offset = Math.floor((initialScrollPercentage / 100) * totalHeight);
|
|
215
269
|
|
|
216
270
|
if (flatListRef.current) {
|
|
217
271
|
flatListRef.current.scrollToOffset({ offset, animated: false });
|
|
218
272
|
}
|
|
219
|
-
}, [
|
|
273
|
+
}, []);
|
|
220
274
|
|
|
221
275
|
return (
|
|
222
276
|
<FlatList
|
|
223
|
-
data={
|
|
277
|
+
data={itemStates}
|
|
224
278
|
getItemLayout={getItemLayout}
|
|
225
279
|
initialNumToRender={initialNumToRender}
|
|
226
280
|
keyExtractor={keyExtractor}
|
|
227
281
|
onViewableItemsChanged={onViewableItemsChanged.current}
|
|
228
|
-
onScroll={onScroll}
|
|
229
282
|
ref={flatListRef}
|
|
283
|
+
removeClippedSubviews={false}
|
|
230
284
|
renderItem={renderItem}
|
|
231
285
|
viewabilityConfig={viewabilityConfig}
|
|
232
286
|
windowSize={windowSize}
|
|
233
|
-
ListFooterComponent={ListFooterComponent}
|
|
234
287
|
{...otherProps}
|
|
235
288
|
/>
|
|
236
289
|
);
|
|
237
|
-
};
|
|
290
|
+
};
|
|
@@ -2,103 +2,23 @@ import React from 'react';
|
|
|
2
2
|
import { ComponentProps } from '@fountain-ui/core';
|
|
3
3
|
import { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
|
|
4
4
|
|
|
5
|
-
export
|
|
6
|
-
INIT: 'init',
|
|
7
|
-
URL_LOADED: 'url_loaded',
|
|
8
|
-
LOADED: 'loaded',
|
|
9
|
-
FAIL: 'fail',
|
|
10
|
-
} as const;
|
|
11
|
-
|
|
12
|
-
export type LoadingState = typeof STATE[keyof typeof STATE];
|
|
13
|
-
|
|
14
|
-
export interface ComicViewerItemState{
|
|
15
|
-
/**
|
|
16
|
-
* Comic viewer item sortKey.
|
|
17
|
-
*/
|
|
18
|
-
sortKey: number;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Content's loading state.
|
|
22
|
-
*/
|
|
23
|
-
state: LoadingState;
|
|
24
|
-
|
|
25
|
-
/***
|
|
26
|
-
* Content's error Info.
|
|
27
|
-
*/
|
|
28
|
-
error?: ErrorInfo;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface ErrorInfo {
|
|
32
|
-
/**
|
|
33
|
-
* ComicViewerItemData.sortKey.
|
|
34
|
-
*/
|
|
35
|
-
sortKey: number;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Number of times an error occurred.
|
|
39
|
-
*/
|
|
40
|
-
count: number;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Content is Expired: true
|
|
44
|
-
*/
|
|
45
|
-
expired: boolean;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export type ComicViewerItemData<T = {}> = T & {
|
|
49
|
-
/**
|
|
50
|
-
* Image height.
|
|
51
|
-
*/
|
|
52
|
-
height: number;
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Unique value for identifying.
|
|
56
|
-
*/
|
|
57
|
-
id: number | undefined;
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Image sourceUrl for displaying.
|
|
61
|
-
*/
|
|
62
|
-
url: string;
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Image width.
|
|
66
|
-
*/
|
|
5
|
+
export interface Dimension {
|
|
67
6
|
width: number;
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* SortKey
|
|
71
|
-
*/
|
|
72
|
-
sortKey: number;
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Image expire date.
|
|
76
|
-
*/
|
|
77
|
-
expiresAt: string;
|
|
78
|
-
|
|
79
|
-
/***
|
|
80
|
-
* Timestamp when get content response
|
|
81
|
-
*/
|
|
82
|
-
responseTimestamp: number;
|
|
7
|
+
height: number;
|
|
83
8
|
}
|
|
84
9
|
|
|
85
|
-
export default interface ComicViewerProps
|
|
86
|
-
/**
|
|
87
|
-
* Data for render.
|
|
88
|
-
*/
|
|
89
|
-
data: ComicViewerItemData<T>[];
|
|
90
|
-
|
|
10
|
+
export default interface ComicViewerProps extends ComponentProps <{
|
|
91
11
|
/**
|
|
92
12
|
* Delay Time to call the error handler.
|
|
93
|
-
* @default
|
|
13
|
+
* @default 100
|
|
94
14
|
*/
|
|
95
|
-
|
|
15
|
+
debounceMillis?: number;
|
|
96
16
|
|
|
97
17
|
/**
|
|
98
|
-
* How many times
|
|
18
|
+
* How many times handle onError directly when item error occur
|
|
99
19
|
* @default 3
|
|
100
20
|
*/
|
|
101
|
-
|
|
21
|
+
autoHandleErrorCount?: number;
|
|
102
22
|
|
|
103
23
|
/**
|
|
104
24
|
* How many items to render in the initial batch.
|
|
@@ -119,15 +39,15 @@ export default interface ComicViewerProps<T> extends ComponentProps <{
|
|
|
119
39
|
*/
|
|
120
40
|
itemVisiblePercentThreshold?: number;
|
|
121
41
|
|
|
122
|
-
|
|
123
|
-
*
|
|
42
|
+
/**
|
|
43
|
+
* Dimensions of each Image considering viewport.
|
|
124
44
|
*/
|
|
125
|
-
|
|
45
|
+
intrinsicDimensions: Array<Dimension>;
|
|
126
46
|
|
|
127
47
|
/**
|
|
128
|
-
*
|
|
48
|
+
* Width of viewport.
|
|
129
49
|
*/
|
|
130
|
-
|
|
50
|
+
viewportWidth: number;
|
|
131
51
|
|
|
132
52
|
/**
|
|
133
53
|
* The value for FlatList windowSize.
|
|
@@ -136,21 +56,9 @@ export default interface ComicViewerProps<T> extends ComponentProps <{
|
|
|
136
56
|
windowSize?: number;
|
|
137
57
|
|
|
138
58
|
/**
|
|
139
|
-
*
|
|
140
|
-
*/
|
|
141
|
-
pageUnit: number;
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Method for getting next page contents.
|
|
145
|
-
* @param sortKey
|
|
146
|
-
*/
|
|
147
|
-
getNextPage?: (sortKey: number) => void;
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Handling all viewerItem errors at once.
|
|
151
|
-
* @param errors Array of ViewerItems errorInfo.
|
|
59
|
+
* Get contents urls by indexes.
|
|
152
60
|
*/
|
|
153
|
-
|
|
61
|
+
getUrlByIndex: (indexes: Array<number>) => Promise<Map<number, string> | undefined> ;
|
|
154
62
|
|
|
155
63
|
/**
|
|
156
64
|
* Handle scroll event.
|
|
@@ -167,4 +75,4 @@ export default interface ComicViewerProps<T> extends ComponentProps <{
|
|
|
167
75
|
* Component for comic viewer footer.
|
|
168
76
|
*/
|
|
169
77
|
ListFooterComponent?: React.ReactElement;
|
|
170
|
-
}> {}
|
|
78
|
+
}> {}
|