@fountain-ui/lab 2.0.0-beta.29 → 2.0.0-beta.30
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 +62 -33
- package/build/commonjs/ComicViewer/ComicViewer.js.map +1 -1
- package/build/commonjs/ComicViewer/ComicViewerItemProps.js.map +1 -1
- package/build/commonjs/ComicViewer/ComicViewerProps.js +12 -0
- package/build/commonjs/ComicViewer/ComicViewerProps.js.map +1 -1
- package/build/commonjs/ComicViewer/ViewerItem.js +94 -23
- package/build/commonjs/ComicViewer/ViewerItem.js.map +1 -1
- package/build/module/ComicViewer/ComicViewer.js +61 -33
- package/build/module/ComicViewer/ComicViewer.js.map +1 -1
- package/build/module/ComicViewer/ComicViewerItemProps.js.map +1 -1
- package/build/module/ComicViewer/ComicViewerProps.js +6 -1
- package/build/module/ComicViewer/ComicViewerProps.js.map +1 -1
- package/build/module/ComicViewer/ViewerItem.js +95 -25
- package/build/module/ComicViewer/ViewerItem.js.map +1 -1
- package/build/typescript/ComicViewer/ComicViewerItemProps.d.ts +12 -1
- package/build/typescript/ComicViewer/ComicViewerProps.d.ts +61 -12
- package/package.json +2 -2
- package/src/ComicViewer/ComicViewer.tsx +70 -30
- package/src/ComicViewer/ComicViewerItemProps.ts +16 -1
- package/src/ComicViewer/ComicViewerProps.ts +70 -10
- package/src/ComicViewer/ViewerItem.tsx +107 -27
|
@@ -1,7 +1,13 @@
|
|
|
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 {
|
|
4
|
+
import {
|
|
5
|
+
ComicViewerItemData,
|
|
6
|
+
ComicViewerItemState,
|
|
7
|
+
default as ComicViewerProps,
|
|
8
|
+
ErrorInfo,
|
|
9
|
+
STATE,
|
|
10
|
+
} from './ComicViewerProps';
|
|
5
11
|
import type ComicViewerItemProps from './ComicViewerItemProps';
|
|
6
12
|
import ViewerItem from './ViewerItem';
|
|
7
13
|
|
|
@@ -9,7 +15,7 @@ const getItemHeights = <T, >(items: ComicViewerItemProps<T>[]): number[] => R.ma
|
|
|
9
15
|
const appender = (left: number, right: number): [number, number] => [left + right, left + right];
|
|
10
16
|
const getHeightAccum = (itemHeights: number[]): [number, number[]] => R.mapAccum(appender, 0, itemHeights);
|
|
11
17
|
|
|
12
|
-
const keyExtractor = <T, >(item: ComicViewerItemProps<T>) => item.
|
|
18
|
+
const keyExtractor = <T, >(item: ComicViewerItemProps<T>) => `${item.sortKey}`;
|
|
13
19
|
|
|
14
20
|
export default function ComicViewer<T>(props: ComicViewerProps<T>) {
|
|
15
21
|
const {
|
|
@@ -20,17 +26,22 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
|
|
|
20
26
|
initialScrollPercentage = 0,
|
|
21
27
|
itemVisiblePercentThreshold = 0,
|
|
22
28
|
onError,
|
|
29
|
+
onScroll,
|
|
30
|
+
getNextPage,
|
|
23
31
|
viewerWidth,
|
|
24
32
|
windowSize = 3,
|
|
33
|
+
pageUnit,
|
|
34
|
+
ListFooterComponent,
|
|
25
35
|
...otherProps
|
|
26
36
|
} = props;
|
|
27
37
|
|
|
28
38
|
const flatListRef = useRef<FlatList>(null);
|
|
29
39
|
|
|
30
|
-
const errors = useRef<Map<
|
|
40
|
+
const errors = useRef<Map<number, ErrorInfo>>(new Map());
|
|
41
|
+
|
|
31
42
|
const debounceTimeOut = useRef<NodeJS.Timeout | null>(null);
|
|
32
43
|
|
|
33
|
-
const resourceString = R.toString(R.map((itemData: ComicViewerItemData) => itemData.
|
|
44
|
+
const resourceString = R.toString(R.map((itemData: ComicViewerItemData) => itemData.url)(data));
|
|
34
45
|
|
|
35
46
|
const initialItems = R.map((itemData: ComicViewerItemData<T>) => ({
|
|
36
47
|
...itemData,
|
|
@@ -41,7 +52,13 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
|
|
|
41
52
|
|
|
42
53
|
const [items, setItems] = useState<ComicViewerItemProps<T>[]>(initialItems);
|
|
43
54
|
|
|
44
|
-
const
|
|
55
|
+
const initialItemState: ComicViewerItemState[] = R.map(() => ({
|
|
56
|
+
state: STATE.UNLOAD,
|
|
57
|
+
}))(data);
|
|
58
|
+
|
|
59
|
+
const itemStates = useRef<Array<ComicViewerItemState>>(initialItemState);
|
|
60
|
+
|
|
61
|
+
const itemHeights = [...getItemHeights(items)];
|
|
45
62
|
const itemHeightAccum = getHeightAccum(itemHeights);
|
|
46
63
|
|
|
47
64
|
const viewabilityConfig = useMemo(() => ({
|
|
@@ -62,67 +79,88 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
|
|
|
62
79
|
viewableItems: Array<ViewToken>,
|
|
63
80
|
}) => {
|
|
64
81
|
setItems((prev: ComicViewerItemProps<T>[]) => {
|
|
65
|
-
const
|
|
82
|
+
const viewableItemSortKeys = R.map((viewableItem: ViewToken) => viewableItem.item.sortKey)(viewableItems);
|
|
66
83
|
|
|
67
|
-
|
|
84
|
+
const newItems = R.map((prevItem: ComicViewerItemProps<T>) => ({
|
|
68
85
|
...prevItem,
|
|
69
|
-
isViewable: R.includes(prevItem.
|
|
86
|
+
isViewable: R.includes(prevItem.sortKey, viewableItemSortKeys),
|
|
70
87
|
}))([...prev]);
|
|
88
|
+
|
|
89
|
+
return newItems;
|
|
71
90
|
});
|
|
72
91
|
});
|
|
73
92
|
|
|
74
|
-
const
|
|
75
|
-
const
|
|
93
|
+
const itemLoadedHandler = useCallback((sortKey: number) => {
|
|
94
|
+
const itemState = itemStates.current[sortKey - 1];
|
|
95
|
+
itemState.state = STATE.LOADED;
|
|
96
|
+
itemState.error = undefined;
|
|
97
|
+
}, [itemStates]);
|
|
76
98
|
|
|
77
|
-
|
|
99
|
+
const itemErrorHandler = useCallback((errorInfo: ErrorInfo) => {
|
|
100
|
+
const { sortKey, count } = errorInfo;
|
|
101
|
+
|
|
102
|
+
if (count >= errorRetryCount) {
|
|
78
103
|
return;
|
|
79
104
|
}
|
|
80
105
|
|
|
81
|
-
|
|
82
|
-
};
|
|
106
|
+
errors.current.set(sortKey, errorInfo);
|
|
83
107
|
|
|
84
|
-
|
|
85
|
-
|
|
108
|
+
const itemState = itemStates.current[sortKey - 1];
|
|
109
|
+
itemState.state = STATE.FAIL;
|
|
110
|
+
itemState.error = errorInfo;
|
|
111
|
+
|
|
112
|
+
const handleError = () => {
|
|
113
|
+
const errorsArray = Array.from(errors.current.entries());
|
|
114
|
+
const errorsInfo = R.map(([key, value]: [number, ErrorInfo]) => value)(errorsArray);
|
|
115
|
+
|
|
116
|
+
onError && onError([...errorsInfo]);
|
|
117
|
+
errors.current.clear();
|
|
118
|
+
};
|
|
86
119
|
|
|
87
120
|
if (debounceTimeOut.current) {
|
|
88
121
|
clearTimeout(debounceTimeOut.current);
|
|
89
122
|
}
|
|
90
123
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
onErrorHandler([...errorsInfo]);
|
|
99
|
-
errors.current.clear();
|
|
100
|
-
}, errorDebounceMillis);
|
|
101
|
-
}, [errorDebounceMillis, errors.current]);
|
|
124
|
+
if (errors.current.size === pageUnit) {
|
|
125
|
+
handleError();
|
|
126
|
+
} else {
|
|
127
|
+
debounceTimeOut.current = setTimeout(handleError, errorDebounceMillis);
|
|
128
|
+
}
|
|
129
|
+
}, [errors.current, itemStates]);
|
|
102
130
|
|
|
103
131
|
const renderItem: ListRenderItem<ComicViewerItemProps<T>> = useCallback(({ item }) => {
|
|
132
|
+
const itemState = itemStates.current[item.sortKey - 1];
|
|
133
|
+
|
|
104
134
|
const props = {
|
|
105
135
|
...item,
|
|
136
|
+
itemState,
|
|
137
|
+
errorRetryCount,
|
|
106
138
|
onError: itemErrorHandler,
|
|
139
|
+
onLoaded: itemLoadedHandler,
|
|
140
|
+
getNextPage,
|
|
107
141
|
};
|
|
108
142
|
|
|
109
143
|
return <ViewerItem props={props}/>;
|
|
110
|
-
}, []);
|
|
144
|
+
}, [resourceString, itemStates, itemErrorHandler, itemLoadedHandler]);
|
|
111
145
|
|
|
112
146
|
useEffect(() => {
|
|
113
147
|
setItems((prev: ComicViewerItemProps<T>[]) => {
|
|
114
148
|
return R.map((prevItem: ComicViewerItemProps<T>) => {
|
|
115
|
-
const currentData = R.find((currentItemData: ComicViewerItemData<T>) => prevItem.
|
|
149
|
+
const currentData = R.find((currentItemData: ComicViewerItemData<T>) => prevItem.sortKey === currentItemData.sortKey)(data);
|
|
116
150
|
|
|
117
|
-
if (currentData
|
|
151
|
+
if (currentData
|
|
152
|
+
&& itemStates.current[currentData.sortKey - 1].state !== STATE.LOADED
|
|
153
|
+
&& (currentData.url !== prevItem.url)) {
|
|
118
154
|
return {
|
|
119
155
|
...prevItem,
|
|
120
|
-
|
|
156
|
+
url: currentData.url,
|
|
157
|
+
expiresAt: currentData.expiresAt,
|
|
121
158
|
};
|
|
122
159
|
}
|
|
123
160
|
|
|
124
161
|
return prevItem;
|
|
125
162
|
})([...prev]);
|
|
163
|
+
;
|
|
126
164
|
});
|
|
127
165
|
}, [resourceString]);
|
|
128
166
|
|
|
@@ -152,10 +190,12 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
|
|
|
152
190
|
initialNumToRender={initialNumToRender}
|
|
153
191
|
keyExtractor={keyExtractor}
|
|
154
192
|
onViewableItemsChanged={onViewableItemsChanged.current}
|
|
193
|
+
onScroll={onScroll}
|
|
155
194
|
ref={flatListRef}
|
|
156
195
|
renderItem={renderItem}
|
|
157
196
|
viewabilityConfig={viewabilityConfig}
|
|
158
197
|
windowSize={windowSize}
|
|
198
|
+
ListFooterComponent={ListFooterComponent}
|
|
159
199
|
{...otherProps}
|
|
160
200
|
/>
|
|
161
201
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ComicViewerItemData, ErrorInfo } from './ComicViewerProps';
|
|
1
|
+
import { ComicViewerItemData, ErrorInfo, ComicViewerItemState } from './ComicViewerProps';
|
|
2
2
|
|
|
3
3
|
type ComicViewerItemProps<T> = ComicViewerItemData<T> & {
|
|
4
4
|
/**
|
|
@@ -6,10 +6,25 @@ type ComicViewerItemProps<T> = ComicViewerItemData<T> & {
|
|
|
6
6
|
*/
|
|
7
7
|
isViewable: boolean;
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* How many times retry onError when same item error occur
|
|
11
|
+
* @default 3
|
|
12
|
+
*/
|
|
13
|
+
errorRetryCount?: number;
|
|
14
|
+
|
|
9
15
|
/**
|
|
10
16
|
* Error handler
|
|
11
17
|
*/
|
|
12
18
|
onError?: (errorInfo: ErrorInfo) => void;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Load handler
|
|
22
|
+
*/
|
|
23
|
+
onLoaded?: (sortKey: number) => void;
|
|
24
|
+
|
|
25
|
+
getNextPage?: (sortKey: number) => void;
|
|
26
|
+
|
|
27
|
+
itemState?: ComicViewerItemState;
|
|
13
28
|
}
|
|
14
29
|
|
|
15
30
|
export default ComicViewerItemProps;
|
|
@@ -1,15 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
1
2
|
import { ComponentProps } from '@fountain-ui/core';
|
|
3
|
+
import { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
|
|
4
|
+
|
|
5
|
+
export const STATE = {
|
|
6
|
+
UNLOAD: 'unload',
|
|
7
|
+
LOADING: 'loading',
|
|
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
|
+
* Content's loading state.
|
|
17
|
+
*/
|
|
18
|
+
state: LoadingState,
|
|
19
|
+
|
|
20
|
+
/***
|
|
21
|
+
* Content's error Info.
|
|
22
|
+
*/
|
|
23
|
+
error?: ErrorInfo,
|
|
24
|
+
}
|
|
2
25
|
|
|
3
26
|
export interface ErrorInfo {
|
|
4
27
|
/**
|
|
5
|
-
* ComicViewerItemData.
|
|
28
|
+
* ComicViewerItemData.sortKey.
|
|
6
29
|
*/
|
|
7
|
-
|
|
30
|
+
sortKey: number;
|
|
8
31
|
|
|
9
32
|
/**
|
|
10
33
|
* Number of times an error occurred.
|
|
11
34
|
*/
|
|
12
35
|
count: number;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Content is Expired: true
|
|
39
|
+
*/
|
|
40
|
+
expired: boolean;
|
|
13
41
|
}
|
|
14
42
|
|
|
15
43
|
export type ComicViewerItemData<T = {}> = T & {
|
|
@@ -21,17 +49,27 @@ export type ComicViewerItemData<T = {}> = T & {
|
|
|
21
49
|
/**
|
|
22
50
|
* Unique value for identifying.
|
|
23
51
|
*/
|
|
24
|
-
id:
|
|
52
|
+
id: number | undefined;
|
|
25
53
|
|
|
26
54
|
/**
|
|
27
55
|
* Image sourceUrl for displaying.
|
|
28
56
|
*/
|
|
29
|
-
|
|
57
|
+
url: string;
|
|
30
58
|
|
|
31
59
|
/**
|
|
32
60
|
* Image width.
|
|
33
61
|
*/
|
|
34
62
|
width: number;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* SortKey
|
|
66
|
+
*/
|
|
67
|
+
sortKey: number;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Image expire date.
|
|
71
|
+
*/
|
|
72
|
+
expiresAt: string;
|
|
35
73
|
}
|
|
36
74
|
|
|
37
75
|
export default interface ComicViewerProps<T> extends ComponentProps <{
|
|
@@ -52,7 +90,7 @@ export default interface ComicViewerProps<T> extends ComponentProps <{
|
|
|
52
90
|
*/
|
|
53
91
|
errorRetryCount?: number;
|
|
54
92
|
|
|
55
|
-
|
|
93
|
+
/**
|
|
56
94
|
* How many items to render in the initial batch.
|
|
57
95
|
* @default 1
|
|
58
96
|
*/
|
|
@@ -71,6 +109,28 @@ export default interface ComicViewerProps<T> extends ComponentProps <{
|
|
|
71
109
|
*/
|
|
72
110
|
itemVisiblePercentThreshold?: number;
|
|
73
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Comic viewer width.
|
|
114
|
+
*/
|
|
115
|
+
viewerWidth: number;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* The value for FlatList windowSize.
|
|
119
|
+
* @default 3
|
|
120
|
+
*/
|
|
121
|
+
windowSize?: number;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* How many images in one page.
|
|
125
|
+
*/
|
|
126
|
+
pageUnit: number;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Method for getting next page contents.
|
|
130
|
+
* @param sortKey
|
|
131
|
+
*/
|
|
132
|
+
getNextPage?: (sortKey: number) => void;
|
|
133
|
+
|
|
74
134
|
/**
|
|
75
135
|
* Handling all viewerItem errors at once.
|
|
76
136
|
* @param errors Array of ViewerItems errorInfo.
|
|
@@ -78,13 +138,13 @@ export default interface ComicViewerProps<T> extends ComponentProps <{
|
|
|
78
138
|
onError?: (errors: ErrorInfo[]) => void;
|
|
79
139
|
|
|
80
140
|
/**
|
|
81
|
-
*
|
|
141
|
+
* Handle scroll event.
|
|
142
|
+
* @param event Scroll event.
|
|
82
143
|
*/
|
|
83
|
-
|
|
144
|
+
onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
84
145
|
|
|
85
146
|
/**
|
|
86
|
-
*
|
|
87
|
-
* @default 3
|
|
147
|
+
* Component for comic viewer footer.
|
|
88
148
|
*/
|
|
89
|
-
|
|
149
|
+
ListFooterComponent?: React.ReactElement;
|
|
90
150
|
}> {}
|
|
@@ -1,64 +1,144 @@
|
|
|
1
|
-
import React, { useCallback, useRef, useState } from 'react';
|
|
1
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
|
-
import
|
|
3
|
+
import * as R from 'ramda';
|
|
4
|
+
import type { PlaceholderProps } from '@fountain-ui/core';
|
|
5
|
+
import { IconButton, Image, Spacer, useTheme } from '@fountain-ui/core';
|
|
6
|
+
import { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';
|
|
7
|
+
import { Restart } from '@fountain-ui/icons';
|
|
4
8
|
import ComicViewerItemProps from './ComicViewerItemProps';
|
|
5
9
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
type PlaceholderStyles = NamedStylesStringUnion<'init' | 'failed' | 'reload'>;
|
|
11
|
+
|
|
12
|
+
const useStyles: UseStyles<PlaceholderStyles> = function (): PlaceholderStyles {
|
|
13
|
+
const theme = useTheme();
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
init: {
|
|
17
|
+
backgroundColor: theme.palette.paper.grey,
|
|
18
|
+
},
|
|
19
|
+
failed: {
|
|
20
|
+
backgroundColor: theme.palette.paper.grey,
|
|
21
|
+
},
|
|
22
|
+
reload: {
|
|
23
|
+
backgroundColor: theme.palette.paper.grey,
|
|
24
|
+
display: 'flex',
|
|
25
|
+
alignItems: 'center',
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
};
|
|
11
29
|
|
|
12
30
|
function ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {
|
|
13
31
|
const {
|
|
32
|
+
expiresAt,
|
|
33
|
+
errorRetryCount = 3,
|
|
14
34
|
height,
|
|
15
|
-
|
|
35
|
+
itemState,
|
|
16
36
|
isViewable,
|
|
17
|
-
|
|
18
|
-
|
|
37
|
+
sortKey,
|
|
38
|
+
url,
|
|
19
39
|
width,
|
|
40
|
+
getNextPage,
|
|
41
|
+
onError,
|
|
42
|
+
onLoaded,
|
|
20
43
|
} = props;
|
|
21
44
|
|
|
22
45
|
const [isLoaded, setIsLoaded] = useState(false);
|
|
23
46
|
|
|
24
|
-
const
|
|
47
|
+
const styles = useStyles();
|
|
48
|
+
|
|
49
|
+
const errorCount = useRef<number>(R.defaultTo(0)(itemState?.error?.count));
|
|
25
50
|
|
|
26
51
|
const onLoad = useCallback(() => {
|
|
27
52
|
errorCount.current = 0;
|
|
53
|
+
|
|
28
54
|
setIsLoaded(true);
|
|
29
|
-
|
|
55
|
+
|
|
56
|
+
onLoaded && onLoaded(sortKey);
|
|
57
|
+
}, [sortKey]);
|
|
30
58
|
|
|
31
59
|
const handleError = useCallback(() => {
|
|
32
60
|
errorCount.current = errorCount.current + 1;
|
|
33
61
|
|
|
62
|
+
const expired = expiresAt ? new Date(expiresAt) <= new Date() : false;
|
|
63
|
+
|
|
64
|
+
onError && onError({
|
|
65
|
+
sortKey,
|
|
66
|
+
count: errorCount.current,
|
|
67
|
+
expired,
|
|
68
|
+
});
|
|
69
|
+
}, [errorCount.current]);
|
|
70
|
+
|
|
71
|
+
const onReloadPress = useCallback(() => {
|
|
72
|
+
errorCount.current = 1;
|
|
73
|
+
|
|
34
74
|
onError && onError({
|
|
35
|
-
|
|
36
|
-
count: errorCount.current
|
|
75
|
+
sortKey,
|
|
76
|
+
count: errorCount.current,
|
|
77
|
+
expired: false,
|
|
37
78
|
});
|
|
38
|
-
}, [
|
|
79
|
+
}, [sortKey]);
|
|
39
80
|
|
|
40
81
|
const viewStyle = { width, height };
|
|
41
82
|
|
|
42
|
-
const Placeholder = () =>
|
|
43
|
-
|
|
44
|
-
viewStyle,
|
|
45
|
-
styles.placeholder,
|
|
46
|
-
]}/>
|
|
47
|
-
);
|
|
83
|
+
const Placeholder = useCallback((props: PlaceholderProps) => {
|
|
84
|
+
const { children, failed } = props;
|
|
48
85
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
86
|
+
if (!isViewable && !isLoaded) {
|
|
87
|
+
return <View style={[
|
|
88
|
+
viewStyle,
|
|
89
|
+
styles.init,
|
|
90
|
+
]}/>;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (errorCount.current >= errorRetryCount) {
|
|
94
|
+
return <View style={[
|
|
95
|
+
viewStyle,
|
|
96
|
+
styles.reload,
|
|
97
|
+
]}>
|
|
98
|
+
<Spacer size={20}/>
|
|
99
|
+
|
|
100
|
+
<IconButton
|
|
101
|
+
children={<Restart fill={'#ffffff'}/>}
|
|
102
|
+
style={{
|
|
103
|
+
width: 48,
|
|
104
|
+
height: 48,
|
|
105
|
+
borderRadius: 24,
|
|
106
|
+
color: '#ffffff',
|
|
107
|
+
backgroundColor: '#767676',
|
|
108
|
+
}}
|
|
109
|
+
onPress={onReloadPress}
|
|
110
|
+
/>
|
|
111
|
+
</View>;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (failed) {
|
|
115
|
+
return (
|
|
116
|
+
<View style={[
|
|
117
|
+
viewStyle,
|
|
118
|
+
styles.failed,
|
|
119
|
+
]}/>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return children ? children : null;
|
|
124
|
+
}, [isViewable, isLoaded, errorCount.current, url]);
|
|
125
|
+
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
if (url === '') {
|
|
128
|
+
getNextPage?.(sortKey);
|
|
129
|
+
}
|
|
130
|
+
}, []);
|
|
52
131
|
|
|
53
132
|
return (
|
|
54
133
|
<Image
|
|
55
134
|
disableOutline={true}
|
|
56
|
-
key={
|
|
135
|
+
key={sortKey}
|
|
57
136
|
onLoad={onLoad}
|
|
58
137
|
onError={handleError}
|
|
59
|
-
source={{ uri:
|
|
138
|
+
source={{ uri: url }}
|
|
60
139
|
style={viewStyle}
|
|
61
140
|
square={true}
|
|
141
|
+
Placeholder={Placeholder}
|
|
62
142
|
/>
|
|
63
143
|
);
|
|
64
144
|
}
|
|
@@ -68,7 +148,7 @@ export default React.memo(ViewerItem, (prevProps, nextProps) => {
|
|
|
68
148
|
return false;
|
|
69
149
|
}
|
|
70
150
|
|
|
71
|
-
if (prevProps.props.
|
|
151
|
+
if (prevProps.props.url !== nextProps.props.url) {
|
|
72
152
|
return false;
|
|
73
153
|
}
|
|
74
154
|
|