@fountain-ui/lab 2.0.0-beta.30 → 2.0.0-beta.32
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 +26 -11
- package/build/commonjs/ComicViewer/ComicViewer.js.map +1 -1
- package/build/commonjs/ComicViewer/ComicViewerItemProps.js.map +1 -1
- package/build/commonjs/ComicViewer/ComicViewerProps.js.map +1 -1
- package/build/commonjs/ComicViewer/ViewerItem.js +26 -7
- package/build/commonjs/ComicViewer/ViewerItem.js.map +1 -1
- package/build/module/ComicViewer/ComicViewer.js +26 -11
- package/build/module/ComicViewer/ComicViewer.js.map +1 -1
- package/build/module/ComicViewer/ComicViewerItemProps.js.map +1 -1
- package/build/module/ComicViewer/ComicViewerProps.js.map +1 -1
- package/build/module/ComicViewer/ViewerItem.js +27 -8
- package/build/module/ComicViewer/ViewerItem.js.map +1 -1
- package/build/typescript/ComicViewer/ComicViewerItemProps.d.ts +11 -0
- package/build/typescript/ComicViewer/ComicViewerProps.d.ts +8 -0
- package/package.json +2 -2
- package/src/ComicViewer/ComicViewer.tsx +28 -12
- package/src/ComicViewer/ComicViewerItemProps.ts +12 -0
- package/src/ComicViewer/ComicViewerProps.ts +12 -2
- package/src/ComicViewer/ViewerItem.tsx +37 -16
|
@@ -41,6 +41,7 @@ function ComicViewer(props) {
|
|
|
41
41
|
itemVisiblePercentThreshold = 0,
|
|
42
42
|
onError,
|
|
43
43
|
onScroll,
|
|
44
|
+
onItemPress,
|
|
44
45
|
getNextPage,
|
|
45
46
|
viewerWidth,
|
|
46
47
|
windowSize = 3,
|
|
@@ -52,13 +53,15 @@ function ComicViewer(props) {
|
|
|
52
53
|
const errors = (0, _react.useRef)(new Map());
|
|
53
54
|
const debounceTimeOut = (0, _react.useRef)(null);
|
|
54
55
|
const resourceString = R.toString(R.map(itemData => itemData.url)(data));
|
|
56
|
+
const imageWidth = Math.min(viewerWidth, 720);
|
|
55
57
|
const initialItems = R.map(itemData => ({ ...itemData,
|
|
56
58
|
isViewable: false,
|
|
57
|
-
width:
|
|
58
|
-
height: itemData.height *
|
|
59
|
+
width: imageWidth,
|
|
60
|
+
height: itemData.height * imageWidth / itemData.width
|
|
59
61
|
}))(data);
|
|
60
62
|
const [items, setItems] = (0, _react.useState)(initialItems);
|
|
61
|
-
const initialItemState = R.map(
|
|
63
|
+
const initialItemState = R.map(itemData => ({
|
|
64
|
+
sortKey: itemData.sortKey,
|
|
62
65
|
state: _ComicViewerProps.STATE.UNLOAD
|
|
63
66
|
}))(data);
|
|
64
67
|
const itemStates = (0, _react.useRef)(initialItemState);
|
|
@@ -88,7 +91,12 @@ function ComicViewer(props) {
|
|
|
88
91
|
});
|
|
89
92
|
});
|
|
90
93
|
const itemLoadedHandler = (0, _react.useCallback)(sortKey => {
|
|
91
|
-
const itemState =
|
|
94
|
+
const itemState = R.find(state => state.sortKey === sortKey)(itemStates.current);
|
|
95
|
+
|
|
96
|
+
if (R.isNil(itemState)) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
92
100
|
itemState.state = _ComicViewerProps.STATE.LOADED;
|
|
93
101
|
itemState.error = undefined;
|
|
94
102
|
}, [itemStates]);
|
|
@@ -103,7 +111,12 @@ function ComicViewer(props) {
|
|
|
103
111
|
}
|
|
104
112
|
|
|
105
113
|
errors.current.set(sortKey, errorInfo);
|
|
106
|
-
const itemState =
|
|
114
|
+
const itemState = R.find(state => state.sortKey === sortKey)(itemStates.current);
|
|
115
|
+
|
|
116
|
+
if (R.isNil(itemState)) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
107
120
|
itemState.state = _ComicViewerProps.STATE.FAIL;
|
|
108
121
|
itemState.error = errorInfo;
|
|
109
122
|
|
|
@@ -131,24 +144,26 @@ function ComicViewer(props) {
|
|
|
131
144
|
let {
|
|
132
145
|
item
|
|
133
146
|
} = _ref3;
|
|
134
|
-
const itemState =
|
|
147
|
+
const itemState = R.find(state => state.sortKey === item.sortKey)(itemStates.current);
|
|
135
148
|
const props = { ...item,
|
|
136
149
|
itemState,
|
|
137
150
|
errorRetryCount,
|
|
138
151
|
onError: itemErrorHandler,
|
|
139
152
|
onLoaded: itemLoadedHandler,
|
|
153
|
+
onItemPress,
|
|
140
154
|
getNextPage
|
|
141
155
|
};
|
|
142
156
|
return /*#__PURE__*/_react.default.createElement(_ViewerItem.default, {
|
|
143
157
|
props: props
|
|
144
158
|
});
|
|
145
|
-
}, [resourceString,
|
|
159
|
+
}, [resourceString, itemErrorHandler, itemLoadedHandler, onItemPress]);
|
|
146
160
|
(0, _react.useEffect)(() => {
|
|
147
161
|
setItems(prev => {
|
|
148
162
|
return R.map(prevItem => {
|
|
149
163
|
const currentData = R.find(currentItemData => prevItem.sortKey === currentItemData.sortKey)(data);
|
|
164
|
+
const itemState = R.find(state => state.sortKey === (currentData === null || currentData === void 0 ? void 0 : currentData.sortKey))(itemStates.current);
|
|
150
165
|
|
|
151
|
-
if (currentData &&
|
|
166
|
+
if (currentData && itemState && itemState.state !== _ComicViewerProps.STATE.LOADED && currentData.url !== prevItem.url) {
|
|
152
167
|
return { ...prevItem,
|
|
153
168
|
url: currentData.url,
|
|
154
169
|
expiresAt: currentData.expiresAt
|
|
@@ -162,11 +177,11 @@ function ComicViewer(props) {
|
|
|
162
177
|
}, [resourceString]);
|
|
163
178
|
(0, _react.useEffect)(() => {
|
|
164
179
|
const newItems = R.map(item => ({ ...item,
|
|
165
|
-
width:
|
|
166
|
-
height: item.height *
|
|
180
|
+
width: imageWidth,
|
|
181
|
+
height: item.height * imageWidth / item.width
|
|
167
182
|
}))(items);
|
|
168
183
|
setItems(newItems);
|
|
169
|
-
}, [
|
|
184
|
+
}, [imageWidth]);
|
|
170
185
|
(0, _react.useEffect)(() => {
|
|
171
186
|
const totalHeight = itemHeightAccum[0];
|
|
172
187
|
const offset = Math.floor(initialScrollPercentage / 100 * totalHeight);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["getItemHeights","items","R","map","content","height","appender","left","right","getHeightAccum","itemHeights","mapAccum","keyExtractor","item","sortKey","ComicViewer","props","data","errorDebounceMillis","errorRetryCount","initialNumToRender","initialScrollPercentage","itemVisiblePercentThreshold","onError","onScroll","getNextPage","viewerWidth","windowSize","pageUnit","ListFooterComponent","otherProps","flatListRef","useRef","errors","Map","debounceTimeOut","resourceString","toString","itemData","url","initialItems","isViewable","width","setItems","useState","initialItemState","state","STATE","UNLOAD","itemStates","itemHeightAccum","viewabilityConfig","useMemo","getItemLayout","useCallback","index","offsets","prepend","length","offset","onViewableItemsChanged","viewableItems","prev","viewableItemSortKeys","viewableItem","newItems","prevItem","includes","itemLoadedHandler","itemState","current","LOADED","error","undefined","itemErrorHandler","errorInfo","count","set","FAIL","handleError","errorsArray","Array","from","entries","errorsInfo","key","value","clear","clearTimeout","size","setTimeout","renderItem","onLoaded","useEffect","currentData","find","currentItemData","expiresAt","totalHeight","Math","floor","scrollToOffset","animated"],"sources":["ComicViewer.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { FlatList, ListRenderItem, ViewToken } from 'react-native';\nimport * as R from 'ramda';\nimport {\n ComicViewerItemData,\n ComicViewerItemState,\n default as ComicViewerProps,\n ErrorInfo,\n STATE,\n} from './ComicViewerProps';\nimport type ComicViewerItemProps from './ComicViewerItemProps';\nimport ViewerItem from './ViewerItem';\n\nconst getItemHeights = <T, >(items: ComicViewerItemProps<T>[]): number[] => R.map((content: ComicViewerItemProps<T>) => content.height)(items);\nconst appender = (left: number, right: number): [number, number] => [left + right, left + right];\nconst getHeightAccum = (itemHeights: number[]): [number, number[]] => R.mapAccum(appender, 0, itemHeights);\n\nconst keyExtractor = <T, >(item: ComicViewerItemProps<T>) => `${item.sortKey}`;\n\nexport default function ComicViewer<T>(props: ComicViewerProps<T>) {\n const {\n data,\n errorDebounceMillis = 500,\n errorRetryCount = 3,\n initialNumToRender = 1,\n initialScrollPercentage = 0,\n itemVisiblePercentThreshold = 0,\n onError,\n onScroll,\n getNextPage,\n viewerWidth,\n windowSize = 3,\n pageUnit,\n ListFooterComponent,\n ...otherProps\n } = props;\n\n const flatListRef = useRef<FlatList>(null);\n\n const errors = useRef<Map<number, ErrorInfo>>(new Map());\n\n const debounceTimeOut = useRef<NodeJS.Timeout | null>(null);\n\n const resourceString = R.toString(R.map((itemData: ComicViewerItemData) => itemData.url)(data));\n\n const initialItems = R.map((itemData: ComicViewerItemData<T>) => ({\n ...itemData,\n isViewable: false,\n width: viewerWidth,\n height: (itemData.height * viewerWidth) / itemData.width,\n }))(data);\n\n const [items, setItems] = useState<ComicViewerItemProps<T>[]>(initialItems);\n\n const initialItemState: ComicViewerItemState[] = R.map(() => ({\n state: STATE.UNLOAD,\n }))(data);\n\n const itemStates = useRef<Array<ComicViewerItemState>>(initialItemState);\n\n const itemHeights = [...getItemHeights(items)];\n const itemHeightAccum = getHeightAccum(itemHeights);\n\n const viewabilityConfig = useMemo(() => ({\n itemVisiblePercentThreshold,\n }), [itemVisiblePercentThreshold]);\n\n const getItemLayout = useCallback((data: any, index: number) => {\n const offsets = R.prepend(0, itemHeightAccum[1]);\n\n return {\n length: itemHeights[index],\n offset: offsets[index],\n index,\n };\n }, [itemHeights]);\n\n const onViewableItemsChanged = useRef(({ viewableItems }: {\n viewableItems: Array<ViewToken>,\n }) => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n const viewableItemSortKeys = R.map((viewableItem: ViewToken) => viewableItem.item.sortKey)(viewableItems);\n\n const newItems = R.map((prevItem: ComicViewerItemProps<T>) => ({\n ...prevItem,\n isViewable: R.includes(prevItem.sortKey, viewableItemSortKeys),\n }))([...prev]);\n\n return newItems;\n });\n });\n\n const itemLoadedHandler = useCallback((sortKey: number) => {\n const itemState = itemStates.current[sortKey - 1];\n itemState.state = STATE.LOADED;\n itemState.error = undefined;\n }, [itemStates]);\n\n const itemErrorHandler = useCallback((errorInfo: ErrorInfo) => {\n const { sortKey, count } = errorInfo;\n\n if (count >= errorRetryCount) {\n return;\n }\n\n errors.current.set(sortKey, errorInfo);\n\n const itemState = itemStates.current[sortKey - 1];\n itemState.state = STATE.FAIL;\n itemState.error = errorInfo;\n\n const handleError = () => {\n const errorsArray = Array.from(errors.current.entries());\n const errorsInfo = R.map(([key, value]: [number, ErrorInfo]) => value)(errorsArray);\n\n onError && onError([...errorsInfo]);\n errors.current.clear();\n };\n\n if (debounceTimeOut.current) {\n clearTimeout(debounceTimeOut.current);\n }\n\n if (errors.current.size === pageUnit) {\n handleError();\n } else {\n debounceTimeOut.current = setTimeout(handleError, errorDebounceMillis);\n }\n }, [errors.current, itemStates]);\n\n const renderItem: ListRenderItem<ComicViewerItemProps<T>> = useCallback(({ item }) => {\n const itemState = itemStates.current[item.sortKey - 1];\n\n const props = {\n ...item,\n itemState,\n errorRetryCount,\n onError: itemErrorHandler,\n onLoaded: itemLoadedHandler,\n getNextPage,\n };\n\n return <ViewerItem props={props}/>;\n }, [resourceString, itemStates, itemErrorHandler, itemLoadedHandler]);\n\n useEffect(() => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n return R.map((prevItem: ComicViewerItemProps<T>) => {\n const currentData = R.find((currentItemData: ComicViewerItemData<T>) => prevItem.sortKey === currentItemData.sortKey)(data);\n\n if (currentData\n && itemStates.current[currentData.sortKey - 1].state !== STATE.LOADED\n && (currentData.url !== prevItem.url)) {\n return {\n ...prevItem,\n url: currentData.url,\n expiresAt: currentData.expiresAt,\n };\n }\n\n return prevItem;\n })([...prev]);\n ;\n });\n }, [resourceString]);\n\n useEffect(() => {\n const newItems = R.map((item: ComicViewerItemProps<T>) => ({\n ...item,\n width: viewerWidth,\n height: (item.height * viewerWidth) / item.width,\n }))(items);\n\n setItems(newItems);\n }, [viewerWidth]);\n\n useEffect(() => {\n const totalHeight = itemHeightAccum[0];\n const offset = Math.floor((initialScrollPercentage / 100) * totalHeight);\n\n if (flatListRef.current) {\n flatListRef.current.scrollToOffset({ offset, animated: false });\n }\n }, [flatListRef.current]);\n\n return (\n <FlatList\n data={items}\n getItemLayout={getItemLayout}\n initialNumToRender={initialNumToRender}\n keyExtractor={keyExtractor}\n onViewableItemsChanged={onViewableItemsChanged.current}\n onScroll={onScroll}\n ref={flatListRef}\n renderItem={renderItem}\n viewabilityConfig={viewabilityConfig}\n windowSize={windowSize}\n ListFooterComponent={ListFooterComponent}\n {...otherProps}\n />\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["getItemHeights","items","R","map","content","height","appender","left","right","getHeightAccum","itemHeights","mapAccum","keyExtractor","item","sortKey","ComicViewer","props","data","errorDebounceMillis","errorRetryCount","initialNumToRender","initialScrollPercentage","itemVisiblePercentThreshold","onError","onScroll","onItemPress","getNextPage","viewerWidth","windowSize","pageUnit","ListFooterComponent","otherProps","flatListRef","useRef","errors","Map","debounceTimeOut","resourceString","toString","itemData","url","imageWidth","Math","min","initialItems","isViewable","width","setItems","useState","initialItemState","state","STATE","UNLOAD","itemStates","itemHeightAccum","viewabilityConfig","useMemo","getItemLayout","useCallback","index","offsets","prepend","length","offset","onViewableItemsChanged","viewableItems","prev","viewableItemSortKeys","viewableItem","newItems","prevItem","includes","itemLoadedHandler","itemState","find","current","isNil","LOADED","error","undefined","itemErrorHandler","errorInfo","count","set","FAIL","handleError","errorsArray","Array","from","entries","errorsInfo","key","value","clear","clearTimeout","size","setTimeout","renderItem","onLoaded","useEffect","currentData","currentItemData","expiresAt","totalHeight","floor","scrollToOffset","animated"],"sources":["ComicViewer.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { FlatList, ListRenderItem, ViewToken } from 'react-native';\nimport * as R from 'ramda';\nimport {\n ComicViewerItemData,\n ComicViewerItemState,\n default as ComicViewerProps,\n ErrorInfo,\n STATE,\n} from './ComicViewerProps';\nimport type ComicViewerItemProps from './ComicViewerItemProps';\nimport ViewerItem from './ViewerItem';\n\nconst getItemHeights = <T, >(items: ComicViewerItemProps<T>[]): number[] => R.map((content: ComicViewerItemProps<T>) => content.height)(items);\nconst appender = (left: number, right: number): [number, number] => [left + right, left + right];\nconst getHeightAccum = (itemHeights: number[]): [number, number[]] => R.mapAccum(appender, 0, itemHeights);\n\nconst keyExtractor = <T, >(item: ComicViewerItemProps<T>) => `${item.sortKey}`;\n\nexport default function ComicViewer<T>(props: ComicViewerProps<T>) {\n const {\n data,\n errorDebounceMillis = 500,\n errorRetryCount = 3,\n initialNumToRender = 1,\n initialScrollPercentage = 0,\n itemVisiblePercentThreshold = 0,\n onError,\n onScroll,\n onItemPress,\n getNextPage,\n viewerWidth,\n windowSize = 3,\n pageUnit,\n ListFooterComponent,\n ...otherProps\n } = props;\n\n const flatListRef = useRef<FlatList>(null);\n\n const errors = useRef<Map<number, ErrorInfo>>(new Map());\n\n const debounceTimeOut = useRef<NodeJS.Timeout | null>(null);\n\n const resourceString = R.toString(R.map((itemData: ComicViewerItemData) => itemData.url)(data));\n\n const imageWidth = Math.min(viewerWidth, 720);\n const initialItems = R.map((itemData: ComicViewerItemData<T>) => ({\n ...itemData,\n isViewable: false,\n width: imageWidth,\n height: (itemData.height * imageWidth) / itemData.width,\n }))(data);\n\n const [items, setItems] = useState<ComicViewerItemProps<T>[]>(initialItems);\n\n const initialItemState: ComicViewerItemState[] = R.map((itemData: ComicViewerItemData<T>) => ({\n sortKey: itemData.sortKey,\n state: STATE.UNLOAD,\n }))(data);\n\n const itemStates = useRef<Array<ComicViewerItemState>>(initialItemState);\n\n const itemHeights = [...getItemHeights(items)];\n const itemHeightAccum = getHeightAccum(itemHeights);\n\n const viewabilityConfig = useMemo(() => ({\n itemVisiblePercentThreshold,\n }), [itemVisiblePercentThreshold]);\n\n const getItemLayout = useCallback((data: any, index: number) => {\n const offsets = R.prepend(0, itemHeightAccum[1]);\n\n return {\n length: itemHeights[index],\n offset: offsets[index],\n index,\n };\n }, [itemHeights]);\n\n const onViewableItemsChanged = useRef(({ viewableItems }: {\n viewableItems: Array<ViewToken>,\n }) => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n const viewableItemSortKeys = R.map((viewableItem: ViewToken) => viewableItem.item.sortKey)(viewableItems);\n\n const newItems = R.map((prevItem: ComicViewerItemProps<T>) => ({\n ...prevItem,\n isViewable: R.includes(prevItem.sortKey, viewableItemSortKeys),\n }))([...prev]);\n\n return newItems;\n });\n });\n\n const itemLoadedHandler = useCallback((sortKey: number) => {\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === sortKey)(itemStates.current);\n\n if (R.isNil(itemState)) {\n return;\n }\n\n itemState.state = STATE.LOADED;\n itemState.error = undefined;\n }, [itemStates]);\n\n const itemErrorHandler = useCallback((errorInfo: ErrorInfo) => {\n const { sortKey, count } = errorInfo;\n\n if (count >= errorRetryCount) {\n return;\n }\n\n errors.current.set(sortKey, errorInfo);\n\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === sortKey)(itemStates.current);\n\n if (R.isNil(itemState)) {\n return;\n }\n\n itemState.state = STATE.FAIL;\n itemState.error = errorInfo;\n\n const handleError = () => {\n const errorsArray = Array.from(errors.current.entries());\n const errorsInfo = R.map(([key, value]: [number, ErrorInfo]) => value)(errorsArray);\n\n onError && onError([...errorsInfo]);\n errors.current.clear();\n };\n\n if (debounceTimeOut.current) {\n clearTimeout(debounceTimeOut.current);\n }\n\n if (errors.current.size === pageUnit) {\n handleError();\n } else {\n debounceTimeOut.current = setTimeout(handleError, errorDebounceMillis);\n }\n }, [errors.current, itemStates]);\n\n const renderItem: ListRenderItem<ComicViewerItemProps<T>> = useCallback(({ item }) => {\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === item.sortKey)(itemStates.current);\n\n const props = {\n ...item,\n itemState,\n errorRetryCount,\n onError: itemErrorHandler,\n onLoaded: itemLoadedHandler,\n onItemPress,\n getNextPage,\n };\n\n return <ViewerItem props={props}/>;\n }, [resourceString, itemErrorHandler, itemLoadedHandler, onItemPress]);\n\n useEffect(() => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n return R.map((prevItem: ComicViewerItemProps<T>) => {\n const currentData: ComicViewerItemData | undefined = R.find((currentItemData: ComicViewerItemData<T>) => prevItem.sortKey === currentItemData.sortKey)(data);\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === currentData?.sortKey)(itemStates.current);\n\n if (currentData\n && itemState\n && itemState.state !== STATE.LOADED\n && (currentData.url !== prevItem.url)) {\n return {\n ...prevItem,\n url: currentData.url,\n expiresAt: currentData.expiresAt,\n };\n }\n\n return prevItem;\n })([...prev]);\n ;\n });\n }, [resourceString]);\n\n useEffect(() => {\n const newItems = R.map((item: ComicViewerItemProps<T>) => ({\n ...item,\n width: imageWidth,\n height: (item.height * imageWidth) / item.width,\n }))(items);\n\n setItems(newItems);\n }, [imageWidth]);\n\n useEffect(() => {\n const totalHeight = itemHeightAccum[0];\n const offset = Math.floor((initialScrollPercentage / 100) * totalHeight);\n\n if (flatListRef.current) {\n flatListRef.current.scrollToOffset({ offset, animated: false });\n }\n }, [flatListRef.current]);\n\n return (\n <FlatList\n data={items}\n getItemLayout={getItemLayout}\n initialNumToRender={initialNumToRender}\n keyExtractor={keyExtractor}\n onViewableItemsChanged={onViewableItemsChanged.current}\n onScroll={onScroll}\n ref={flatListRef}\n renderItem={renderItem}\n viewabilityConfig={viewabilityConfig}\n windowSize={windowSize}\n ListFooterComponent={ListFooterComponent}\n {...otherProps}\n />\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["ComicViewerItemProps.ts"],"sourcesContent":["import { ComicViewerItemData, ErrorInfo, ComicViewerItemState } from './ComicViewerProps';\n\ntype ComicViewerItemProps<T> = ComicViewerItemData<T> & {\n /**\n * FlatListItem is viewable in screen.\n */\n isViewable: boolean;\n\n /**\n * How many times retry onError when same item error occur\n * @default 3\n */\n errorRetryCount?: number;\n\n /**\n * Error handler\n */\n onError?: (errorInfo: ErrorInfo) => void;\n\n /**\n * Load handler\n */\n onLoaded?: (sortKey: number) => void;\n\n getNextPage?: (sortKey: number) => void;\n\n itemState?: ComicViewerItemState;\n}\n\nexport default ComicViewerItemProps;"],"mappings":""}
|
|
1
|
+
{"version":3,"names":[],"sources":["ComicViewerItemProps.ts"],"sourcesContent":["import { ComicViewerItemData, ErrorInfo, ComicViewerItemState } from './ComicViewerProps';\n\ntype ComicViewerItemProps<T> = ComicViewerItemData<T> & {\n /**\n * FlatListItem is viewable in screen.\n */\n isViewable: boolean;\n\n /**\n * How many times retry onError when same item error occur\n * @default 3\n */\n errorRetryCount?: number;\n\n /**\n * Error handler\n */\n onError?: (errorInfo: ErrorInfo) => void;\n\n /**\n * Load handler\n */\n onLoaded?: (sortKey: number) => void;\n\n /**\n * Method for getting next page contents.\n * @param sortKey\n */\n getNextPage?: (sortKey: number) => void;\n\n /**\n * Handle item press event.\n */\n onItemPress?: () => void;\n\n /**\n * Image loading state and error info.\n */\n itemState?: ComicViewerItemState;\n}\n\nexport default ComicViewerItemProps;"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["STATE","UNLOAD","LOADING","LOADED","FAIL"],"sources":["ComicViewerProps.ts"],"sourcesContent":["import React from 'react';\nimport { ComponentProps } from '@fountain-ui/core';\nimport { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';\n\nexport const STATE = {\n UNLOAD: 'unload',\n LOADING: 'loading',\n LOADED: 'loaded',\n FAIL: 'fail',\n} as const;\n\nexport type LoadingState = typeof STATE[keyof typeof STATE];\n\nexport interface ComicViewerItemState{\n /**\n * Content's loading state.\n */\n state: LoadingState
|
|
1
|
+
{"version":3,"names":["STATE","UNLOAD","LOADING","LOADED","FAIL"],"sources":["ComicViewerProps.ts"],"sourcesContent":["import React from 'react';\nimport { ComponentProps } from '@fountain-ui/core';\nimport { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';\n\nexport const STATE = {\n UNLOAD: 'unload',\n LOADING: 'loading',\n LOADED: 'loaded',\n FAIL: 'fail',\n} as const;\n\nexport type LoadingState = typeof STATE[keyof typeof STATE];\n\nexport interface ComicViewerItemState{\n /**\n * Comic viewer item sortKey.\n */\n sortKey: number;\n\n /**\n * Content's loading state.\n */\n state: LoadingState;\n\n /***\n * Content's error Info.\n */\n error?: ErrorInfo;\n}\n\nexport interface ErrorInfo {\n /**\n * ComicViewerItemData.sortKey.\n */\n sortKey: number;\n\n /**\n * Number of times an error occurred.\n */\n count: number;\n\n /**\n * Content is Expired: true\n */\n expired: boolean;\n}\n\nexport type ComicViewerItemData<T = {}> = T & {\n /**\n * Image height.\n */\n height: number;\n\n /**\n * Unique value for identifying.\n */\n id: number | undefined;\n\n /**\n * Image sourceUrl for displaying.\n */\n url: string;\n\n /**\n * Image width.\n */\n width: number;\n\n /**\n * SortKey\n */\n sortKey: number;\n\n /**\n * Image expire date.\n */\n expiresAt: string;\n}\n\nexport default interface ComicViewerProps<T> extends ComponentProps <{\n /**\n * Data for render.\n */\n data: ComicViewerItemData<T>[];\n\n /**\n * Delay Time to call the error handler.\n * @default 500\n */\n errorDebounceMillis?: number;\n\n /**\n * How many times retry onError when same item error occur\n * @default 3\n */\n errorRetryCount?: number;\n\n /**\n * How many items to render in the initial batch.\n * @default 1\n */\n initialNumToRender?: number;\n\n /**\n * Start at initialScrollPercentage.\n * If over 100, scroll to end.\n * @default 0\n */\n initialScrollPercentage?: number;\n\n /**\n * The value for FlatList viewabilityConfig.itemVisiblePercentThreshold.\n * @default 0\n */\n itemVisiblePercentThreshold?: number;\n\n /**\n * Comic viewer width.\n */\n viewerWidth: number;\n\n /**\n * The value for FlatList windowSize.\n * @default 3\n */\n windowSize?: number;\n\n /**\n * How many images in one page.\n */\n pageUnit: number;\n\n /**\n * Method for getting next page contents.\n * @param sortKey\n */\n getNextPage?: (sortKey: number) => void;\n\n /**\n * Handling all viewerItem errors at once.\n * @param errors Array of ViewerItems errorInfo.\n */\n onError?: (errors: ErrorInfo[]) => void;\n\n /**\n * Handle scroll event.\n * @param event Scroll event.\n */\n onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;\n\n /**\n * Handle item press event.\n */\n onItemPress?: () => void;\n\n /**\n * Component for comic viewer footer.\n */\n ListFooterComponent?: React.ReactElement;\n}> {}"],"mappings":";;;;;;AAIO,MAAMA,KAAK,GAAG;EACjBC,MAAM,EAAE,QADS;EAEjBC,OAAO,EAAE,SAFQ;EAGjBC,MAAM,EAAE,QAHS;EAIjBC,IAAI,EAAE;AAJW,CAAd"}
|
|
@@ -22,6 +22,11 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
|
|
22
22
|
const useStyles = function () {
|
|
23
23
|
const theme = (0, _core.useTheme)();
|
|
24
24
|
return {
|
|
25
|
+
root: {
|
|
26
|
+
display: 'flex',
|
|
27
|
+
flexDirection: 'row',
|
|
28
|
+
justifyContent: 'center'
|
|
29
|
+
},
|
|
25
30
|
init: {
|
|
26
31
|
backgroundColor: theme.palette.paper.grey
|
|
27
32
|
},
|
|
@@ -53,7 +58,8 @@ function ViewerItem(_ref) {
|
|
|
53
58
|
width,
|
|
54
59
|
getNextPage,
|
|
55
60
|
onError,
|
|
56
|
-
onLoaded
|
|
61
|
+
onLoaded,
|
|
62
|
+
onItemPress
|
|
57
63
|
} = props;
|
|
58
64
|
const [isLoaded, setIsLoaded] = (0, _react.useState)(false);
|
|
59
65
|
const styles = useStyles();
|
|
@@ -65,7 +71,9 @@ function ViewerItem(_ref) {
|
|
|
65
71
|
}, [sortKey]);
|
|
66
72
|
const handleError = (0, _react.useCallback)(() => {
|
|
67
73
|
errorCount.current = errorCount.current + 1;
|
|
68
|
-
const
|
|
74
|
+
const now = new Date();
|
|
75
|
+
const utcNow = now.getTime() + now.getTimezoneOffset() * 60 * 1000;
|
|
76
|
+
const expired = new Date(expiresAt).getTime() <= utcNow;
|
|
69
77
|
onError && onError({
|
|
70
78
|
sortKey,
|
|
71
79
|
count: errorCount.current,
|
|
@@ -90,7 +98,7 @@ function ViewerItem(_ref) {
|
|
|
90
98
|
failed
|
|
91
99
|
} = props;
|
|
92
100
|
|
|
93
|
-
if (!isViewable && !isLoaded) {
|
|
101
|
+
if (!isViewable && !isLoaded || url === '') {
|
|
94
102
|
return /*#__PURE__*/_react.default.createElement(_reactNative.View, {
|
|
95
103
|
style: [viewStyle, styles.init]
|
|
96
104
|
});
|
|
@@ -122,25 +130,32 @@ function ViewerItem(_ref) {
|
|
|
122
130
|
});
|
|
123
131
|
}
|
|
124
132
|
|
|
125
|
-
return children ?
|
|
126
|
-
|
|
133
|
+
return children ? /*#__PURE__*/_react.default.createElement(_reactNative.Pressable, {
|
|
134
|
+
onPress: onItemPress
|
|
135
|
+
}, children) : null;
|
|
136
|
+
}, [isViewable, isLoaded, errorCount.current, url, onItemPress]);
|
|
127
137
|
(0, _react.useEffect)(() => {
|
|
128
138
|
if (url === '') {
|
|
129
139
|
getNextPage === null || getNextPage === void 0 ? void 0 : getNextPage(sortKey);
|
|
130
140
|
}
|
|
131
141
|
}, []);
|
|
132
|
-
return /*#__PURE__*/_react.default.createElement(
|
|
142
|
+
return /*#__PURE__*/_react.default.createElement(_reactNative.View, {
|
|
143
|
+
style: styles.root
|
|
144
|
+
}, /*#__PURE__*/_react.default.createElement(_core.Image, {
|
|
133
145
|
disableOutline: true,
|
|
134
146
|
key: sortKey,
|
|
147
|
+
disableLongClick: true,
|
|
148
|
+
disableDrag: true,
|
|
135
149
|
onLoad: onLoad,
|
|
136
150
|
onError: handleError,
|
|
151
|
+
loading: 'eager',
|
|
137
152
|
source: {
|
|
138
153
|
uri: url
|
|
139
154
|
},
|
|
140
155
|
style: viewStyle,
|
|
141
156
|
square: true,
|
|
142
157
|
Placeholder: Placeholder
|
|
143
|
-
});
|
|
158
|
+
}));
|
|
144
159
|
}
|
|
145
160
|
|
|
146
161
|
var _default = /*#__PURE__*/_react.default.memo(ViewerItem, (prevProps, nextProps) => {
|
|
@@ -152,6 +167,10 @@ var _default = /*#__PURE__*/_react.default.memo(ViewerItem, (prevProps, nextProp
|
|
|
152
167
|
return false;
|
|
153
168
|
}
|
|
154
169
|
|
|
170
|
+
if (prevProps.props.width !== nextProps.props.width) {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
|
|
155
174
|
return true;
|
|
156
175
|
});
|
|
157
176
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useStyles","theme","useTheme","init","backgroundColor","palette","paper","grey","failed","reload","
|
|
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","Placeholder","children","borderRadius","color","useEffect","uri","React","memo","prevProps","nextProps"],"sources":["ViewerItem.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { Pressable, 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';\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 = { width, height };\n\n const Placeholder = useCallback((props: PlaceholderProps) => {\n const { children, failed } = props;\n\n if ((!isViewable && !isLoaded) || url === '') {\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 if (failed) {\n return (\n <View style={[\n viewStyle,\n styles.failed,\n ]}/>\n );\n }\n\n return children ? (\n <Pressable onPress={onItemPress}>\n {children}\n </Pressable>\n ) : null;\n }, [isViewable, isLoaded, errorCount.current, url, onItemPress]);\n\n useEffect(() => {\n if (url === '') {\n getNextPage?.(sortKey);\n }\n }, []);\n\n return (\n <View style={styles.root}>\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={viewStyle}\n square={true}\n Placeholder={Placeholder}\n />\n </View>\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 return true;\n});\n"],"mappings":"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"}
|
|
@@ -24,6 +24,7 @@ export default function ComicViewer(props) {
|
|
|
24
24
|
itemVisiblePercentThreshold = 0,
|
|
25
25
|
onError,
|
|
26
26
|
onScroll,
|
|
27
|
+
onItemPress,
|
|
27
28
|
getNextPage,
|
|
28
29
|
viewerWidth,
|
|
29
30
|
windowSize = 3,
|
|
@@ -35,13 +36,15 @@ export default function ComicViewer(props) {
|
|
|
35
36
|
const errors = useRef(new Map());
|
|
36
37
|
const debounceTimeOut = useRef(null);
|
|
37
38
|
const resourceString = R.toString(R.map(itemData => itemData.url)(data));
|
|
39
|
+
const imageWidth = Math.min(viewerWidth, 720);
|
|
38
40
|
const initialItems = R.map(itemData => ({ ...itemData,
|
|
39
41
|
isViewable: false,
|
|
40
|
-
width:
|
|
41
|
-
height: itemData.height *
|
|
42
|
+
width: imageWidth,
|
|
43
|
+
height: itemData.height * imageWidth / itemData.width
|
|
42
44
|
}))(data);
|
|
43
45
|
const [items, setItems] = useState(initialItems);
|
|
44
|
-
const initialItemState = R.map(
|
|
46
|
+
const initialItemState = R.map(itemData => ({
|
|
47
|
+
sortKey: itemData.sortKey,
|
|
45
48
|
state: STATE.UNLOAD
|
|
46
49
|
}))(data);
|
|
47
50
|
const itemStates = useRef(initialItemState);
|
|
@@ -71,7 +74,12 @@ export default function ComicViewer(props) {
|
|
|
71
74
|
});
|
|
72
75
|
});
|
|
73
76
|
const itemLoadedHandler = useCallback(sortKey => {
|
|
74
|
-
const itemState =
|
|
77
|
+
const itemState = R.find(state => state.sortKey === sortKey)(itemStates.current);
|
|
78
|
+
|
|
79
|
+
if (R.isNil(itemState)) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
75
83
|
itemState.state = STATE.LOADED;
|
|
76
84
|
itemState.error = undefined;
|
|
77
85
|
}, [itemStates]);
|
|
@@ -86,7 +94,12 @@ export default function ComicViewer(props) {
|
|
|
86
94
|
}
|
|
87
95
|
|
|
88
96
|
errors.current.set(sortKey, errorInfo);
|
|
89
|
-
const itemState =
|
|
97
|
+
const itemState = R.find(state => state.sortKey === sortKey)(itemStates.current);
|
|
98
|
+
|
|
99
|
+
if (R.isNil(itemState)) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
90
103
|
itemState.state = STATE.FAIL;
|
|
91
104
|
itemState.error = errorInfo;
|
|
92
105
|
|
|
@@ -114,24 +127,26 @@ export default function ComicViewer(props) {
|
|
|
114
127
|
let {
|
|
115
128
|
item
|
|
116
129
|
} = _ref3;
|
|
117
|
-
const itemState =
|
|
130
|
+
const itemState = R.find(state => state.sortKey === item.sortKey)(itemStates.current);
|
|
118
131
|
const props = { ...item,
|
|
119
132
|
itemState,
|
|
120
133
|
errorRetryCount,
|
|
121
134
|
onError: itemErrorHandler,
|
|
122
135
|
onLoaded: itemLoadedHandler,
|
|
136
|
+
onItemPress,
|
|
123
137
|
getNextPage
|
|
124
138
|
};
|
|
125
139
|
return /*#__PURE__*/React.createElement(ViewerItem, {
|
|
126
140
|
props: props
|
|
127
141
|
});
|
|
128
|
-
}, [resourceString,
|
|
142
|
+
}, [resourceString, itemErrorHandler, itemLoadedHandler, onItemPress]);
|
|
129
143
|
useEffect(() => {
|
|
130
144
|
setItems(prev => {
|
|
131
145
|
return R.map(prevItem => {
|
|
132
146
|
const currentData = R.find(currentItemData => prevItem.sortKey === currentItemData.sortKey)(data);
|
|
147
|
+
const itemState = R.find(state => state.sortKey === (currentData === null || currentData === void 0 ? void 0 : currentData.sortKey))(itemStates.current);
|
|
133
148
|
|
|
134
|
-
if (currentData &&
|
|
149
|
+
if (currentData && itemState && itemState.state !== STATE.LOADED && currentData.url !== prevItem.url) {
|
|
135
150
|
return { ...prevItem,
|
|
136
151
|
url: currentData.url,
|
|
137
152
|
expiresAt: currentData.expiresAt
|
|
@@ -145,11 +160,11 @@ export default function ComicViewer(props) {
|
|
|
145
160
|
}, [resourceString]);
|
|
146
161
|
useEffect(() => {
|
|
147
162
|
const newItems = R.map(item => ({ ...item,
|
|
148
|
-
width:
|
|
149
|
-
height: item.height *
|
|
163
|
+
width: imageWidth,
|
|
164
|
+
height: item.height * imageWidth / item.width
|
|
150
165
|
}))(items);
|
|
151
166
|
setItems(newItems);
|
|
152
|
-
}, [
|
|
167
|
+
}, [imageWidth]);
|
|
153
168
|
useEffect(() => {
|
|
154
169
|
const totalHeight = itemHeightAccum[0];
|
|
155
170
|
const offset = Math.floor(initialScrollPercentage / 100 * totalHeight);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useCallback","useEffect","useMemo","useRef","useState","FlatList","R","STATE","ViewerItem","getItemHeights","items","map","content","height","appender","left","right","getHeightAccum","itemHeights","mapAccum","keyExtractor","item","sortKey","ComicViewer","props","data","errorDebounceMillis","errorRetryCount","initialNumToRender","initialScrollPercentage","itemVisiblePercentThreshold","onError","onScroll","getNextPage","viewerWidth","windowSize","pageUnit","ListFooterComponent","otherProps","flatListRef","errors","Map","debounceTimeOut","resourceString","toString","itemData","url","initialItems","isViewable","width","setItems","initialItemState","state","UNLOAD","itemStates","itemHeightAccum","viewabilityConfig","getItemLayout","index","offsets","prepend","length","offset","onViewableItemsChanged","viewableItems","prev","viewableItemSortKeys","viewableItem","newItems","prevItem","includes","itemLoadedHandler","itemState","current","LOADED","error","undefined","itemErrorHandler","errorInfo","count","set","FAIL","handleError","errorsArray","Array","from","entries","errorsInfo","key","value","clear","clearTimeout","size","setTimeout","renderItem","onLoaded","currentData","find","currentItemData","expiresAt","totalHeight","Math","floor","scrollToOffset","animated"],"sources":["ComicViewer.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { FlatList, ListRenderItem, ViewToken } from 'react-native';\nimport * as R from 'ramda';\nimport {\n ComicViewerItemData,\n ComicViewerItemState,\n default as ComicViewerProps,\n ErrorInfo,\n STATE,\n} from './ComicViewerProps';\nimport type ComicViewerItemProps from './ComicViewerItemProps';\nimport ViewerItem from './ViewerItem';\n\nconst getItemHeights = <T, >(items: ComicViewerItemProps<T>[]): number[] => R.map((content: ComicViewerItemProps<T>) => content.height)(items);\nconst appender = (left: number, right: number): [number, number] => [left + right, left + right];\nconst getHeightAccum = (itemHeights: number[]): [number, number[]] => R.mapAccum(appender, 0, itemHeights);\n\nconst keyExtractor = <T, >(item: ComicViewerItemProps<T>) => `${item.sortKey}`;\n\nexport default function ComicViewer<T>(props: ComicViewerProps<T>) {\n const {\n data,\n errorDebounceMillis = 500,\n errorRetryCount = 3,\n initialNumToRender = 1,\n initialScrollPercentage = 0,\n itemVisiblePercentThreshold = 0,\n onError,\n onScroll,\n getNextPage,\n viewerWidth,\n windowSize = 3,\n pageUnit,\n ListFooterComponent,\n ...otherProps\n } = props;\n\n const flatListRef = useRef<FlatList>(null);\n\n const errors = useRef<Map<number, ErrorInfo>>(new Map());\n\n const debounceTimeOut = useRef<NodeJS.Timeout | null>(null);\n\n const resourceString = R.toString(R.map((itemData: ComicViewerItemData) => itemData.url)(data));\n\n const initialItems = R.map((itemData: ComicViewerItemData<T>) => ({\n ...itemData,\n isViewable: false,\n width: viewerWidth,\n height: (itemData.height * viewerWidth) / itemData.width,\n }))(data);\n\n const [items, setItems] = useState<ComicViewerItemProps<T>[]>(initialItems);\n\n const initialItemState: ComicViewerItemState[] = R.map(() => ({\n state: STATE.UNLOAD,\n }))(data);\n\n const itemStates = useRef<Array<ComicViewerItemState>>(initialItemState);\n\n const itemHeights = [...getItemHeights(items)];\n const itemHeightAccum = getHeightAccum(itemHeights);\n\n const viewabilityConfig = useMemo(() => ({\n itemVisiblePercentThreshold,\n }), [itemVisiblePercentThreshold]);\n\n const getItemLayout = useCallback((data: any, index: number) => {\n const offsets = R.prepend(0, itemHeightAccum[1]);\n\n return {\n length: itemHeights[index],\n offset: offsets[index],\n index,\n };\n }, [itemHeights]);\n\n const onViewableItemsChanged = useRef(({ viewableItems }: {\n viewableItems: Array<ViewToken>,\n }) => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n const viewableItemSortKeys = R.map((viewableItem: ViewToken) => viewableItem.item.sortKey)(viewableItems);\n\n const newItems = R.map((prevItem: ComicViewerItemProps<T>) => ({\n ...prevItem,\n isViewable: R.includes(prevItem.sortKey, viewableItemSortKeys),\n }))([...prev]);\n\n return newItems;\n });\n });\n\n const itemLoadedHandler = useCallback((sortKey: number) => {\n const itemState = itemStates.current[sortKey - 1];\n itemState.state = STATE.LOADED;\n itemState.error = undefined;\n }, [itemStates]);\n\n const itemErrorHandler = useCallback((errorInfo: ErrorInfo) => {\n const { sortKey, count } = errorInfo;\n\n if (count >= errorRetryCount) {\n return;\n }\n\n errors.current.set(sortKey, errorInfo);\n\n const itemState = itemStates.current[sortKey - 1];\n itemState.state = STATE.FAIL;\n itemState.error = errorInfo;\n\n const handleError = () => {\n const errorsArray = Array.from(errors.current.entries());\n const errorsInfo = R.map(([key, value]: [number, ErrorInfo]) => value)(errorsArray);\n\n onError && onError([...errorsInfo]);\n errors.current.clear();\n };\n\n if (debounceTimeOut.current) {\n clearTimeout(debounceTimeOut.current);\n }\n\n if (errors.current.size === pageUnit) {\n handleError();\n } else {\n debounceTimeOut.current = setTimeout(handleError, errorDebounceMillis);\n }\n }, [errors.current, itemStates]);\n\n const renderItem: ListRenderItem<ComicViewerItemProps<T>> = useCallback(({ item }) => {\n const itemState = itemStates.current[item.sortKey - 1];\n\n const props = {\n ...item,\n itemState,\n errorRetryCount,\n onError: itemErrorHandler,\n onLoaded: itemLoadedHandler,\n getNextPage,\n };\n\n return <ViewerItem props={props}/>;\n }, [resourceString, itemStates, itemErrorHandler, itemLoadedHandler]);\n\n useEffect(() => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n return R.map((prevItem: ComicViewerItemProps<T>) => {\n const currentData = R.find((currentItemData: ComicViewerItemData<T>) => prevItem.sortKey === currentItemData.sortKey)(data);\n\n if (currentData\n && itemStates.current[currentData.sortKey - 1].state !== STATE.LOADED\n && (currentData.url !== prevItem.url)) {\n return {\n ...prevItem,\n url: currentData.url,\n expiresAt: currentData.expiresAt,\n };\n }\n\n return prevItem;\n })([...prev]);\n ;\n });\n }, [resourceString]);\n\n useEffect(() => {\n const newItems = R.map((item: ComicViewerItemProps<T>) => ({\n ...item,\n width: viewerWidth,\n height: (item.height * viewerWidth) / item.width,\n }))(items);\n\n setItems(newItems);\n }, [viewerWidth]);\n\n useEffect(() => {\n const totalHeight = itemHeightAccum[0];\n const offset = Math.floor((initialScrollPercentage / 100) * totalHeight);\n\n if (flatListRef.current) {\n flatListRef.current.scrollToOffset({ offset, animated: false });\n }\n }, [flatListRef.current]);\n\n return (\n <FlatList\n data={items}\n getItemLayout={getItemLayout}\n initialNumToRender={initialNumToRender}\n keyExtractor={keyExtractor}\n onViewableItemsChanged={onViewableItemsChanged.current}\n onScroll={onScroll}\n ref={flatListRef}\n renderItem={renderItem}\n viewabilityConfig={viewabilityConfig}\n windowSize={windowSize}\n ListFooterComponent={ListFooterComponent}\n {...otherProps}\n />\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["React","useCallback","useEffect","useMemo","useRef","useState","FlatList","R","STATE","ViewerItem","getItemHeights","items","map","content","height","appender","left","right","getHeightAccum","itemHeights","mapAccum","keyExtractor","item","sortKey","ComicViewer","props","data","errorDebounceMillis","errorRetryCount","initialNumToRender","initialScrollPercentage","itemVisiblePercentThreshold","onError","onScroll","onItemPress","getNextPage","viewerWidth","windowSize","pageUnit","ListFooterComponent","otherProps","flatListRef","errors","Map","debounceTimeOut","resourceString","toString","itemData","url","imageWidth","Math","min","initialItems","isViewable","width","setItems","initialItemState","state","UNLOAD","itemStates","itemHeightAccum","viewabilityConfig","getItemLayout","index","offsets","prepend","length","offset","onViewableItemsChanged","viewableItems","prev","viewableItemSortKeys","viewableItem","newItems","prevItem","includes","itemLoadedHandler","itemState","find","current","isNil","LOADED","error","undefined","itemErrorHandler","errorInfo","count","set","FAIL","handleError","errorsArray","Array","from","entries","errorsInfo","key","value","clear","clearTimeout","size","setTimeout","renderItem","onLoaded","currentData","currentItemData","expiresAt","totalHeight","floor","scrollToOffset","animated"],"sources":["ComicViewer.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { FlatList, ListRenderItem, ViewToken } from 'react-native';\nimport * as R from 'ramda';\nimport {\n ComicViewerItemData,\n ComicViewerItemState,\n default as ComicViewerProps,\n ErrorInfo,\n STATE,\n} from './ComicViewerProps';\nimport type ComicViewerItemProps from './ComicViewerItemProps';\nimport ViewerItem from './ViewerItem';\n\nconst getItemHeights = <T, >(items: ComicViewerItemProps<T>[]): number[] => R.map((content: ComicViewerItemProps<T>) => content.height)(items);\nconst appender = (left: number, right: number): [number, number] => [left + right, left + right];\nconst getHeightAccum = (itemHeights: number[]): [number, number[]] => R.mapAccum(appender, 0, itemHeights);\n\nconst keyExtractor = <T, >(item: ComicViewerItemProps<T>) => `${item.sortKey}`;\n\nexport default function ComicViewer<T>(props: ComicViewerProps<T>) {\n const {\n data,\n errorDebounceMillis = 500,\n errorRetryCount = 3,\n initialNumToRender = 1,\n initialScrollPercentage = 0,\n itemVisiblePercentThreshold = 0,\n onError,\n onScroll,\n onItemPress,\n getNextPage,\n viewerWidth,\n windowSize = 3,\n pageUnit,\n ListFooterComponent,\n ...otherProps\n } = props;\n\n const flatListRef = useRef<FlatList>(null);\n\n const errors = useRef<Map<number, ErrorInfo>>(new Map());\n\n const debounceTimeOut = useRef<NodeJS.Timeout | null>(null);\n\n const resourceString = R.toString(R.map((itemData: ComicViewerItemData) => itemData.url)(data));\n\n const imageWidth = Math.min(viewerWidth, 720);\n const initialItems = R.map((itemData: ComicViewerItemData<T>) => ({\n ...itemData,\n isViewable: false,\n width: imageWidth,\n height: (itemData.height * imageWidth) / itemData.width,\n }))(data);\n\n const [items, setItems] = useState<ComicViewerItemProps<T>[]>(initialItems);\n\n const initialItemState: ComicViewerItemState[] = R.map((itemData: ComicViewerItemData<T>) => ({\n sortKey: itemData.sortKey,\n state: STATE.UNLOAD,\n }))(data);\n\n const itemStates = useRef<Array<ComicViewerItemState>>(initialItemState);\n\n const itemHeights = [...getItemHeights(items)];\n const itemHeightAccum = getHeightAccum(itemHeights);\n\n const viewabilityConfig = useMemo(() => ({\n itemVisiblePercentThreshold,\n }), [itemVisiblePercentThreshold]);\n\n const getItemLayout = useCallback((data: any, index: number) => {\n const offsets = R.prepend(0, itemHeightAccum[1]);\n\n return {\n length: itemHeights[index],\n offset: offsets[index],\n index,\n };\n }, [itemHeights]);\n\n const onViewableItemsChanged = useRef(({ viewableItems }: {\n viewableItems: Array<ViewToken>,\n }) => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n const viewableItemSortKeys = R.map((viewableItem: ViewToken) => viewableItem.item.sortKey)(viewableItems);\n\n const newItems = R.map((prevItem: ComicViewerItemProps<T>) => ({\n ...prevItem,\n isViewable: R.includes(prevItem.sortKey, viewableItemSortKeys),\n }))([...prev]);\n\n return newItems;\n });\n });\n\n const itemLoadedHandler = useCallback((sortKey: number) => {\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === sortKey)(itemStates.current);\n\n if (R.isNil(itemState)) {\n return;\n }\n\n itemState.state = STATE.LOADED;\n itemState.error = undefined;\n }, [itemStates]);\n\n const itemErrorHandler = useCallback((errorInfo: ErrorInfo) => {\n const { sortKey, count } = errorInfo;\n\n if (count >= errorRetryCount) {\n return;\n }\n\n errors.current.set(sortKey, errorInfo);\n\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === sortKey)(itemStates.current);\n\n if (R.isNil(itemState)) {\n return;\n }\n\n itemState.state = STATE.FAIL;\n itemState.error = errorInfo;\n\n const handleError = () => {\n const errorsArray = Array.from(errors.current.entries());\n const errorsInfo = R.map(([key, value]: [number, ErrorInfo]) => value)(errorsArray);\n\n onError && onError([...errorsInfo]);\n errors.current.clear();\n };\n\n if (debounceTimeOut.current) {\n clearTimeout(debounceTimeOut.current);\n }\n\n if (errors.current.size === pageUnit) {\n handleError();\n } else {\n debounceTimeOut.current = setTimeout(handleError, errorDebounceMillis);\n }\n }, [errors.current, itemStates]);\n\n const renderItem: ListRenderItem<ComicViewerItemProps<T>> = useCallback(({ item }) => {\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === item.sortKey)(itemStates.current);\n\n const props = {\n ...item,\n itemState,\n errorRetryCount,\n onError: itemErrorHandler,\n onLoaded: itemLoadedHandler,\n onItemPress,\n getNextPage,\n };\n\n return <ViewerItem props={props}/>;\n }, [resourceString, itemErrorHandler, itemLoadedHandler, onItemPress]);\n\n useEffect(() => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n return R.map((prevItem: ComicViewerItemProps<T>) => {\n const currentData: ComicViewerItemData | undefined = R.find((currentItemData: ComicViewerItemData<T>) => prevItem.sortKey === currentItemData.sortKey)(data);\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === currentData?.sortKey)(itemStates.current);\n\n if (currentData\n && itemState\n && itemState.state !== STATE.LOADED\n && (currentData.url !== prevItem.url)) {\n return {\n ...prevItem,\n url: currentData.url,\n expiresAt: currentData.expiresAt,\n };\n }\n\n return prevItem;\n })([...prev]);\n ;\n });\n }, [resourceString]);\n\n useEffect(() => {\n const newItems = R.map((item: ComicViewerItemProps<T>) => ({\n ...item,\n width: imageWidth,\n height: (item.height * imageWidth) / item.width,\n }))(items);\n\n setItems(newItems);\n }, [imageWidth]);\n\n useEffect(() => {\n const totalHeight = itemHeightAccum[0];\n const offset = Math.floor((initialScrollPercentage / 100) * totalHeight);\n\n if (flatListRef.current) {\n flatListRef.current.scrollToOffset({ offset, animated: false });\n }\n }, [flatListRef.current]);\n\n return (\n <FlatList\n data={items}\n getItemLayout={getItemLayout}\n initialNumToRender={initialNumToRender}\n keyExtractor={keyExtractor}\n onViewableItemsChanged={onViewableItemsChanged.current}\n onScroll={onScroll}\n ref={flatListRef}\n renderItem={renderItem}\n viewabilityConfig={viewabilityConfig}\n windowSize={windowSize}\n ListFooterComponent={ListFooterComponent}\n {...otherProps}\n />\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["ComicViewerItemProps.ts"],"sourcesContent":["import { ComicViewerItemData, ErrorInfo, ComicViewerItemState } from './ComicViewerProps';\n\ntype ComicViewerItemProps<T> = ComicViewerItemData<T> & {\n /**\n * FlatListItem is viewable in screen.\n */\n isViewable: boolean;\n\n /**\n * How many times retry onError when same item error occur\n * @default 3\n */\n errorRetryCount?: number;\n\n /**\n * Error handler\n */\n onError?: (errorInfo: ErrorInfo) => void;\n\n /**\n * Load handler\n */\n onLoaded?: (sortKey: number) => void;\n\n getNextPage?: (sortKey: number) => void;\n\n itemState?: ComicViewerItemState;\n}\n\nexport default ComicViewerItemProps;"],"mappings":""}
|
|
1
|
+
{"version":3,"names":[],"sources":["ComicViewerItemProps.ts"],"sourcesContent":["import { ComicViewerItemData, ErrorInfo, ComicViewerItemState } from './ComicViewerProps';\n\ntype ComicViewerItemProps<T> = ComicViewerItemData<T> & {\n /**\n * FlatListItem is viewable in screen.\n */\n isViewable: boolean;\n\n /**\n * How many times retry onError when same item error occur\n * @default 3\n */\n errorRetryCount?: number;\n\n /**\n * Error handler\n */\n onError?: (errorInfo: ErrorInfo) => void;\n\n /**\n * Load handler\n */\n onLoaded?: (sortKey: number) => void;\n\n /**\n * Method for getting next page contents.\n * @param sortKey\n */\n getNextPage?: (sortKey: number) => void;\n\n /**\n * Handle item press event.\n */\n onItemPress?: () => void;\n\n /**\n * Image loading state and error info.\n */\n itemState?: ComicViewerItemState;\n}\n\nexport default ComicViewerItemProps;"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["STATE","UNLOAD","LOADING","LOADED","FAIL"],"sources":["ComicViewerProps.ts"],"sourcesContent":["import React from 'react';\nimport { ComponentProps } from '@fountain-ui/core';\nimport { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';\n\nexport const STATE = {\n UNLOAD: 'unload',\n LOADING: 'loading',\n LOADED: 'loaded',\n FAIL: 'fail',\n} as const;\n\nexport type LoadingState = typeof STATE[keyof typeof STATE];\n\nexport interface ComicViewerItemState{\n /**\n * Content's loading state.\n */\n state: LoadingState
|
|
1
|
+
{"version":3,"names":["STATE","UNLOAD","LOADING","LOADED","FAIL"],"sources":["ComicViewerProps.ts"],"sourcesContent":["import React from 'react';\nimport { ComponentProps } from '@fountain-ui/core';\nimport { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';\n\nexport const STATE = {\n UNLOAD: 'unload',\n LOADING: 'loading',\n LOADED: 'loaded',\n FAIL: 'fail',\n} as const;\n\nexport type LoadingState = typeof STATE[keyof typeof STATE];\n\nexport interface ComicViewerItemState{\n /**\n * Comic viewer item sortKey.\n */\n sortKey: number;\n\n /**\n * Content's loading state.\n */\n state: LoadingState;\n\n /***\n * Content's error Info.\n */\n error?: ErrorInfo;\n}\n\nexport interface ErrorInfo {\n /**\n * ComicViewerItemData.sortKey.\n */\n sortKey: number;\n\n /**\n * Number of times an error occurred.\n */\n count: number;\n\n /**\n * Content is Expired: true\n */\n expired: boolean;\n}\n\nexport type ComicViewerItemData<T = {}> = T & {\n /**\n * Image height.\n */\n height: number;\n\n /**\n * Unique value for identifying.\n */\n id: number | undefined;\n\n /**\n * Image sourceUrl for displaying.\n */\n url: string;\n\n /**\n * Image width.\n */\n width: number;\n\n /**\n * SortKey\n */\n sortKey: number;\n\n /**\n * Image expire date.\n */\n expiresAt: string;\n}\n\nexport default interface ComicViewerProps<T> extends ComponentProps <{\n /**\n * Data for render.\n */\n data: ComicViewerItemData<T>[];\n\n /**\n * Delay Time to call the error handler.\n * @default 500\n */\n errorDebounceMillis?: number;\n\n /**\n * How many times retry onError when same item error occur\n * @default 3\n */\n errorRetryCount?: number;\n\n /**\n * How many items to render in the initial batch.\n * @default 1\n */\n initialNumToRender?: number;\n\n /**\n * Start at initialScrollPercentage.\n * If over 100, scroll to end.\n * @default 0\n */\n initialScrollPercentage?: number;\n\n /**\n * The value for FlatList viewabilityConfig.itemVisiblePercentThreshold.\n * @default 0\n */\n itemVisiblePercentThreshold?: number;\n\n /**\n * Comic viewer width.\n */\n viewerWidth: number;\n\n /**\n * The value for FlatList windowSize.\n * @default 3\n */\n windowSize?: number;\n\n /**\n * How many images in one page.\n */\n pageUnit: number;\n\n /**\n * Method for getting next page contents.\n * @param sortKey\n */\n getNextPage?: (sortKey: number) => void;\n\n /**\n * Handling all viewerItem errors at once.\n * @param errors Array of ViewerItems errorInfo.\n */\n onError?: (errors: ErrorInfo[]) => void;\n\n /**\n * Handle scroll event.\n * @param event Scroll event.\n */\n onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;\n\n /**\n * Handle item press event.\n */\n onItemPress?: () => void;\n\n /**\n * Component for comic viewer footer.\n */\n ListFooterComponent?: React.ReactElement;\n}> {}"],"mappings":"AAIA,OAAO,MAAMA,KAAK,GAAG;EACjBC,MAAM,EAAE,QADS;EAEjBC,OAAO,EAAE,SAFQ;EAGjBC,MAAM,EAAE,QAHS;EAIjBC,IAAI,EAAE;AAJW,CAAd"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
-
import { View } from 'react-native';
|
|
2
|
+
import { Pressable, View } from 'react-native';
|
|
3
3
|
import * as R from 'ramda';
|
|
4
4
|
import { IconButton, Image, Spacer, useTheme } from '@fountain-ui/core';
|
|
5
5
|
import { Restart } from '@fountain-ui/icons';
|
|
@@ -7,6 +7,11 @@ import { Restart } from '@fountain-ui/icons';
|
|
|
7
7
|
const useStyles = function () {
|
|
8
8
|
const theme = useTheme();
|
|
9
9
|
return {
|
|
10
|
+
root: {
|
|
11
|
+
display: 'flex',
|
|
12
|
+
flexDirection: 'row',
|
|
13
|
+
justifyContent: 'center'
|
|
14
|
+
},
|
|
10
15
|
init: {
|
|
11
16
|
backgroundColor: theme.palette.paper.grey
|
|
12
17
|
},
|
|
@@ -38,7 +43,8 @@ function ViewerItem(_ref) {
|
|
|
38
43
|
width,
|
|
39
44
|
getNextPage,
|
|
40
45
|
onError,
|
|
41
|
-
onLoaded
|
|
46
|
+
onLoaded,
|
|
47
|
+
onItemPress
|
|
42
48
|
} = props;
|
|
43
49
|
const [isLoaded, setIsLoaded] = useState(false);
|
|
44
50
|
const styles = useStyles();
|
|
@@ -50,7 +56,9 @@ function ViewerItem(_ref) {
|
|
|
50
56
|
}, [sortKey]);
|
|
51
57
|
const handleError = useCallback(() => {
|
|
52
58
|
errorCount.current = errorCount.current + 1;
|
|
53
|
-
const
|
|
59
|
+
const now = new Date();
|
|
60
|
+
const utcNow = now.getTime() + now.getTimezoneOffset() * 60 * 1000;
|
|
61
|
+
const expired = new Date(expiresAt).getTime() <= utcNow;
|
|
54
62
|
onError && onError({
|
|
55
63
|
sortKey,
|
|
56
64
|
count: errorCount.current,
|
|
@@ -75,7 +83,7 @@ function ViewerItem(_ref) {
|
|
|
75
83
|
failed
|
|
76
84
|
} = props;
|
|
77
85
|
|
|
78
|
-
if (!isViewable && !isLoaded) {
|
|
86
|
+
if (!isViewable && !isLoaded || url === '') {
|
|
79
87
|
return /*#__PURE__*/React.createElement(View, {
|
|
80
88
|
style: [viewStyle, styles.init]
|
|
81
89
|
});
|
|
@@ -107,25 +115,32 @@ function ViewerItem(_ref) {
|
|
|
107
115
|
});
|
|
108
116
|
}
|
|
109
117
|
|
|
110
|
-
return children ?
|
|
111
|
-
|
|
118
|
+
return children ? /*#__PURE__*/React.createElement(Pressable, {
|
|
119
|
+
onPress: onItemPress
|
|
120
|
+
}, children) : null;
|
|
121
|
+
}, [isViewable, isLoaded, errorCount.current, url, onItemPress]);
|
|
112
122
|
useEffect(() => {
|
|
113
123
|
if (url === '') {
|
|
114
124
|
getNextPage === null || getNextPage === void 0 ? void 0 : getNextPage(sortKey);
|
|
115
125
|
}
|
|
116
126
|
}, []);
|
|
117
|
-
return /*#__PURE__*/React.createElement(
|
|
127
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
128
|
+
style: styles.root
|
|
129
|
+
}, /*#__PURE__*/React.createElement(Image, {
|
|
118
130
|
disableOutline: true,
|
|
119
131
|
key: sortKey,
|
|
132
|
+
disableLongClick: true,
|
|
133
|
+
disableDrag: true,
|
|
120
134
|
onLoad: onLoad,
|
|
121
135
|
onError: handleError,
|
|
136
|
+
loading: 'eager',
|
|
122
137
|
source: {
|
|
123
138
|
uri: url
|
|
124
139
|
},
|
|
125
140
|
style: viewStyle,
|
|
126
141
|
square: true,
|
|
127
142
|
Placeholder: Placeholder
|
|
128
|
-
});
|
|
143
|
+
}));
|
|
129
144
|
}
|
|
130
145
|
|
|
131
146
|
export default /*#__PURE__*/React.memo(ViewerItem, (prevProps, nextProps) => {
|
|
@@ -137,6 +152,10 @@ export default /*#__PURE__*/React.memo(ViewerItem, (prevProps, nextProps) => {
|
|
|
137
152
|
return false;
|
|
138
153
|
}
|
|
139
154
|
|
|
155
|
+
if (prevProps.props.width !== nextProps.props.width) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
|
|
140
159
|
return true;
|
|
141
160
|
});
|
|
142
161
|
//# sourceMappingURL=ViewerItem.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useCallback","useEffect","useRef","useState","View","R","IconButton","Image","Spacer","useTheme","Restart","useStyles","theme","init","backgroundColor","palette","paper","grey","failed","reload","
|
|
1
|
+
{"version":3,"names":["React","useCallback","useEffect","useRef","useState","Pressable","View","R","IconButton","Image","Spacer","useTheme","Restart","useStyles","theme","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","styles","errorCount","defaultTo","error","count","onLoad","current","handleError","now","Date","utcNow","getTime","getTimezoneOffset","expired","onReloadPress","viewStyle","Placeholder","children","borderRadius","color","uri","memo","prevProps","nextProps"],"sources":["ViewerItem.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { Pressable, 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';\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 = { width, height };\n\n const Placeholder = useCallback((props: PlaceholderProps) => {\n const { children, failed } = props;\n\n if ((!isViewable && !isLoaded) || url === '') {\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 if (failed) {\n return (\n <View style={[\n viewStyle,\n styles.failed,\n ]}/>\n );\n }\n\n return children ? (\n <Pressable onPress={onItemPress}>\n {children}\n </Pressable>\n ) : null;\n }, [isViewable, isLoaded, errorCount.current, url, onItemPress]);\n\n useEffect(() => {\n if (url === '') {\n getNextPage?.(sortKey);\n }\n }, []);\n\n return (\n <View style={styles.root}>\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={viewStyle}\n square={true}\n Placeholder={Placeholder}\n />\n </View>\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 return true;\n});\n"],"mappings":"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"}
|
|
@@ -17,7 +17,18 @@ declare type ComicViewerItemProps<T> = ComicViewerItemData<T> & {
|
|
|
17
17
|
* Load handler
|
|
18
18
|
*/
|
|
19
19
|
onLoaded?: (sortKey: number) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Method for getting next page contents.
|
|
22
|
+
* @param sortKey
|
|
23
|
+
*/
|
|
20
24
|
getNextPage?: (sortKey: number) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Handle item press event.
|
|
27
|
+
*/
|
|
28
|
+
onItemPress?: () => void;
|
|
29
|
+
/**
|
|
30
|
+
* Image loading state and error info.
|
|
31
|
+
*/
|
|
21
32
|
itemState?: ComicViewerItemState;
|
|
22
33
|
};
|
|
23
34
|
export default ComicViewerItemProps;
|
|
@@ -9,6 +9,10 @@ export declare const STATE: {
|
|
|
9
9
|
};
|
|
10
10
|
export declare type LoadingState = typeof STATE[keyof typeof STATE];
|
|
11
11
|
export interface ComicViewerItemState {
|
|
12
|
+
/**
|
|
13
|
+
* Comic viewer item sortKey.
|
|
14
|
+
*/
|
|
15
|
+
sortKey: number;
|
|
12
16
|
/**
|
|
13
17
|
* Content's loading state.
|
|
14
18
|
*/
|
|
@@ -117,6 +121,10 @@ export default interface ComicViewerProps<T> extends ComponentProps<{
|
|
|
117
121
|
* @param event Scroll event.
|
|
118
122
|
*/
|
|
119
123
|
onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
124
|
+
/**
|
|
125
|
+
* Handle item press event.
|
|
126
|
+
*/
|
|
127
|
+
onItemPress?: () => void;
|
|
120
128
|
/**
|
|
121
129
|
* Component for comic viewer footer.
|
|
122
130
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fountain-ui/lab",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.32",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Fountain-UI Team",
|
|
6
6
|
"description": "Incubator for Fountain-UI React components.",
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
"publishConfig": {
|
|
71
71
|
"access": "public"
|
|
72
72
|
},
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "c2b92cc0980304e20d1fb3e025a5d230a46f2ff2"
|
|
74
74
|
}
|
|
@@ -27,6 +27,7 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
|
|
|
27
27
|
itemVisiblePercentThreshold = 0,
|
|
28
28
|
onError,
|
|
29
29
|
onScroll,
|
|
30
|
+
onItemPress,
|
|
30
31
|
getNextPage,
|
|
31
32
|
viewerWidth,
|
|
32
33
|
windowSize = 3,
|
|
@@ -43,16 +44,18 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
|
|
|
43
44
|
|
|
44
45
|
const resourceString = R.toString(R.map((itemData: ComicViewerItemData) => itemData.url)(data));
|
|
45
46
|
|
|
47
|
+
const imageWidth = Math.min(viewerWidth, 720);
|
|
46
48
|
const initialItems = R.map((itemData: ComicViewerItemData<T>) => ({
|
|
47
49
|
...itemData,
|
|
48
50
|
isViewable: false,
|
|
49
|
-
width:
|
|
50
|
-
height: (itemData.height *
|
|
51
|
+
width: imageWidth,
|
|
52
|
+
height: (itemData.height * imageWidth) / itemData.width,
|
|
51
53
|
}))(data);
|
|
52
54
|
|
|
53
55
|
const [items, setItems] = useState<ComicViewerItemProps<T>[]>(initialItems);
|
|
54
56
|
|
|
55
|
-
const initialItemState: ComicViewerItemState[] = R.map(() => ({
|
|
57
|
+
const initialItemState: ComicViewerItemState[] = R.map((itemData: ComicViewerItemData<T>) => ({
|
|
58
|
+
sortKey: itemData.sortKey,
|
|
56
59
|
state: STATE.UNLOAD,
|
|
57
60
|
}))(data);
|
|
58
61
|
|
|
@@ -91,7 +94,12 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
|
|
|
91
94
|
});
|
|
92
95
|
|
|
93
96
|
const itemLoadedHandler = useCallback((sortKey: number) => {
|
|
94
|
-
const itemState =
|
|
97
|
+
const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === sortKey)(itemStates.current);
|
|
98
|
+
|
|
99
|
+
if (R.isNil(itemState)) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
95
103
|
itemState.state = STATE.LOADED;
|
|
96
104
|
itemState.error = undefined;
|
|
97
105
|
}, [itemStates]);
|
|
@@ -105,7 +113,12 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
|
|
|
105
113
|
|
|
106
114
|
errors.current.set(sortKey, errorInfo);
|
|
107
115
|
|
|
108
|
-
const itemState =
|
|
116
|
+
const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === sortKey)(itemStates.current);
|
|
117
|
+
|
|
118
|
+
if (R.isNil(itemState)) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
109
122
|
itemState.state = STATE.FAIL;
|
|
110
123
|
itemState.error = errorInfo;
|
|
111
124
|
|
|
@@ -129,7 +142,7 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
|
|
|
129
142
|
}, [errors.current, itemStates]);
|
|
130
143
|
|
|
131
144
|
const renderItem: ListRenderItem<ComicViewerItemProps<T>> = useCallback(({ item }) => {
|
|
132
|
-
const itemState =
|
|
145
|
+
const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === item.sortKey)(itemStates.current);
|
|
133
146
|
|
|
134
147
|
const props = {
|
|
135
148
|
...item,
|
|
@@ -137,19 +150,22 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
|
|
|
137
150
|
errorRetryCount,
|
|
138
151
|
onError: itemErrorHandler,
|
|
139
152
|
onLoaded: itemLoadedHandler,
|
|
153
|
+
onItemPress,
|
|
140
154
|
getNextPage,
|
|
141
155
|
};
|
|
142
156
|
|
|
143
157
|
return <ViewerItem props={props}/>;
|
|
144
|
-
}, [resourceString,
|
|
158
|
+
}, [resourceString, itemErrorHandler, itemLoadedHandler, onItemPress]);
|
|
145
159
|
|
|
146
160
|
useEffect(() => {
|
|
147
161
|
setItems((prev: ComicViewerItemProps<T>[]) => {
|
|
148
162
|
return R.map((prevItem: ComicViewerItemProps<T>) => {
|
|
149
|
-
const currentData = R.find((currentItemData: ComicViewerItemData<T>) => prevItem.sortKey === currentItemData.sortKey)(data);
|
|
163
|
+
const currentData: ComicViewerItemData | undefined = R.find((currentItemData: ComicViewerItemData<T>) => prevItem.sortKey === currentItemData.sortKey)(data);
|
|
164
|
+
const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === currentData?.sortKey)(itemStates.current);
|
|
150
165
|
|
|
151
166
|
if (currentData
|
|
152
|
-
&&
|
|
167
|
+
&& itemState
|
|
168
|
+
&& itemState.state !== STATE.LOADED
|
|
153
169
|
&& (currentData.url !== prevItem.url)) {
|
|
154
170
|
return {
|
|
155
171
|
...prevItem,
|
|
@@ -167,12 +183,12 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
|
|
|
167
183
|
useEffect(() => {
|
|
168
184
|
const newItems = R.map((item: ComicViewerItemProps<T>) => ({
|
|
169
185
|
...item,
|
|
170
|
-
width:
|
|
171
|
-
height: (item.height *
|
|
186
|
+
width: imageWidth,
|
|
187
|
+
height: (item.height * imageWidth) / item.width,
|
|
172
188
|
}))(items);
|
|
173
189
|
|
|
174
190
|
setItems(newItems);
|
|
175
|
-
}, [
|
|
191
|
+
}, [imageWidth]);
|
|
176
192
|
|
|
177
193
|
useEffect(() => {
|
|
178
194
|
const totalHeight = itemHeightAccum[0];
|
|
@@ -22,8 +22,20 @@ type ComicViewerItemProps<T> = ComicViewerItemData<T> & {
|
|
|
22
22
|
*/
|
|
23
23
|
onLoaded?: (sortKey: number) => void;
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Method for getting next page contents.
|
|
27
|
+
* @param sortKey
|
|
28
|
+
*/
|
|
25
29
|
getNextPage?: (sortKey: number) => void;
|
|
26
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Handle item press event.
|
|
33
|
+
*/
|
|
34
|
+
onItemPress?: () => void;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Image loading state and error info.
|
|
38
|
+
*/
|
|
27
39
|
itemState?: ComicViewerItemState;
|
|
28
40
|
}
|
|
29
41
|
|
|
@@ -12,15 +12,20 @@ export const STATE = {
|
|
|
12
12
|
export type LoadingState = typeof STATE[keyof typeof STATE];
|
|
13
13
|
|
|
14
14
|
export interface ComicViewerItemState{
|
|
15
|
+
/**
|
|
16
|
+
* Comic viewer item sortKey.
|
|
17
|
+
*/
|
|
18
|
+
sortKey: number;
|
|
19
|
+
|
|
15
20
|
/**
|
|
16
21
|
* Content's loading state.
|
|
17
22
|
*/
|
|
18
|
-
state: LoadingState
|
|
23
|
+
state: LoadingState;
|
|
19
24
|
|
|
20
25
|
/***
|
|
21
26
|
* Content's error Info.
|
|
22
27
|
*/
|
|
23
|
-
error?: ErrorInfo
|
|
28
|
+
error?: ErrorInfo;
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
export interface ErrorInfo {
|
|
@@ -143,6 +148,11 @@ export default interface ComicViewerProps<T> extends ComponentProps <{
|
|
|
143
148
|
*/
|
|
144
149
|
onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
145
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Handle item press event.
|
|
153
|
+
*/
|
|
154
|
+
onItemPress?: () => void;
|
|
155
|
+
|
|
146
156
|
/**
|
|
147
157
|
* Component for comic viewer footer.
|
|
148
158
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
-
import { View } from 'react-native';
|
|
2
|
+
import { Pressable, View } from 'react-native';
|
|
3
3
|
import * as R from 'ramda';
|
|
4
4
|
import type { PlaceholderProps } from '@fountain-ui/core';
|
|
5
5
|
import { IconButton, Image, Spacer, useTheme } from '@fountain-ui/core';
|
|
@@ -7,12 +7,17 @@ import { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';
|
|
|
7
7
|
import { Restart } from '@fountain-ui/icons';
|
|
8
8
|
import ComicViewerItemProps from './ComicViewerItemProps';
|
|
9
9
|
|
|
10
|
-
type PlaceholderStyles = NamedStylesStringUnion<'init' | 'failed' | 'reload'>;
|
|
10
|
+
type PlaceholderStyles = NamedStylesStringUnion<'init' | 'failed' | 'reload' | 'root'>;
|
|
11
11
|
|
|
12
12
|
const useStyles: UseStyles<PlaceholderStyles> = function (): PlaceholderStyles {
|
|
13
13
|
const theme = useTheme();
|
|
14
14
|
|
|
15
15
|
return {
|
|
16
|
+
root: {
|
|
17
|
+
display: 'flex',
|
|
18
|
+
flexDirection: 'row',
|
|
19
|
+
justifyContent: 'center',
|
|
20
|
+
},
|
|
16
21
|
init: {
|
|
17
22
|
backgroundColor: theme.palette.paper.grey,
|
|
18
23
|
},
|
|
@@ -40,6 +45,7 @@ function ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {
|
|
|
40
45
|
getNextPage,
|
|
41
46
|
onError,
|
|
42
47
|
onLoaded,
|
|
48
|
+
onItemPress,
|
|
43
49
|
} = props;
|
|
44
50
|
|
|
45
51
|
const [isLoaded, setIsLoaded] = useState(false);
|
|
@@ -59,7 +65,9 @@ function ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {
|
|
|
59
65
|
const handleError = useCallback(() => {
|
|
60
66
|
errorCount.current = errorCount.current + 1;
|
|
61
67
|
|
|
62
|
-
const
|
|
68
|
+
const now = new Date();
|
|
69
|
+
const utcNow = now.getTime() + (now.getTimezoneOffset() * 60 * 1000);
|
|
70
|
+
const expired = new Date(expiresAt).getTime() <= utcNow;
|
|
63
71
|
|
|
64
72
|
onError && onError({
|
|
65
73
|
sortKey,
|
|
@@ -83,7 +91,7 @@ function ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {
|
|
|
83
91
|
const Placeholder = useCallback((props: PlaceholderProps) => {
|
|
84
92
|
const { children, failed } = props;
|
|
85
93
|
|
|
86
|
-
if (!isViewable && !isLoaded) {
|
|
94
|
+
if ((!isViewable && !isLoaded) || url === '') {
|
|
87
95
|
return <View style={[
|
|
88
96
|
viewStyle,
|
|
89
97
|
styles.init,
|
|
@@ -120,8 +128,12 @@ function ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {
|
|
|
120
128
|
);
|
|
121
129
|
}
|
|
122
130
|
|
|
123
|
-
return children ?
|
|
124
|
-
|
|
131
|
+
return children ? (
|
|
132
|
+
<Pressable onPress={onItemPress}>
|
|
133
|
+
{children}
|
|
134
|
+
</Pressable>
|
|
135
|
+
) : null;
|
|
136
|
+
}, [isViewable, isLoaded, errorCount.current, url, onItemPress]);
|
|
125
137
|
|
|
126
138
|
useEffect(() => {
|
|
127
139
|
if (url === '') {
|
|
@@ -130,16 +142,21 @@ function ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {
|
|
|
130
142
|
}, []);
|
|
131
143
|
|
|
132
144
|
return (
|
|
133
|
-
<
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
145
|
+
<View style={styles.root}>
|
|
146
|
+
<Image
|
|
147
|
+
disableOutline={true}
|
|
148
|
+
key={sortKey}
|
|
149
|
+
disableLongClick={true}
|
|
150
|
+
disableDrag={true}
|
|
151
|
+
onLoad={onLoad}
|
|
152
|
+
onError={handleError}
|
|
153
|
+
loading={'eager'}
|
|
154
|
+
source={{ uri: url }}
|
|
155
|
+
style={viewStyle}
|
|
156
|
+
square={true}
|
|
157
|
+
Placeholder={Placeholder}
|
|
158
|
+
/>
|
|
159
|
+
</View>
|
|
143
160
|
);
|
|
144
161
|
}
|
|
145
162
|
|
|
@@ -152,5 +169,9 @@ export default React.memo(ViewerItem, (prevProps, nextProps) => {
|
|
|
152
169
|
return false;
|
|
153
170
|
}
|
|
154
171
|
|
|
172
|
+
if (prevProps.props.width !== nextProps.props.width) {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
|
|
155
176
|
return true;
|
|
156
177
|
});
|