@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.
Files changed (41) hide show
  1. package/build/commonjs/ComicViewer/ComicViewer.js +196 -143
  2. package/build/commonjs/ComicViewer/ComicViewer.js.map +1 -1
  3. package/build/commonjs/ComicViewer/ComicViewerProps.js +0 -12
  4. package/build/commonjs/ComicViewer/ComicViewerProps.js.map +1 -1
  5. package/build/commonjs/ComicViewer/EncodedTile.js +10 -0
  6. package/build/commonjs/ComicViewer/EncodedTile.js.map +1 -0
  7. package/build/commonjs/ComicViewer/ReloadButton.js +48 -0
  8. package/build/commonjs/ComicViewer/ReloadButton.js.map +1 -0
  9. package/build/commonjs/ComicViewer/ViewerItem.js +41 -173
  10. package/build/commonjs/ComicViewer/ViewerItem.js.map +1 -1
  11. package/build/commonjs/ComicViewer/index.js.map +1 -1
  12. package/build/module/ComicViewer/ComicViewer.js +195 -143
  13. package/build/module/ComicViewer/ComicViewer.js.map +1 -1
  14. package/build/module/ComicViewer/ComicViewerProps.js +1 -6
  15. package/build/module/ComicViewer/ComicViewerProps.js.map +1 -1
  16. package/build/module/ComicViewer/EncodedTile.js +3 -0
  17. package/build/module/ComicViewer/EncodedTile.js.map +1 -0
  18. package/build/module/ComicViewer/ReloadButton.js +33 -0
  19. package/build/module/ComicViewer/ReloadButton.js.map +1 -0
  20. package/build/module/ComicViewer/ViewerItem.js +42 -173
  21. package/build/module/ComicViewer/ViewerItem.js.map +1 -1
  22. package/build/module/ComicViewer/index.js.map +1 -1
  23. package/build/typescript/ComicViewer/ComicViewer.d.ts +1 -1
  24. package/build/typescript/ComicViewer/ComicViewerProps.d.ts +15 -90
  25. package/build/typescript/ComicViewer/EncodedTile.d.ts +2 -0
  26. package/build/typescript/ComicViewer/ReloadButton.d.ts +6 -0
  27. package/build/typescript/ComicViewer/ViewerItem.d.ts +37 -7
  28. package/build/typescript/ComicViewer/index.d.ts +2 -2
  29. package/package.json +2 -2
  30. package/src/ComicViewer/ComicViewer.tsx +210 -157
  31. package/src/ComicViewer/ComicViewerProps.ts +15 -107
  32. package/src/ComicViewer/EncodedTile.ts +3 -0
  33. package/src/ComicViewer/ReloadButton.tsx +36 -0
  34. package/src/ComicViewer/ViewerItem.tsx +82 -184
  35. package/src/ComicViewer/index.ts +2 -2
  36. package/build/commonjs/ComicViewer/ComicViewerItemProps.js +0 -6
  37. package/build/commonjs/ComicViewer/ComicViewerItemProps.js.map +0 -1
  38. package/build/module/ComicViewer/ComicViewerItemProps.js +0 -2
  39. package/build/module/ComicViewer/ComicViewerItemProps.js.map +0 -1
  40. package/build/typescript/ComicViewer/ComicViewerItemProps.d.ts +0 -34
  41. 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
- ComicViewerItemData,
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 = (itemHeights: number[]): [number, number[]] => R.mapAccum(appender, 0, itemHeights);
17
-
18
- const keyExtractor = <T, >(item: ComicViewerItemProps<T>) => `${item.sortKey}`;
19
-
20
- export default function ComicViewer<T>(props: ComicViewerProps<T>) {
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
- data,
23
- errorDebounceMillis = 500,
24
- errorRetryCount = 3,
25
- responseTimestamp,
55
+ debounceMillis = 100,
56
+ autoHandleErrorCount = 3,
57
+ getUrlByIndex,
26
58
  initialNumToRender = 1,
27
59
  initialScrollPercentage = 0,
28
60
  itemVisiblePercentThreshold = 0,
29
- onError,
30
- onScroll,
61
+ intrinsicDimensions,
31
62
  onItemPress,
32
- getNextPage,
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 errors = useRef<Map<number, ErrorInfo>>(new Map());
70
+ const maybeLoadableItemsIndexRange = useRef<[number, number]>([-1, 0]);
71
+
72
+ const actualImageWidth = Math.min(viewportWidth, MAXIMUM_WIDTH);
43
73
 
44
- const debounceTimeOut = useRef<NodeJS.Timeout | null>(null);
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 imageWidth = Math.min(viewerWidth, 720);
47
- const initialItems = R.map((itemData: ComicViewerItemData<T>) => ({
48
- ...itemData,
49
- isViewable: false,
50
- width: imageWidth,
51
- height: (itemData.height * imageWidth) / itemData.width,
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 [items, setItems] = useState<ComicViewerItemProps<T>[]>(initialItems);
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
- const initialItemState: ComicViewerItemState[] = R.map((itemData: ComicViewerItemData<T>) => ({
57
- sortKey: itemData.sortKey,
58
- state: R.isNil(itemData.id) ? STATE.INIT : STATE.URL_LOADED,
59
- }))(data);
99
+ const getItemLayout = (data: any, index: number) => ({
100
+ index,
101
+ length: itemHeights[index],
102
+ offset: itemOffsets[index],
103
+ });
60
104
 
61
- const itemStates = useRef<Array<ComicViewerItemState>>(initialItemState);
105
+ return {
106
+ totalHeight,
107
+ getItemLayout,
108
+ };
109
+ }, [renderedDimensions]);
62
110
 
63
- const itemHeights = [...getItemHeights(items)];
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 getItemLayout = useCallback((data: any, index: number) => {
71
- const offsets = R.prepend(0, itemHeightAccum[1]);
117
+ const updateImageState = (updateFunction: (prev: ImageState, index: number) => ImageState) => {
118
+ const prevImageStates = imageStatesRef.current;
119
+ const newImageStates = prevImageStates.map(updateFunction);
72
120
 
73
- return {
74
- length: itemHeights[index],
75
- offset: offsets[index],
76
- index,
77
- };
78
- }, [itemHeights]);
79
-
80
- const onViewableItemsChanged = useRef(({ viewableItems }: {
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
- const frontBoundary = R.max(firstItem.sortKey, firstViewableSortKey - 1);
99
- const backBoundary = R.min(lastItem.sortKey, lastViewableItemSortKey + 1);
130
+ const loadUrlByIndex = async (indexes: number[]) => {
131
+ const filteredIndexes = R.filter(index => {
132
+ const state = imageStatesRef.current[index];
100
133
 
101
- const viewableItemBoundary = R.range(frontBoundary, backBoundary + 1);
102
- const newItems = R.map((prevItem: ComicViewerItemProps<T>) => ({
103
- ...prevItem,
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
- return newItems;
138
+ updateImageState((imageState, i) => {
139
+ return R.includes(i, filteredIndexes)
140
+ ? { ...imageState, isNewUrlIncoming: true }
141
+ : imageState;
108
142
  });
109
- });
110
143
 
111
- const itemLoadedHandler = useCallback((sortKey: number) => {
112
- const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === sortKey)(itemStates.current);
144
+ try {
145
+ const urls = await getUrlByIndex(filteredIndexes);
113
146
 
114
- if (R.isNil(itemState)) {
115
- return;
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
- itemState.state = STATE.LOADED;
119
- itemState.error = undefined;
120
- }, [itemStates]);
172
+ const loadMaybeLoadableItems = async () => {
173
+ const [startIndex, endIndex] = maybeLoadableItemsIndexRange.current;
174
+ const affectedIndexes = R.range(startIndex, endIndex);
121
175
 
122
- const itemErrorHandler = useCallback((errorInfo: ErrorInfo) => {
123
- const { sortKey, count } = errorInfo;
176
+ await loadUrlByIndex(affectedIndexes);
177
+ };
124
178
 
125
- if (count >= errorRetryCount) {
126
- return;
127
- }
179
+ const loadItemsDebounce = useDebounce(loadMaybeLoadableItems, debounceMillis);
128
180
 
129
- errors.current.set(sortKey, errorInfo);
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 itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === sortKey)(itemStates.current);
184
+ const firstViewableIndex = R.head(orderedViewableItems)?.index;
185
+ const lastViewableItemIndex = R.last(orderedViewableItems)?.index;
132
186
 
133
- if (R.isNil(itemState)) {
187
+ if (R.isNil(firstViewableIndex) || R.isNil(lastViewableItemIndex)) {
134
188
  return;
135
189
  }
136
190
 
137
- itemState.state = STATE.FAIL;
138
- itemState.error = errorInfo;
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
- const handleError = () => {
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
- onError && onError([...errorsInfo]);
145
- errors.current.clear();
146
- };
196
+ loadItemsDebounce();
197
+ });
147
198
 
148
- if (debounceTimeOut.current) {
149
- clearTimeout(debounceTimeOut.current);
150
- }
199
+ const renderItem: ListRenderItem<ItemState> = useCallback(({ item, index }) => {
200
+ const onError = () => {
201
+ updateImageState((imageState, i) => {
202
+ const urlState = imageState.urlState;
151
203
 
152
- if (errors.current.size === pageUnit) {
153
- handleError();
154
- } else {
155
- debounceTimeOut.current = setTimeout(handleError, errorDebounceMillis);
156
- }
157
- }, [errors.current, itemStates]);
158
-
159
- const renderItem: ListRenderItem<ComicViewerItemProps<T>> = useCallback(({ item }) => {
160
- const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === item.sortKey)(itemStates.current);
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
- return <ViewerItem props={props}/>;
174
- }, [responseTimestamp, itemErrorHandler, itemLoadedHandler, onItemPress]);
215
+ return imageState;
216
+ });
175
217
 
176
- useEffect(() => {
177
- setItems((prev: ComicViewerItemProps<T>[]) => {
178
- return R.map((prevItem: ComicViewerItemProps<T>) => {
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
- if (currentData
183
- && currentData.id
184
- && itemState
185
- && itemState.state !== STATE.LOADED) {
222
+ const [startIndex, endIndex] = maybeLoadableItemsIndexRange.current;
223
+ if (index >= startIndex || index < endIndex) {
224
+ loadItemsDebounce();
225
+ }
226
+ };
186
227
 
187
- itemState.state = STATE.URL_LOADED;
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
- ...prevItem,
191
- url: currentData.url,
192
- expiresAt: currentData.expiresAt,
241
+ ...imageState,
242
+ urlState: {
243
+ ...urlState,
244
+ validity: 'valid',
245
+ },
193
246
  };
194
247
  }
195
248
 
196
- return prevItem;
197
- })([...prev]);
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
- setItems(newItems);
210
- }, [imageWidth]);
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
- }, [flatListRef.current]);
273
+ }, []);
220
274
 
221
275
  return (
222
276
  <FlatList
223
- data={items}
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 const STATE = {
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<T> extends ComponentProps <{
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 500
13
+ * @default 100
94
14
  */
95
- errorDebounceMillis?: number;
15
+ debounceMillis?: number;
96
16
 
97
17
  /**
98
- * How many times retry onError when same item error occur
18
+ * How many times handle onError directly when item error occur
99
19
  * @default 3
100
20
  */
101
- errorRetryCount?: number;
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
- * Timestamp when get content response
42
+ /**
43
+ * Dimensions of each Image considering viewport.
124
44
  */
125
- responseTimestamp: number;
45
+ intrinsicDimensions: Array<Dimension>;
126
46
 
127
47
  /**
128
- * Comic viewer width.
48
+ * Width of viewport.
129
49
  */
130
- viewerWidth: number;
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
- * How many images in one page.
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
- onError?: (errors: ErrorInfo[]) => void;
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
+ }> {}