@fountain-ui/lab 2.0.0-beta.52 → 2.0.0-beta.54
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 +30 -37
- package/build/commonjs/ComicViewer/ComicViewer.js.map +1 -1
- package/build/commonjs/ComicViewer/FastScroll.js +6 -4
- package/build/commonjs/ComicViewer/FastScroll.js.map +1 -1
- package/build/module/ComicViewer/ComicViewer.js +31 -38
- package/build/module/ComicViewer/ComicViewer.js.map +1 -1
- package/build/module/ComicViewer/FastScroll.js +6 -4
- package/build/module/ComicViewer/FastScroll.js.map +1 -1
- package/package.json +2 -2
- package/src/ComicViewer/ComicViewer.tsx +28 -39
- package/src/ComicViewer/FastScroll.tsx +6 -5
|
@@ -53,7 +53,6 @@ const mapImageStateToItemState = (index, imageState, autoHandleErrorCount) => {
|
|
|
53
53
|
|
|
54
54
|
const mapIndexed = R.addIndex(R.map);
|
|
55
55
|
const MAXIMUM_WIDTH = 720;
|
|
56
|
-
const NUMBER_OF_ADJACENT_ITEM = 5;
|
|
57
56
|
|
|
58
57
|
function ComicViewer(props) {
|
|
59
58
|
const {
|
|
@@ -76,7 +75,6 @@ function ComicViewer(props) {
|
|
|
76
75
|
} = props;
|
|
77
76
|
const fastScrollRef = fastScrollOptions === null || fastScrollOptions === void 0 ? void 0 : fastScrollOptions.ref;
|
|
78
77
|
const flatListRef = (0, _react.useRef)(null);
|
|
79
|
-
const maybeLoadableItemsIndexRange = (0, _react.useRef)([-1, 0]);
|
|
80
78
|
const actualImageWidth = Math.min(viewportWidth, maxContentWidth);
|
|
81
79
|
const initialImageStates = (0, _react.useMemo)(() => R.map(createInitialImageState, intrinsicImages), []);
|
|
82
80
|
const imageStatesRef = (0, _react.useRef)(initialImageStates);
|
|
@@ -131,13 +129,12 @@ function ComicViewer(props) {
|
|
|
131
129
|
});
|
|
132
130
|
};
|
|
133
131
|
|
|
134
|
-
const
|
|
132
|
+
const updateTryRenderingMillis = () => {
|
|
135
133
|
const tryRenderingMillis = new Date().getTime();
|
|
136
134
|
updateImageState((imageState, i) => {
|
|
137
135
|
const urlState = imageState.urlState;
|
|
138
|
-
const shouldRerender = R.includes(i, R.defaultTo([], indexes));
|
|
139
136
|
|
|
140
|
-
if (
|
|
137
|
+
if ((urlState === null || urlState === void 0 ? void 0 : urlState.validity) === 'invalid') {
|
|
141
138
|
return { ...imageState,
|
|
142
139
|
tryRenderingMillis
|
|
143
140
|
};
|
|
@@ -147,30 +144,11 @@ function ComicViewer(props) {
|
|
|
147
144
|
});
|
|
148
145
|
};
|
|
149
146
|
|
|
150
|
-
const renderMaybeLoadableItems = () => {
|
|
151
|
-
const [startIndex, endIndex] = maybeLoadableItemsIndexRange.current;
|
|
152
|
-
const affectedIndexes = R.range(startIndex, endIndex);
|
|
153
|
-
updateItems(affectedIndexes);
|
|
154
|
-
};
|
|
155
|
-
|
|
156
147
|
const onViewableItemsChanged = (0, _react.useRef)(_ref => {
|
|
157
|
-
var _R$head, _R$last;
|
|
158
|
-
|
|
159
148
|
let {
|
|
160
149
|
viewableItems
|
|
161
150
|
} = _ref;
|
|
162
|
-
|
|
163
|
-
const firstViewableIndex = (_R$head = R.head(orderedViewableItems)) === null || _R$head === void 0 ? void 0 : _R$head.index;
|
|
164
|
-
const lastViewableItemIndex = (_R$last = R.last(orderedViewableItems)) === null || _R$last === void 0 ? void 0 : _R$last.index;
|
|
165
|
-
|
|
166
|
-
if (R.isNil(firstViewableIndex) || R.isNil(lastViewableItemIndex)) {
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const startIndex = R.max(firstViewableIndex - NUMBER_OF_ADJACENT_ITEM, 0);
|
|
171
|
-
const endIndex = R.min(lastViewableItemIndex + NUMBER_OF_ADJACENT_ITEM, itemStates.length - 1);
|
|
172
|
-
maybeLoadableItemsIndexRange.current = [startIndex, endIndex + 1];
|
|
173
|
-
renderMaybeLoadableItems();
|
|
151
|
+
updateTryRenderingMillis();
|
|
174
152
|
});
|
|
175
153
|
const handleScroll = (0, _react.useCallback)(event => {
|
|
176
154
|
var _fastScrollRef$curren;
|
|
@@ -217,16 +195,12 @@ function ComicViewer(props) {
|
|
|
217
195
|
return;
|
|
218
196
|
}
|
|
219
197
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if (index >= startIndex || index < endIndex) {
|
|
223
|
-
renderMaybeLoadableItems();
|
|
224
|
-
}
|
|
198
|
+
updateTryRenderingMillis();
|
|
225
199
|
};
|
|
226
200
|
|
|
227
201
|
const handleReloadPress = () => {
|
|
228
202
|
onReloadPress && onReloadPress();
|
|
229
|
-
|
|
203
|
+
updateTryRenderingMillis();
|
|
230
204
|
};
|
|
231
205
|
|
|
232
206
|
const onLoad = () => {
|
|
@@ -259,14 +233,33 @@ function ComicViewer(props) {
|
|
|
259
233
|
});
|
|
260
234
|
}, [onItemPress, renderedDimensions]);
|
|
261
235
|
(0, _react.useEffect)(() => {
|
|
262
|
-
const
|
|
236
|
+
const scroll = () => {
|
|
237
|
+
const offset = Math.floor(initialScrollPercentage / 100 * totalHeight);
|
|
238
|
+
|
|
239
|
+
if (flatListRef.current) {
|
|
240
|
+
flatListRef.current.scrollToOffset({
|
|
241
|
+
offset,
|
|
242
|
+
animated: false
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
};
|
|
263
246
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
247
|
+
let timeoutId = undefined;
|
|
248
|
+
/**
|
|
249
|
+
* @FIXME
|
|
250
|
+
* scrollToOffset has issue(no effect) in useEffect hook on iOS.
|
|
251
|
+
* ref: https://github.com/facebook/react-native/issues/35575
|
|
252
|
+
*/
|
|
253
|
+
|
|
254
|
+
if (_reactNative.Platform.OS === 'ios') {
|
|
255
|
+
timeoutId = setTimeout(scroll, 0);
|
|
256
|
+
} else {
|
|
257
|
+
scroll();
|
|
269
258
|
}
|
|
259
|
+
|
|
260
|
+
return () => {
|
|
261
|
+
timeoutId && clearTimeout(timeoutId);
|
|
262
|
+
};
|
|
270
263
|
}, []);
|
|
271
264
|
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_reactNative.FlatList, _extends({
|
|
272
265
|
data: itemStates,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["appender","left","right","getHeightAccum","heights","R","mapAccum","keyExtractor","item","String","index","createInitialImageState","image","totalErrorCount","dimension","tryRenderingMillis","urlState","url","validity","mapImageStateToItemState","imageState","autoHandleErrorCount","imageKey","reloadButtonVisible","mapIndexed","addIndex","map","MAXIMUM_WIDTH","NUMBER_OF_ADJACENT_ITEM","ComicViewer","props","debounceMillis","fastScrollOptions","initialNumToRender","initialScrollPercentage","itemVisiblePercentThreshold","intrinsicImages","maxContentWidth","onItemPress","onScroll","onError","onReloadPress","viewportWidth","invisiblePaddingTop","windowSize","otherProps","fastScrollRef","ref","flatListRef","useRef","maybeLoadableItemsIndexRange","actualImageWidth","Math","min","initialImageStates","useMemo","imageStatesRef","mapImageStatesToItemStates","imageStates","itemStates","setItemStates","useState","current","renderedDimensions","intrinsicImage","height","width","isNaN","layoutFromDimensions","useCallback","itemHeights","totalHeight","heightAccum","itemOffsets","prepend","getItemLayout","data","length","offset","viewabilityConfig","updateImageState","updateFunction","prevImageStates","newImageStates","prevItemStates","newItemStates","equals","updateItems","indexes","Date","getTime","i","shouldRerender","includes","defaultTo","renderMaybeLoadableItems","startIndex","endIndex","affectedIndexes","range","onViewableItemsChanged","viewableItems","orderedViewableItems","sort","a","b","firstViewableIndex","head","lastViewableItemIndex","last","isNil","max","handleScroll","event","onContentScroll","scrollContentToOffset","scrollToOffset","animated","renderItem","handleError","handleReloadPress","onLoad","undefined","useEffect","floor"],"sources":["ComicViewer.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { FlatList, ListRenderItem, NativeScrollEvent, NativeSyntheticEvent, ViewToken } from 'react-native';\nimport * as R from 'ramda';\nimport { default as ComicViewerProps, Dimension, IntrinsicImage } from './ComicViewerProps';\nimport ViewerItem from './ViewerItem';\nimport FastScroll from './FastScroll';\n\nconst appender = (left: number, right: number): [number, number] => [left + right, left + right];\nconst getHeightAccum = (heights: number[]): [number, number[]] => R.mapAccum(appender, 0, heights);\n\nconst keyExtractor = <T, >(item: ItemState) => String(item.index);\n\ninterface UrlState {\n url: string;\n validity: 'valid' | 'invalid' | 'unknown';\n}\n\ninterface ImageState {\n urlState: UrlState;\n totalErrorCount: number;\n dimension: Dimension;\n tryRenderingMillis: number;\n}\n\ninterface ItemState {\n index: number;\n url?: string;\n imageKey: string;\n reloadButtonVisible: boolean;\n dimension: Dimension;\n}\n\nconst createInitialImageState = (image: IntrinsicImage): ImageState => ({\n totalErrorCount: 0,\n dimension: image.dimension,\n tryRenderingMillis: 0,\n urlState: {\n url: image.url,\n validity: 'unknown',\n },\n});\n\nconst mapImageStateToItemState = (\n index: number,\n imageState: ImageState,\n autoHandleErrorCount: number,\n): ItemState => ({\n index,\n url: imageState.urlState?.url,\n imageKey: `${imageState.tryRenderingMillis}-${index}`,\n reloadButtonVisible: (imageState.urlState?.validity !== 'valid') && imageState.totalErrorCount >= autoHandleErrorCount,\n dimension: imageState.dimension,\n});\n\nconst mapIndexed = R.addIndex<IntrinsicImage>(R.map);\n\nconst MAXIMUM_WIDTH = 720;\n\nconst NUMBER_OF_ADJACENT_ITEM = 5;\n\nexport default function ComicViewer(props: ComicViewerProps) {\n const {\n debounceMillis = 100,\n autoHandleErrorCount = 3,\n fastScrollOptions,\n initialNumToRender = 1,\n initialScrollPercentage = 0,\n itemVisiblePercentThreshold = 0,\n intrinsicImages,\n maxContentWidth = MAXIMUM_WIDTH,\n onItemPress,\n onScroll,\n onError,\n onReloadPress,\n viewportWidth,\n invisiblePaddingTop = 0,\n windowSize = 3,\n ...otherProps\n } = props;\n\n const fastScrollRef = fastScrollOptions?.ref;\n\n const flatListRef = useRef<FlatList>(null);\n\n const maybeLoadableItemsIndexRange = useRef<[number, number]>([-1, 0]);\n\n const actualImageWidth = Math.min(viewportWidth, maxContentWidth);\n\n const initialImageStates = useMemo<Array<ImageState>>(() => R.map(createInitialImageState, intrinsicImages), []);\n\n const imageStatesRef = useRef<Array<ImageState>>(initialImageStates);\n\n const mapImageStatesToItemStates = (imageStates: Array<ImageState>): Array<ItemState> => {\n return imageStates.map((image, index) => mapImageStateToItemState(\n index, image, autoHandleErrorCount,\n ));\n };\n\n const [itemStates, setItemStates] = useState<Array<ItemState>>(() => {\n return mapImageStatesToItemStates(imageStatesRef.current);\n });\n\n const renderedDimensions = useMemo<Array<Dimension>>(() => {\n return mapIndexed((intrinsicImage, index) => {\n const height = (intrinsicImage.dimension.height * actualImageWidth) / intrinsicImage.dimension.width + (index === 0 ? invisiblePaddingTop : 0);\n\n return {\n width: actualImageWidth,\n height: isNaN(height) ? 0 : height,\n };\n }, intrinsicImages);\n }, [actualImageWidth]);\n\n const layoutFromDimensions = useCallback(() => {\n const itemHeights = R.map(dimension => dimension.height, renderedDimensions);\n const [totalHeight, heightAccum] = getHeightAccum(itemHeights);\n const itemOffsets = R.prepend(0, heightAccum);\n\n const getItemLayout = (data: any, index: number) => ({\n index,\n length: itemHeights[index],\n offset: itemOffsets[index],\n });\n\n return {\n totalHeight,\n getItemLayout,\n };\n }, [renderedDimensions]);\n\n const { totalHeight, getItemLayout } = layoutFromDimensions();\n\n const viewabilityConfig = useMemo(() => ({\n itemVisiblePercentThreshold,\n }), [itemVisiblePercentThreshold]);\n\n const updateImageState = (updateFunction: (prev: ImageState, index: number) => ImageState) => {\n const prevImageStates = imageStatesRef.current;\n const newImageStates = prevImageStates.map(updateFunction);\n\n imageStatesRef.current = newImageStates;\n\n setItemStates(prevItemStates => {\n const newItemStates = mapImageStatesToItemStates(newImageStates);\n\n return R.equals(prevItemStates, newItemStates) ? prevItemStates : newItemStates;\n });\n };\n\n const updateItems = (indexes: number[]) => {\n const tryRenderingMillis = new Date().getTime();\n\n updateImageState((imageState, i) => {\n const urlState = imageState.urlState;\n const shouldRerender = R.includes(i, R.defaultTo([], indexes));\n\n if (shouldRerender && urlState?.validity !== 'valid') {\n return {\n ...imageState,\n tryRenderingMillis,\n };\n }\n\n return imageState;\n });\n };\n\n const renderMaybeLoadableItems = () => {\n const [startIndex, endIndex] = maybeLoadableItemsIndexRange.current;\n const affectedIndexes = R.range(startIndex, endIndex);\n\n updateItems(affectedIndexes);\n };\n\n const onViewableItemsChanged = useRef(({ viewableItems }: { viewableItems: Array<ViewToken> }) => {\n const orderedViewableItems = R.sort((a, b) => (a.index || 0) - (b.index || 0), viewableItems);\n\n const firstViewableIndex = R.head(orderedViewableItems)?.index;\n const lastViewableItemIndex = R.last(orderedViewableItems)?.index;\n\n if (R.isNil(firstViewableIndex) || R.isNil(lastViewableItemIndex)) {\n return;\n }\n\n const startIndex = R.max(firstViewableIndex - NUMBER_OF_ADJACENT_ITEM, 0);\n const endIndex = R.min(lastViewableItemIndex + NUMBER_OF_ADJACENT_ITEM, itemStates.length - 1);\n\n maybeLoadableItemsIndexRange.current = [startIndex, endIndex + 1];\n\n renderMaybeLoadableItems();\n });\n\n const handleScroll = useCallback((event: NativeSyntheticEvent<NativeScrollEvent>) => {\n fastScrollRef?.current?.onContentScroll(event);\n\n onScroll?.(event);\n }, [onScroll]);\n\n const scrollContentToOffset = (offset: number) => {\n flatListRef.current?.scrollToOffset({\n offset,\n animated: false,\n });\n };\n\n const renderItem: ListRenderItem<ItemState> = useCallback(({ item, index }) => {\n const handleError = () => {\n onError && onError();\n\n updateImageState((imageState, i) => {\n const urlState = imageState.urlState;\n\n if (i === index) {\n return {\n ...imageState,\n totalErrorCount: imageState.totalErrorCount + 1,\n urlState: {\n ...urlState,\n validity: 'invalid',\n },\n };\n }\n\n return imageState;\n });\n\n if (item.reloadButtonVisible) {\n return;\n }\n\n const [startIndex, endIndex] = maybeLoadableItemsIndexRange.current;\n if (index >= startIndex || index < endIndex) {\n renderMaybeLoadableItems();\n }\n };\n\n const handleReloadPress = () => {\n onReloadPress && onReloadPress();\n\n updateItems([index]);\n };\n\n const onLoad = () => {\n updateImageState((imageState, i) => {\n const urlState = imageState.urlState;\n\n if (i === index && urlState !== undefined) {\n return {\n ...imageState,\n urlState: {\n ...urlState,\n validity: 'valid',\n },\n };\n }\n\n return imageState;\n });\n };\n\n return (\n <ViewerItem\n onError={handleError}\n onLoad={onLoad}\n onPress={onItemPress}\n onReloadPress={handleReloadPress}\n url={item.url}\n imageKey={item.imageKey}\n invisiblePaddingTop={index === 0 ? invisiblePaddingTop : 0}\n width={renderedDimensions[index]?.width ?? 0}\n height={renderedDimensions[index]?.height ?? 0}\n reloadButtonVisible={item.reloadButtonVisible}\n />\n );\n }, [onItemPress, renderedDimensions]);\n\n useEffect(() => {\n const offset = Math.floor((initialScrollPercentage / 100) * totalHeight);\n\n if (flatListRef.current) {\n flatListRef.current.scrollToOffset({ offset, animated: false });\n }\n }, []);\n\n return (\n <React.Fragment>\n <FlatList\n data={itemStates}\n getItemLayout={getItemLayout}\n initialNumToRender={initialNumToRender}\n keyExtractor={keyExtractor}\n onViewableItemsChanged={onViewableItemsChanged.current}\n ref={flatListRef}\n renderItem={renderItem}\n viewabilityConfig={viewabilityConfig}\n windowSize={windowSize}\n onScroll={handleScroll}\n {...otherProps}\n />\n\n <FastScroll\n {...fastScrollOptions}\n contentLength={totalHeight}\n scrollContentToOffset={scrollContentToOffset}\n />\n </React.Fragment>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["appender","left","right","getHeightAccum","heights","R","mapAccum","keyExtractor","item","String","index","createInitialImageState","image","totalErrorCount","dimension","tryRenderingMillis","urlState","url","validity","mapImageStateToItemState","imageState","autoHandleErrorCount","imageKey","reloadButtonVisible","mapIndexed","addIndex","map","MAXIMUM_WIDTH","ComicViewer","props","debounceMillis","fastScrollOptions","initialNumToRender","initialScrollPercentage","itemVisiblePercentThreshold","intrinsicImages","maxContentWidth","onItemPress","onScroll","onError","onReloadPress","viewportWidth","invisiblePaddingTop","windowSize","otherProps","fastScrollRef","ref","flatListRef","useRef","actualImageWidth","Math","min","initialImageStates","useMemo","imageStatesRef","mapImageStatesToItemStates","imageStates","itemStates","setItemStates","useState","current","renderedDimensions","intrinsicImage","height","width","isNaN","layoutFromDimensions","useCallback","itemHeights","totalHeight","heightAccum","itemOffsets","prepend","getItemLayout","data","length","offset","viewabilityConfig","updateImageState","updateFunction","prevImageStates","newImageStates","prevItemStates","newItemStates","equals","updateTryRenderingMillis","Date","getTime","i","onViewableItemsChanged","viewableItems","handleScroll","event","onContentScroll","scrollContentToOffset","scrollToOffset","animated","renderItem","handleError","handleReloadPress","onLoad","undefined","useEffect","scroll","floor","timeoutId","Platform","OS","setTimeout","clearTimeout"],"sources":["ComicViewer.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { FlatList, ListRenderItem, NativeScrollEvent, NativeSyntheticEvent, Platform, ViewToken } from 'react-native';\nimport * as R from 'ramda';\nimport { default as ComicViewerProps, Dimension, IntrinsicImage } from './ComicViewerProps';\nimport ViewerItem from './ViewerItem';\nimport FastScroll from './FastScroll';\n\nconst appender = (left: number, right: number): [number, number] => [left + right, left + right];\nconst getHeightAccum = (heights: number[]): [number, number[]] => R.mapAccum(appender, 0, heights);\n\nconst keyExtractor = <T, >(item: ItemState) => String(item.index);\n\ninterface UrlState {\n url: string;\n validity: 'valid' | 'invalid' | 'unknown';\n}\n\ninterface ImageState {\n urlState: UrlState;\n totalErrorCount: number;\n dimension: Dimension;\n tryRenderingMillis: number;\n}\n\ninterface ItemState {\n index: number;\n url?: string;\n imageKey: string;\n reloadButtonVisible: boolean;\n dimension: Dimension;\n}\n\nconst createInitialImageState = (image: IntrinsicImage): ImageState => ({\n totalErrorCount: 0,\n dimension: image.dimension,\n tryRenderingMillis: 0,\n urlState: {\n url: image.url,\n validity: 'unknown',\n },\n});\n\nconst mapImageStateToItemState = (\n index: number,\n imageState: ImageState,\n autoHandleErrorCount: number,\n): ItemState => ({\n index,\n url: imageState.urlState?.url,\n imageKey: `${imageState.tryRenderingMillis}-${index}`,\n reloadButtonVisible: (imageState.urlState?.validity !== 'valid') && imageState.totalErrorCount >= autoHandleErrorCount,\n dimension: imageState.dimension,\n});\n\nconst mapIndexed = R.addIndex<IntrinsicImage>(R.map);\n\nconst MAXIMUM_WIDTH = 720;\n\nexport default function ComicViewer(props: ComicViewerProps) {\n const {\n debounceMillis = 100,\n autoHandleErrorCount = 3,\n fastScrollOptions,\n initialNumToRender = 1,\n initialScrollPercentage = 0,\n itemVisiblePercentThreshold = 0,\n intrinsicImages,\n maxContentWidth = MAXIMUM_WIDTH,\n onItemPress,\n onScroll,\n onError,\n onReloadPress,\n viewportWidth,\n invisiblePaddingTop = 0,\n windowSize = 3,\n ...otherProps\n } = props;\n\n const fastScrollRef = fastScrollOptions?.ref;\n\n const flatListRef = useRef<FlatList>(null);\n\n const actualImageWidth = Math.min(viewportWidth, maxContentWidth);\n\n const initialImageStates = useMemo<Array<ImageState>>(() => R.map(createInitialImageState, intrinsicImages), []);\n\n const imageStatesRef = useRef<Array<ImageState>>(initialImageStates);\n\n const mapImageStatesToItemStates = (imageStates: Array<ImageState>): Array<ItemState> => {\n return imageStates.map((image, index) => mapImageStateToItemState(\n index, image, autoHandleErrorCount,\n ));\n };\n\n const [itemStates, setItemStates] = useState<Array<ItemState>>(() => {\n return mapImageStatesToItemStates(imageStatesRef.current);\n });\n\n const renderedDimensions = useMemo<Array<Dimension>>(() => {\n return mapIndexed((intrinsicImage, index) => {\n const height = (intrinsicImage.dimension.height * actualImageWidth) / intrinsicImage.dimension.width + (index === 0 ? invisiblePaddingTop : 0);\n\n return {\n width: actualImageWidth,\n height: isNaN(height) ? 0 : height,\n };\n }, intrinsicImages);\n }, [actualImageWidth]);\n\n const layoutFromDimensions = useCallback(() => {\n const itemHeights = R.map(dimension => dimension.height, renderedDimensions);\n const [totalHeight, heightAccum] = getHeightAccum(itemHeights);\n const itemOffsets = R.prepend(0, heightAccum);\n\n const getItemLayout = (data: any, index: number) => ({\n index,\n length: itemHeights[index],\n offset: itemOffsets[index],\n });\n\n return {\n totalHeight,\n getItemLayout,\n };\n }, [renderedDimensions]);\n\n const { totalHeight, getItemLayout } = layoutFromDimensions();\n\n const viewabilityConfig = useMemo(() => ({\n itemVisiblePercentThreshold,\n }), [itemVisiblePercentThreshold]);\n\n const updateImageState = (updateFunction: (prev: ImageState, index: number) => ImageState) => {\n const prevImageStates = imageStatesRef.current;\n const newImageStates = prevImageStates.map(updateFunction);\n\n imageStatesRef.current = newImageStates;\n\n setItemStates(prevItemStates => {\n const newItemStates = mapImageStatesToItemStates(newImageStates);\n\n return R.equals(prevItemStates, newItemStates) ? prevItemStates : newItemStates;\n });\n };\n\n const updateTryRenderingMillis = () => {\n const tryRenderingMillis = new Date().getTime();\n\n updateImageState((imageState, i) => {\n const urlState = imageState.urlState;\n\n if (urlState?.validity === 'invalid') {\n return {\n ...imageState,\n tryRenderingMillis,\n };\n }\n\n return imageState;\n });\n };\n const onViewableItemsChanged = useRef(({ viewableItems }: { viewableItems: Array<ViewToken> }) => {\n updateTryRenderingMillis();\n });\n\n const handleScroll = useCallback((event: NativeSyntheticEvent<NativeScrollEvent>) => {\n fastScrollRef?.current?.onContentScroll(event);\n\n onScroll?.(event);\n }, [onScroll]);\n\n const scrollContentToOffset = (offset: number) => {\n flatListRef.current?.scrollToOffset({\n offset,\n animated: false,\n });\n };\n\n const renderItem: ListRenderItem<ItemState> = useCallback(({ item, index }) => {\n const handleError = () => {\n onError && onError();\n\n updateImageState((imageState, i) => {\n const urlState = imageState.urlState;\n\n if (i === index) {\n return {\n ...imageState,\n totalErrorCount: imageState.totalErrorCount + 1,\n urlState: {\n ...urlState,\n validity: 'invalid',\n },\n };\n }\n\n return imageState;\n });\n\n if (item.reloadButtonVisible) {\n return;\n }\n\n updateTryRenderingMillis();\n };\n\n const handleReloadPress = () => {\n onReloadPress && onReloadPress();\n\n updateTryRenderingMillis();\n };\n\n const onLoad = () => {\n updateImageState((imageState, i) => {\n const urlState = imageState.urlState;\n\n if (i === index && urlState !== undefined) {\n return {\n ...imageState,\n urlState: {\n ...urlState,\n validity: 'valid',\n },\n };\n }\n\n return imageState;\n });\n };\n\n return (\n <ViewerItem\n onError={handleError}\n onLoad={onLoad}\n onPress={onItemPress}\n onReloadPress={handleReloadPress}\n url={item.url}\n imageKey={item.imageKey}\n invisiblePaddingTop={index === 0 ? invisiblePaddingTop : 0}\n width={renderedDimensions[index]?.width ?? 0}\n height={renderedDimensions[index]?.height ?? 0}\n reloadButtonVisible={item.reloadButtonVisible}\n />\n );\n }, [onItemPress, renderedDimensions]);\n\n useEffect(() => {\n const scroll = () => {\n const offset = Math.floor((initialScrollPercentage / 100) * totalHeight);\n\n if (flatListRef.current) {\n flatListRef.current.scrollToOffset({ offset, animated: false });\n }\n };\n\n let timeoutId: NodeJS.Timeout | undefined = undefined;\n\n /**\n * @FIXME\n * scrollToOffset has issue(no effect) in useEffect hook on iOS.\n * ref: https://github.com/facebook/react-native/issues/35575\n */\n if (Platform.OS === 'ios') {\n timeoutId = setTimeout(scroll, 0);\n } else {\n scroll();\n }\n\n return () => {\n timeoutId && clearTimeout(timeoutId);\n }\n }, []);\n\n return (\n <React.Fragment>\n <FlatList\n data={itemStates}\n getItemLayout={getItemLayout}\n initialNumToRender={initialNumToRender}\n keyExtractor={keyExtractor}\n onViewableItemsChanged={onViewableItemsChanged.current}\n ref={flatListRef}\n renderItem={renderItem}\n viewabilityConfig={viewabilityConfig}\n windowSize={windowSize}\n onScroll={handleScroll}\n {...otherProps}\n />\n\n <FastScroll\n {...fastScrollOptions}\n contentLength={totalHeight}\n scrollContentToOffset={scrollContentToOffset}\n />\n </React.Fragment>\n );\n};\n"],"mappings":"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"}
|
|
@@ -25,14 +25,16 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
|
|
25
25
|
|
|
26
26
|
const styles = _core.StyleSheet.create({
|
|
27
27
|
indicator: {
|
|
28
|
-
width:
|
|
29
|
-
height:
|
|
28
|
+
width: 28,
|
|
29
|
+
height: 48,
|
|
30
30
|
backgroundColor: '#767676',
|
|
31
31
|
flexDirection: 'column',
|
|
32
32
|
alignItems: 'center',
|
|
33
|
-
|
|
33
|
+
justifyContent: 'center',
|
|
34
|
+
borderRadius: 16
|
|
34
35
|
},
|
|
35
36
|
view: {
|
|
37
|
+
padding: 4,
|
|
36
38
|
position: 'absolute'
|
|
37
39
|
}
|
|
38
40
|
});
|
|
@@ -63,7 +65,7 @@ const FastScroll = /*#__PURE__*/_react.default.forwardRef((props, ref) => {
|
|
|
63
65
|
const totalContentLength = contentLength + additionalLength;
|
|
64
66
|
|
|
65
67
|
const onContentScroll = event => {
|
|
66
|
-
if (isIndicatorDragging.current
|
|
68
|
+
if (!isIndicatorDragging.current) {
|
|
67
69
|
const contentPercentage = (0, _util.offsetToPercentage)(event.nativeEvent.contentOffset.y, totalContentLength);
|
|
68
70
|
const offset = (0, _util.percentageToOffset)(contentPercentage, movementRange);
|
|
69
71
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["styles","StyleSheet","create","indicator","width","height","backgroundColor","flexDirection","alignItems","borderRadius","view","position","FastScroll","React","forwardRef","props","ref","absolutePosition","additionalLength","contentLength","movementRange","scrollContentToOffset","visibleDurations","hideMillis","showMillis","lastIndicatorOffset","useSharedValue","indicatorOffset","value","isIndicatorDragging","useRef","indicatorOpacity","visible","setVisible","useState","animatedStyle","useAnimatedStyle","transform","translateY","opacity","totalContentLength","onContentScroll","event","current","contentPercentage","offsetToPercentage","nativeEvent","contentOffset","y","offset","percentageToOffset","getIsIndicatorDragging","useImperativeHandle","handleUpdate","setIsIndicatorDragging","pan","Gesture","Pan","onBegin","e","runOnJS","onUpdate","translationY","onFinalize","hide","withDelay","withTiming","duration","show","useEffect"],"sources":["FastScroll.tsx"],"sourcesContent":["import React, { useEffect, useImperativeHandle, useRef, useState } from 'react';\nimport { NativeScrollEvent, NativeSyntheticEvent, View } from 'react-native';\nimport { Gesture, GestureDetector } from 'react-native-gesture-handler';\nimport Animated, { runOnJS, useAnimatedStyle, useSharedValue, withDelay, withTiming } from 'react-native-reanimated';\nimport { ChevronDown, ChevronUp } from '@fountain-ui/icons';\nimport { StyleSheet } from '@fountain-ui/core';\nimport FastScrollProps from './FastScrollProps';\nimport { offsetToPercentage, percentageToOffset } from './util';\n\nconst styles = StyleSheet.create({\n indicator: {\n width: 24,\n height: 40,\n backgroundColor: '#767676',\n flexDirection: 'column',\n alignItems: 'center',\n borderRadius: 4,\n },\n view: { position: 'absolute' },\n});\n\nconst FastScroll = React.forwardRef((props: FastScrollProps, ref) => {\n const {\n absolutePosition,\n additionalLength = 0,\n contentLength,\n movementRange,\n scrollContentToOffset,\n visibleDurations = { hideMillis: 200, showMillis: 350 },\n } = props;\n\n const lastIndicatorOffset = useSharedValue(0);\n const indicatorOffset = useSharedValue(lastIndicatorOffset.value);\n\n const isIndicatorDragging = useRef(false);\n\n const indicatorOpacity = useSharedValue(1);\n const [visible, setVisible] = useState(true);\n\n const animatedStyle = useAnimatedStyle(() => ({\n transform: [{ translateY: indicatorOffset.value }],\n opacity: indicatorOpacity.value,\n }));\n\n const totalContentLength = contentLength + additionalLength;\n\n const onContentScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {\n if (isIndicatorDragging.current === false) {\n const contentPercentage = offsetToPercentage(event.nativeEvent.contentOffset.y, totalContentLength);\n const offset = percentageToOffset(contentPercentage, movementRange);\n\n if (offset < 0 || indicatorOffset.value < 0) {\n lastIndicatorOffset.value = 0;\n indicatorOffset.value = 0;\n return;\n }\n\n if (offset > movementRange || indicatorOffset.value > movementRange) {\n lastIndicatorOffset.value = movementRange;\n indicatorOffset.value = movementRange;\n return;\n }\n\n lastIndicatorOffset.value = offset;\n } else {\n setVisible(true);\n }\n };\n\n const getIsIndicatorDragging = () => isIndicatorDragging.current;\n\n useImperativeHandle(\n ref,\n () => ({\n getIsIndicatorDragging,\n onContentScroll,\n setVisible,\n }),\n [],\n );\n\n const handleUpdate = () => {\n const contentPercentage = offsetToPercentage(indicatorOffset.value, movementRange);\n const offset = percentageToOffset(contentPercentage, totalContentLength);\n\n scrollContentToOffset(offset);\n };\n\n const setIsIndicatorDragging = (value: boolean) => isIndicatorDragging.current = value;\n\n const pan = Gesture.Pan()\n .onBegin((e) => {\n indicatorOffset.value = lastIndicatorOffset.value;\n runOnJS(setIsIndicatorDragging)(true);\n })\n .onUpdate((e) => {\n if (indicatorOffset.value <= 0 && e.translationY < 0) {\n indicatorOffset.value = 0;\n return;\n }\n\n if (indicatorOffset.value >= movementRange && e.translationY > 0) {\n indicatorOffset.value = movementRange;\n return;\n }\n\n indicatorOffset.value = lastIndicatorOffset.value + e.translationY;\n\n runOnJS(handleUpdate)();\n })\n .onFinalize((e) => {\n lastIndicatorOffset.value = indicatorOffset.value;\n runOnJS(setIsIndicatorDragging)(false);\n });\n\n const hide = () => indicatorOpacity.value = withDelay(0, withTiming(0, { duration: visibleDurations.hideMillis }));\n\n const show = () => indicatorOpacity.value = withDelay(0, withTiming(1, { duration: visibleDurations.showMillis }));\n\n useEffect(() => {\n if (visible) {\n indicatorOffset.value = lastIndicatorOffset.value;\n show();\n } else {\n hide();\n }\n }, [visible]);\n\n return (\n <View\n style={[\n { height: movementRange },\n styles.view,\n absolutePosition,\n ]}\n >\n <GestureDetector gesture={pan}>\n <Animated.View style={[\n animatedStyle,\n styles.indicator,\n ]}>\n <ChevronUp\n fill={'#ededed'}\n height={20}\n width={20}\n />\n <ChevronDown\n fill={'#ededed'}\n height={20}\n width={20}\n />\n </Animated.View>\n </GestureDetector>\n </View>\n );\n});\n\nexport default FastScroll;"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["styles","StyleSheet","create","indicator","width","height","backgroundColor","flexDirection","alignItems","justifyContent","borderRadius","view","padding","position","FastScroll","React","forwardRef","props","ref","absolutePosition","additionalLength","contentLength","movementRange","scrollContentToOffset","visibleDurations","hideMillis","showMillis","lastIndicatorOffset","useSharedValue","indicatorOffset","value","isIndicatorDragging","useRef","indicatorOpacity","visible","setVisible","useState","animatedStyle","useAnimatedStyle","transform","translateY","opacity","totalContentLength","onContentScroll","event","current","contentPercentage","offsetToPercentage","nativeEvent","contentOffset","y","offset","percentageToOffset","getIsIndicatorDragging","useImperativeHandle","handleUpdate","setIsIndicatorDragging","pan","Gesture","Pan","onBegin","e","runOnJS","onUpdate","translationY","onFinalize","hide","withDelay","withTiming","duration","show","useEffect"],"sources":["FastScroll.tsx"],"sourcesContent":["import React, { useEffect, useImperativeHandle, useRef, useState } from 'react';\nimport { NativeScrollEvent, NativeSyntheticEvent, View } from 'react-native';\nimport { Gesture, GestureDetector } from 'react-native-gesture-handler';\nimport Animated, { runOnJS, useAnimatedStyle, useSharedValue, withDelay, withTiming } from 'react-native-reanimated';\nimport { ChevronDown, ChevronUp } from '@fountain-ui/icons';\nimport { StyleSheet } from '@fountain-ui/core';\nimport FastScrollProps from './FastScrollProps';\nimport { offsetToPercentage, percentageToOffset } from './util';\n\nconst styles = StyleSheet.create({\n indicator: {\n width: 28,\n height: 48,\n backgroundColor: '#767676',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 16,\n },\n view: { padding: 4, position: 'absolute' },\n});\n\nconst FastScroll = React.forwardRef((props: FastScrollProps, ref) => {\n const {\n absolutePosition,\n additionalLength = 0,\n contentLength,\n movementRange,\n scrollContentToOffset,\n visibleDurations = { hideMillis: 200, showMillis: 350 },\n } = props;\n\n const lastIndicatorOffset = useSharedValue(0);\n const indicatorOffset = useSharedValue(lastIndicatorOffset.value);\n\n const isIndicatorDragging = useRef(false);\n\n const indicatorOpacity = useSharedValue(1);\n const [visible, setVisible] = useState(true);\n\n const animatedStyle = useAnimatedStyle(() => ({\n transform: [{ translateY: indicatorOffset.value }],\n opacity: indicatorOpacity.value,\n }));\n\n const totalContentLength = contentLength + additionalLength;\n\n const onContentScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {\n if (!isIndicatorDragging.current) {\n const contentPercentage = offsetToPercentage(event.nativeEvent.contentOffset.y, totalContentLength);\n const offset = percentageToOffset(contentPercentage, movementRange);\n\n if (offset < 0 || indicatorOffset.value < 0) {\n lastIndicatorOffset.value = 0;\n indicatorOffset.value = 0;\n return;\n }\n\n if (offset > movementRange || indicatorOffset.value > movementRange) {\n lastIndicatorOffset.value = movementRange;\n indicatorOffset.value = movementRange;\n return;\n }\n\n lastIndicatorOffset.value = offset;\n } else {\n setVisible(true);\n }\n };\n\n const getIsIndicatorDragging = () => isIndicatorDragging.current;\n\n useImperativeHandle(\n ref,\n () => ({\n getIsIndicatorDragging,\n onContentScroll,\n setVisible,\n }),\n [],\n );\n\n const handleUpdate = () => {\n const contentPercentage = offsetToPercentage(indicatorOffset.value, movementRange);\n const offset = percentageToOffset(contentPercentage, totalContentLength);\n\n scrollContentToOffset(offset);\n };\n\n const setIsIndicatorDragging = (value: boolean) => isIndicatorDragging.current = value;\n\n const pan = Gesture.Pan()\n .onBegin((e) => {\n indicatorOffset.value = lastIndicatorOffset.value;\n runOnJS(setIsIndicatorDragging)(true);\n })\n .onUpdate((e) => {\n if (indicatorOffset.value <= 0 && e.translationY < 0) {\n indicatorOffset.value = 0;\n return;\n }\n\n if (indicatorOffset.value >= movementRange && e.translationY > 0) {\n indicatorOffset.value = movementRange;\n return;\n }\n\n indicatorOffset.value = lastIndicatorOffset.value + e.translationY;\n\n runOnJS(handleUpdate)();\n })\n .onFinalize((e) => {\n lastIndicatorOffset.value = indicatorOffset.value;\n runOnJS(setIsIndicatorDragging)(false);\n });\n\n const hide = () => indicatorOpacity.value = withDelay(0, withTiming(0, { duration: visibleDurations.hideMillis }));\n\n const show = () => indicatorOpacity.value = withDelay(0, withTiming(1, { duration: visibleDurations.showMillis }));\n\n useEffect(() => {\n if (visible) {\n indicatorOffset.value = lastIndicatorOffset.value;\n show();\n } else {\n hide();\n }\n }, [visible]);\n\n return (\n <View\n style={[\n { height: movementRange },\n styles.view,\n absolutePosition,\n ]}\n >\n <GestureDetector gesture={pan}>\n <Animated.View style={[\n animatedStyle,\n styles.indicator,\n ]}>\n <ChevronUp\n fill={'#ededed'}\n height={20}\n width={20}\n />\n <ChevronDown\n fill={'#ededed'}\n height={20}\n width={20}\n />\n </Animated.View>\n </GestureDetector>\n </View>\n );\n});\n\nexport default FastScroll;"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
2
2
|
|
|
3
3
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
|
-
import { FlatList } from 'react-native';
|
|
4
|
+
import { FlatList, Platform } from 'react-native';
|
|
5
5
|
import * as R from 'ramda';
|
|
6
6
|
import ViewerItem from './ViewerItem';
|
|
7
7
|
import FastScroll from './FastScroll';
|
|
@@ -36,7 +36,6 @@ const mapImageStateToItemState = (index, imageState, autoHandleErrorCount) => {
|
|
|
36
36
|
|
|
37
37
|
const mapIndexed = R.addIndex(R.map);
|
|
38
38
|
const MAXIMUM_WIDTH = 720;
|
|
39
|
-
const NUMBER_OF_ADJACENT_ITEM = 5;
|
|
40
39
|
export default function ComicViewer(props) {
|
|
41
40
|
const {
|
|
42
41
|
debounceMillis = 100,
|
|
@@ -58,7 +57,6 @@ export default function ComicViewer(props) {
|
|
|
58
57
|
} = props;
|
|
59
58
|
const fastScrollRef = fastScrollOptions === null || fastScrollOptions === void 0 ? void 0 : fastScrollOptions.ref;
|
|
60
59
|
const flatListRef = useRef(null);
|
|
61
|
-
const maybeLoadableItemsIndexRange = useRef([-1, 0]);
|
|
62
60
|
const actualImageWidth = Math.min(viewportWidth, maxContentWidth);
|
|
63
61
|
const initialImageStates = useMemo(() => R.map(createInitialImageState, intrinsicImages), []);
|
|
64
62
|
const imageStatesRef = useRef(initialImageStates);
|
|
@@ -113,13 +111,12 @@ export default function ComicViewer(props) {
|
|
|
113
111
|
});
|
|
114
112
|
};
|
|
115
113
|
|
|
116
|
-
const
|
|
114
|
+
const updateTryRenderingMillis = () => {
|
|
117
115
|
const tryRenderingMillis = new Date().getTime();
|
|
118
116
|
updateImageState((imageState, i) => {
|
|
119
117
|
const urlState = imageState.urlState;
|
|
120
|
-
const shouldRerender = R.includes(i, R.defaultTo([], indexes));
|
|
121
118
|
|
|
122
|
-
if (
|
|
119
|
+
if ((urlState === null || urlState === void 0 ? void 0 : urlState.validity) === 'invalid') {
|
|
123
120
|
return { ...imageState,
|
|
124
121
|
tryRenderingMillis
|
|
125
122
|
};
|
|
@@ -129,30 +126,11 @@ export default function ComicViewer(props) {
|
|
|
129
126
|
});
|
|
130
127
|
};
|
|
131
128
|
|
|
132
|
-
const renderMaybeLoadableItems = () => {
|
|
133
|
-
const [startIndex, endIndex] = maybeLoadableItemsIndexRange.current;
|
|
134
|
-
const affectedIndexes = R.range(startIndex, endIndex);
|
|
135
|
-
updateItems(affectedIndexes);
|
|
136
|
-
};
|
|
137
|
-
|
|
138
129
|
const onViewableItemsChanged = useRef(_ref => {
|
|
139
|
-
var _R$head, _R$last;
|
|
140
|
-
|
|
141
130
|
let {
|
|
142
131
|
viewableItems
|
|
143
132
|
} = _ref;
|
|
144
|
-
|
|
145
|
-
const firstViewableIndex = (_R$head = R.head(orderedViewableItems)) === null || _R$head === void 0 ? void 0 : _R$head.index;
|
|
146
|
-
const lastViewableItemIndex = (_R$last = R.last(orderedViewableItems)) === null || _R$last === void 0 ? void 0 : _R$last.index;
|
|
147
|
-
|
|
148
|
-
if (R.isNil(firstViewableIndex) || R.isNil(lastViewableItemIndex)) {
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const startIndex = R.max(firstViewableIndex - NUMBER_OF_ADJACENT_ITEM, 0);
|
|
153
|
-
const endIndex = R.min(lastViewableItemIndex + NUMBER_OF_ADJACENT_ITEM, itemStates.length - 1);
|
|
154
|
-
maybeLoadableItemsIndexRange.current = [startIndex, endIndex + 1];
|
|
155
|
-
renderMaybeLoadableItems();
|
|
133
|
+
updateTryRenderingMillis();
|
|
156
134
|
});
|
|
157
135
|
const handleScroll = useCallback(event => {
|
|
158
136
|
var _fastScrollRef$curren;
|
|
@@ -199,16 +177,12 @@ export default function ComicViewer(props) {
|
|
|
199
177
|
return;
|
|
200
178
|
}
|
|
201
179
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if (index >= startIndex || index < endIndex) {
|
|
205
|
-
renderMaybeLoadableItems();
|
|
206
|
-
}
|
|
180
|
+
updateTryRenderingMillis();
|
|
207
181
|
};
|
|
208
182
|
|
|
209
183
|
const handleReloadPress = () => {
|
|
210
184
|
onReloadPress && onReloadPress();
|
|
211
|
-
|
|
185
|
+
updateTryRenderingMillis();
|
|
212
186
|
};
|
|
213
187
|
|
|
214
188
|
const onLoad = () => {
|
|
@@ -241,14 +215,33 @@ export default function ComicViewer(props) {
|
|
|
241
215
|
});
|
|
242
216
|
}, [onItemPress, renderedDimensions]);
|
|
243
217
|
useEffect(() => {
|
|
244
|
-
const
|
|
218
|
+
const scroll = () => {
|
|
219
|
+
const offset = Math.floor(initialScrollPercentage / 100 * totalHeight);
|
|
220
|
+
|
|
221
|
+
if (flatListRef.current) {
|
|
222
|
+
flatListRef.current.scrollToOffset({
|
|
223
|
+
offset,
|
|
224
|
+
animated: false
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
};
|
|
245
228
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
229
|
+
let timeoutId = undefined;
|
|
230
|
+
/**
|
|
231
|
+
* @FIXME
|
|
232
|
+
* scrollToOffset has issue(no effect) in useEffect hook on iOS.
|
|
233
|
+
* ref: https://github.com/facebook/react-native/issues/35575
|
|
234
|
+
*/
|
|
235
|
+
|
|
236
|
+
if (Platform.OS === 'ios') {
|
|
237
|
+
timeoutId = setTimeout(scroll, 0);
|
|
238
|
+
} else {
|
|
239
|
+
scroll();
|
|
251
240
|
}
|
|
241
|
+
|
|
242
|
+
return () => {
|
|
243
|
+
timeoutId && clearTimeout(timeoutId);
|
|
244
|
+
};
|
|
252
245
|
}, []);
|
|
253
246
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(FlatList, _extends({
|
|
254
247
|
data: itemStates,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useCallback","useEffect","useMemo","useRef","useState","FlatList","R","ViewerItem","FastScroll","appender","left","right","getHeightAccum","heights","mapAccum","keyExtractor","item","String","index","createInitialImageState","image","totalErrorCount","dimension","tryRenderingMillis","urlState","url","validity","mapImageStateToItemState","imageState","autoHandleErrorCount","imageKey","reloadButtonVisible","mapIndexed","addIndex","map","MAXIMUM_WIDTH","NUMBER_OF_ADJACENT_ITEM","ComicViewer","props","debounceMillis","fastScrollOptions","initialNumToRender","initialScrollPercentage","itemVisiblePercentThreshold","intrinsicImages","maxContentWidth","onItemPress","onScroll","onError","onReloadPress","viewportWidth","invisiblePaddingTop","windowSize","otherProps","fastScrollRef","ref","flatListRef","maybeLoadableItemsIndexRange","actualImageWidth","Math","min","initialImageStates","imageStatesRef","mapImageStatesToItemStates","imageStates","itemStates","setItemStates","current","renderedDimensions","intrinsicImage","height","width","isNaN","layoutFromDimensions","itemHeights","totalHeight","heightAccum","itemOffsets","prepend","getItemLayout","data","length","offset","viewabilityConfig","updateImageState","updateFunction","prevImageStates","newImageStates","prevItemStates","newItemStates","equals","updateItems","indexes","Date","getTime","i","shouldRerender","includes","defaultTo","renderMaybeLoadableItems","startIndex","endIndex","affectedIndexes","range","onViewableItemsChanged","viewableItems","orderedViewableItems","sort","a","b","firstViewableIndex","head","lastViewableItemIndex","last","isNil","max","handleScroll","event","onContentScroll","scrollContentToOffset","scrollToOffset","animated","renderItem","handleError","handleReloadPress","onLoad","undefined","floor"],"sources":["ComicViewer.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { FlatList, ListRenderItem, NativeScrollEvent, NativeSyntheticEvent, ViewToken } from 'react-native';\nimport * as R from 'ramda';\nimport { default as ComicViewerProps, Dimension, IntrinsicImage } from './ComicViewerProps';\nimport ViewerItem from './ViewerItem';\nimport FastScroll from './FastScroll';\n\nconst appender = (left: number, right: number): [number, number] => [left + right, left + right];\nconst getHeightAccum = (heights: number[]): [number, number[]] => R.mapAccum(appender, 0, heights);\n\nconst keyExtractor = <T, >(item: ItemState) => String(item.index);\n\ninterface UrlState {\n url: string;\n validity: 'valid' | 'invalid' | 'unknown';\n}\n\ninterface ImageState {\n urlState: UrlState;\n totalErrorCount: number;\n dimension: Dimension;\n tryRenderingMillis: number;\n}\n\ninterface ItemState {\n index: number;\n url?: string;\n imageKey: string;\n reloadButtonVisible: boolean;\n dimension: Dimension;\n}\n\nconst createInitialImageState = (image: IntrinsicImage): ImageState => ({\n totalErrorCount: 0,\n dimension: image.dimension,\n tryRenderingMillis: 0,\n urlState: {\n url: image.url,\n validity: 'unknown',\n },\n});\n\nconst mapImageStateToItemState = (\n index: number,\n imageState: ImageState,\n autoHandleErrorCount: number,\n): ItemState => ({\n index,\n url: imageState.urlState?.url,\n imageKey: `${imageState.tryRenderingMillis}-${index}`,\n reloadButtonVisible: (imageState.urlState?.validity !== 'valid') && imageState.totalErrorCount >= autoHandleErrorCount,\n dimension: imageState.dimension,\n});\n\nconst mapIndexed = R.addIndex<IntrinsicImage>(R.map);\n\nconst MAXIMUM_WIDTH = 720;\n\nconst NUMBER_OF_ADJACENT_ITEM = 5;\n\nexport default function ComicViewer(props: ComicViewerProps) {\n const {\n debounceMillis = 100,\n autoHandleErrorCount = 3,\n fastScrollOptions,\n initialNumToRender = 1,\n initialScrollPercentage = 0,\n itemVisiblePercentThreshold = 0,\n intrinsicImages,\n maxContentWidth = MAXIMUM_WIDTH,\n onItemPress,\n onScroll,\n onError,\n onReloadPress,\n viewportWidth,\n invisiblePaddingTop = 0,\n windowSize = 3,\n ...otherProps\n } = props;\n\n const fastScrollRef = fastScrollOptions?.ref;\n\n const flatListRef = useRef<FlatList>(null);\n\n const maybeLoadableItemsIndexRange = useRef<[number, number]>([-1, 0]);\n\n const actualImageWidth = Math.min(viewportWidth, maxContentWidth);\n\n const initialImageStates = useMemo<Array<ImageState>>(() => R.map(createInitialImageState, intrinsicImages), []);\n\n const imageStatesRef = useRef<Array<ImageState>>(initialImageStates);\n\n const mapImageStatesToItemStates = (imageStates: Array<ImageState>): Array<ItemState> => {\n return imageStates.map((image, index) => mapImageStateToItemState(\n index, image, autoHandleErrorCount,\n ));\n };\n\n const [itemStates, setItemStates] = useState<Array<ItemState>>(() => {\n return mapImageStatesToItemStates(imageStatesRef.current);\n });\n\n const renderedDimensions = useMemo<Array<Dimension>>(() => {\n return mapIndexed((intrinsicImage, index) => {\n const height = (intrinsicImage.dimension.height * actualImageWidth) / intrinsicImage.dimension.width + (index === 0 ? invisiblePaddingTop : 0);\n\n return {\n width: actualImageWidth,\n height: isNaN(height) ? 0 : height,\n };\n }, intrinsicImages);\n }, [actualImageWidth]);\n\n const layoutFromDimensions = useCallback(() => {\n const itemHeights = R.map(dimension => dimension.height, renderedDimensions);\n const [totalHeight, heightAccum] = getHeightAccum(itemHeights);\n const itemOffsets = R.prepend(0, heightAccum);\n\n const getItemLayout = (data: any, index: number) => ({\n index,\n length: itemHeights[index],\n offset: itemOffsets[index],\n });\n\n return {\n totalHeight,\n getItemLayout,\n };\n }, [renderedDimensions]);\n\n const { totalHeight, getItemLayout } = layoutFromDimensions();\n\n const viewabilityConfig = useMemo(() => ({\n itemVisiblePercentThreshold,\n }), [itemVisiblePercentThreshold]);\n\n const updateImageState = (updateFunction: (prev: ImageState, index: number) => ImageState) => {\n const prevImageStates = imageStatesRef.current;\n const newImageStates = prevImageStates.map(updateFunction);\n\n imageStatesRef.current = newImageStates;\n\n setItemStates(prevItemStates => {\n const newItemStates = mapImageStatesToItemStates(newImageStates);\n\n return R.equals(prevItemStates, newItemStates) ? prevItemStates : newItemStates;\n });\n };\n\n const updateItems = (indexes: number[]) => {\n const tryRenderingMillis = new Date().getTime();\n\n updateImageState((imageState, i) => {\n const urlState = imageState.urlState;\n const shouldRerender = R.includes(i, R.defaultTo([], indexes));\n\n if (shouldRerender && urlState?.validity !== 'valid') {\n return {\n ...imageState,\n tryRenderingMillis,\n };\n }\n\n return imageState;\n });\n };\n\n const renderMaybeLoadableItems = () => {\n const [startIndex, endIndex] = maybeLoadableItemsIndexRange.current;\n const affectedIndexes = R.range(startIndex, endIndex);\n\n updateItems(affectedIndexes);\n };\n\n const onViewableItemsChanged = useRef(({ viewableItems }: { viewableItems: Array<ViewToken> }) => {\n const orderedViewableItems = R.sort((a, b) => (a.index || 0) - (b.index || 0), viewableItems);\n\n const firstViewableIndex = R.head(orderedViewableItems)?.index;\n const lastViewableItemIndex = R.last(orderedViewableItems)?.index;\n\n if (R.isNil(firstViewableIndex) || R.isNil(lastViewableItemIndex)) {\n return;\n }\n\n const startIndex = R.max(firstViewableIndex - NUMBER_OF_ADJACENT_ITEM, 0);\n const endIndex = R.min(lastViewableItemIndex + NUMBER_OF_ADJACENT_ITEM, itemStates.length - 1);\n\n maybeLoadableItemsIndexRange.current = [startIndex, endIndex + 1];\n\n renderMaybeLoadableItems();\n });\n\n const handleScroll = useCallback((event: NativeSyntheticEvent<NativeScrollEvent>) => {\n fastScrollRef?.current?.onContentScroll(event);\n\n onScroll?.(event);\n }, [onScroll]);\n\n const scrollContentToOffset = (offset: number) => {\n flatListRef.current?.scrollToOffset({\n offset,\n animated: false,\n });\n };\n\n const renderItem: ListRenderItem<ItemState> = useCallback(({ item, index }) => {\n const handleError = () => {\n onError && onError();\n\n updateImageState((imageState, i) => {\n const urlState = imageState.urlState;\n\n if (i === index) {\n return {\n ...imageState,\n totalErrorCount: imageState.totalErrorCount + 1,\n urlState: {\n ...urlState,\n validity: 'invalid',\n },\n };\n }\n\n return imageState;\n });\n\n if (item.reloadButtonVisible) {\n return;\n }\n\n const [startIndex, endIndex] = maybeLoadableItemsIndexRange.current;\n if (index >= startIndex || index < endIndex) {\n renderMaybeLoadableItems();\n }\n };\n\n const handleReloadPress = () => {\n onReloadPress && onReloadPress();\n\n updateItems([index]);\n };\n\n const onLoad = () => {\n updateImageState((imageState, i) => {\n const urlState = imageState.urlState;\n\n if (i === index && urlState !== undefined) {\n return {\n ...imageState,\n urlState: {\n ...urlState,\n validity: 'valid',\n },\n };\n }\n\n return imageState;\n });\n };\n\n return (\n <ViewerItem\n onError={handleError}\n onLoad={onLoad}\n onPress={onItemPress}\n onReloadPress={handleReloadPress}\n url={item.url}\n imageKey={item.imageKey}\n invisiblePaddingTop={index === 0 ? invisiblePaddingTop : 0}\n width={renderedDimensions[index]?.width ?? 0}\n height={renderedDimensions[index]?.height ?? 0}\n reloadButtonVisible={item.reloadButtonVisible}\n />\n );\n }, [onItemPress, renderedDimensions]);\n\n useEffect(() => {\n const offset = Math.floor((initialScrollPercentage / 100) * totalHeight);\n\n if (flatListRef.current) {\n flatListRef.current.scrollToOffset({ offset, animated: false });\n }\n }, []);\n\n return (\n <React.Fragment>\n <FlatList\n data={itemStates}\n getItemLayout={getItemLayout}\n initialNumToRender={initialNumToRender}\n keyExtractor={keyExtractor}\n onViewableItemsChanged={onViewableItemsChanged.current}\n ref={flatListRef}\n renderItem={renderItem}\n viewabilityConfig={viewabilityConfig}\n windowSize={windowSize}\n onScroll={handleScroll}\n {...otherProps}\n />\n\n <FastScroll\n {...fastScrollOptions}\n contentLength={totalHeight}\n scrollContentToOffset={scrollContentToOffset}\n />\n </React.Fragment>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["React","useCallback","useEffect","useMemo","useRef","useState","FlatList","Platform","R","ViewerItem","FastScroll","appender","left","right","getHeightAccum","heights","mapAccum","keyExtractor","item","String","index","createInitialImageState","image","totalErrorCount","dimension","tryRenderingMillis","urlState","url","validity","mapImageStateToItemState","imageState","autoHandleErrorCount","imageKey","reloadButtonVisible","mapIndexed","addIndex","map","MAXIMUM_WIDTH","ComicViewer","props","debounceMillis","fastScrollOptions","initialNumToRender","initialScrollPercentage","itemVisiblePercentThreshold","intrinsicImages","maxContentWidth","onItemPress","onScroll","onError","onReloadPress","viewportWidth","invisiblePaddingTop","windowSize","otherProps","fastScrollRef","ref","flatListRef","actualImageWidth","Math","min","initialImageStates","imageStatesRef","mapImageStatesToItemStates","imageStates","itemStates","setItemStates","current","renderedDimensions","intrinsicImage","height","width","isNaN","layoutFromDimensions","itemHeights","totalHeight","heightAccum","itemOffsets","prepend","getItemLayout","data","length","offset","viewabilityConfig","updateImageState","updateFunction","prevImageStates","newImageStates","prevItemStates","newItemStates","equals","updateTryRenderingMillis","Date","getTime","i","onViewableItemsChanged","viewableItems","handleScroll","event","onContentScroll","scrollContentToOffset","scrollToOffset","animated","renderItem","handleError","handleReloadPress","onLoad","undefined","scroll","floor","timeoutId","OS","setTimeout","clearTimeout"],"sources":["ComicViewer.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { FlatList, ListRenderItem, NativeScrollEvent, NativeSyntheticEvent, Platform, ViewToken } from 'react-native';\nimport * as R from 'ramda';\nimport { default as ComicViewerProps, Dimension, IntrinsicImage } from './ComicViewerProps';\nimport ViewerItem from './ViewerItem';\nimport FastScroll from './FastScroll';\n\nconst appender = (left: number, right: number): [number, number] => [left + right, left + right];\nconst getHeightAccum = (heights: number[]): [number, number[]] => R.mapAccum(appender, 0, heights);\n\nconst keyExtractor = <T, >(item: ItemState) => String(item.index);\n\ninterface UrlState {\n url: string;\n validity: 'valid' | 'invalid' | 'unknown';\n}\n\ninterface ImageState {\n urlState: UrlState;\n totalErrorCount: number;\n dimension: Dimension;\n tryRenderingMillis: number;\n}\n\ninterface ItemState {\n index: number;\n url?: string;\n imageKey: string;\n reloadButtonVisible: boolean;\n dimension: Dimension;\n}\n\nconst createInitialImageState = (image: IntrinsicImage): ImageState => ({\n totalErrorCount: 0,\n dimension: image.dimension,\n tryRenderingMillis: 0,\n urlState: {\n url: image.url,\n validity: 'unknown',\n },\n});\n\nconst mapImageStateToItemState = (\n index: number,\n imageState: ImageState,\n autoHandleErrorCount: number,\n): ItemState => ({\n index,\n url: imageState.urlState?.url,\n imageKey: `${imageState.tryRenderingMillis}-${index}`,\n reloadButtonVisible: (imageState.urlState?.validity !== 'valid') && imageState.totalErrorCount >= autoHandleErrorCount,\n dimension: imageState.dimension,\n});\n\nconst mapIndexed = R.addIndex<IntrinsicImage>(R.map);\n\nconst MAXIMUM_WIDTH = 720;\n\nexport default function ComicViewer(props: ComicViewerProps) {\n const {\n debounceMillis = 100,\n autoHandleErrorCount = 3,\n fastScrollOptions,\n initialNumToRender = 1,\n initialScrollPercentage = 0,\n itemVisiblePercentThreshold = 0,\n intrinsicImages,\n maxContentWidth = MAXIMUM_WIDTH,\n onItemPress,\n onScroll,\n onError,\n onReloadPress,\n viewportWidth,\n invisiblePaddingTop = 0,\n windowSize = 3,\n ...otherProps\n } = props;\n\n const fastScrollRef = fastScrollOptions?.ref;\n\n const flatListRef = useRef<FlatList>(null);\n\n const actualImageWidth = Math.min(viewportWidth, maxContentWidth);\n\n const initialImageStates = useMemo<Array<ImageState>>(() => R.map(createInitialImageState, intrinsicImages), []);\n\n const imageStatesRef = useRef<Array<ImageState>>(initialImageStates);\n\n const mapImageStatesToItemStates = (imageStates: Array<ImageState>): Array<ItemState> => {\n return imageStates.map((image, index) => mapImageStateToItemState(\n index, image, autoHandleErrorCount,\n ));\n };\n\n const [itemStates, setItemStates] = useState<Array<ItemState>>(() => {\n return mapImageStatesToItemStates(imageStatesRef.current);\n });\n\n const renderedDimensions = useMemo<Array<Dimension>>(() => {\n return mapIndexed((intrinsicImage, index) => {\n const height = (intrinsicImage.dimension.height * actualImageWidth) / intrinsicImage.dimension.width + (index === 0 ? invisiblePaddingTop : 0);\n\n return {\n width: actualImageWidth,\n height: isNaN(height) ? 0 : height,\n };\n }, intrinsicImages);\n }, [actualImageWidth]);\n\n const layoutFromDimensions = useCallback(() => {\n const itemHeights = R.map(dimension => dimension.height, renderedDimensions);\n const [totalHeight, heightAccum] = getHeightAccum(itemHeights);\n const itemOffsets = R.prepend(0, heightAccum);\n\n const getItemLayout = (data: any, index: number) => ({\n index,\n length: itemHeights[index],\n offset: itemOffsets[index],\n });\n\n return {\n totalHeight,\n getItemLayout,\n };\n }, [renderedDimensions]);\n\n const { totalHeight, getItemLayout } = layoutFromDimensions();\n\n const viewabilityConfig = useMemo(() => ({\n itemVisiblePercentThreshold,\n }), [itemVisiblePercentThreshold]);\n\n const updateImageState = (updateFunction: (prev: ImageState, index: number) => ImageState) => {\n const prevImageStates = imageStatesRef.current;\n const newImageStates = prevImageStates.map(updateFunction);\n\n imageStatesRef.current = newImageStates;\n\n setItemStates(prevItemStates => {\n const newItemStates = mapImageStatesToItemStates(newImageStates);\n\n return R.equals(prevItemStates, newItemStates) ? prevItemStates : newItemStates;\n });\n };\n\n const updateTryRenderingMillis = () => {\n const tryRenderingMillis = new Date().getTime();\n\n updateImageState((imageState, i) => {\n const urlState = imageState.urlState;\n\n if (urlState?.validity === 'invalid') {\n return {\n ...imageState,\n tryRenderingMillis,\n };\n }\n\n return imageState;\n });\n };\n const onViewableItemsChanged = useRef(({ viewableItems }: { viewableItems: Array<ViewToken> }) => {\n updateTryRenderingMillis();\n });\n\n const handleScroll = useCallback((event: NativeSyntheticEvent<NativeScrollEvent>) => {\n fastScrollRef?.current?.onContentScroll(event);\n\n onScroll?.(event);\n }, [onScroll]);\n\n const scrollContentToOffset = (offset: number) => {\n flatListRef.current?.scrollToOffset({\n offset,\n animated: false,\n });\n };\n\n const renderItem: ListRenderItem<ItemState> = useCallback(({ item, index }) => {\n const handleError = () => {\n onError && onError();\n\n updateImageState((imageState, i) => {\n const urlState = imageState.urlState;\n\n if (i === index) {\n return {\n ...imageState,\n totalErrorCount: imageState.totalErrorCount + 1,\n urlState: {\n ...urlState,\n validity: 'invalid',\n },\n };\n }\n\n return imageState;\n });\n\n if (item.reloadButtonVisible) {\n return;\n }\n\n updateTryRenderingMillis();\n };\n\n const handleReloadPress = () => {\n onReloadPress && onReloadPress();\n\n updateTryRenderingMillis();\n };\n\n const onLoad = () => {\n updateImageState((imageState, i) => {\n const urlState = imageState.urlState;\n\n if (i === index && urlState !== undefined) {\n return {\n ...imageState,\n urlState: {\n ...urlState,\n validity: 'valid',\n },\n };\n }\n\n return imageState;\n });\n };\n\n return (\n <ViewerItem\n onError={handleError}\n onLoad={onLoad}\n onPress={onItemPress}\n onReloadPress={handleReloadPress}\n url={item.url}\n imageKey={item.imageKey}\n invisiblePaddingTop={index === 0 ? invisiblePaddingTop : 0}\n width={renderedDimensions[index]?.width ?? 0}\n height={renderedDimensions[index]?.height ?? 0}\n reloadButtonVisible={item.reloadButtonVisible}\n />\n );\n }, [onItemPress, renderedDimensions]);\n\n useEffect(() => {\n const scroll = () => {\n const offset = Math.floor((initialScrollPercentage / 100) * totalHeight);\n\n if (flatListRef.current) {\n flatListRef.current.scrollToOffset({ offset, animated: false });\n }\n };\n\n let timeoutId: NodeJS.Timeout | undefined = undefined;\n\n /**\n * @FIXME\n * scrollToOffset has issue(no effect) in useEffect hook on iOS.\n * ref: https://github.com/facebook/react-native/issues/35575\n */\n if (Platform.OS === 'ios') {\n timeoutId = setTimeout(scroll, 0);\n } else {\n scroll();\n }\n\n return () => {\n timeoutId && clearTimeout(timeoutId);\n }\n }, []);\n\n return (\n <React.Fragment>\n <FlatList\n data={itemStates}\n getItemLayout={getItemLayout}\n initialNumToRender={initialNumToRender}\n keyExtractor={keyExtractor}\n onViewableItemsChanged={onViewableItemsChanged.current}\n ref={flatListRef}\n renderItem={renderItem}\n viewabilityConfig={viewabilityConfig}\n windowSize={windowSize}\n onScroll={handleScroll}\n {...otherProps}\n />\n\n <FastScroll\n {...fastScrollOptions}\n contentLength={totalHeight}\n scrollContentToOffset={scrollContentToOffset}\n />\n </React.Fragment>\n );\n};\n"],"mappings":"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"}
|
|
@@ -7,14 +7,16 @@ import { StyleSheet } from '@fountain-ui/core';
|
|
|
7
7
|
import { offsetToPercentage, percentageToOffset } from './util';
|
|
8
8
|
const styles = StyleSheet.create({
|
|
9
9
|
indicator: {
|
|
10
|
-
width:
|
|
11
|
-
height:
|
|
10
|
+
width: 28,
|
|
11
|
+
height: 48,
|
|
12
12
|
backgroundColor: '#767676',
|
|
13
13
|
flexDirection: 'column',
|
|
14
14
|
alignItems: 'center',
|
|
15
|
-
|
|
15
|
+
justifyContent: 'center',
|
|
16
|
+
borderRadius: 16
|
|
16
17
|
},
|
|
17
18
|
view: {
|
|
19
|
+
padding: 4,
|
|
18
20
|
position: 'absolute'
|
|
19
21
|
}
|
|
20
22
|
});
|
|
@@ -44,7 +46,7 @@ const FastScroll = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
44
46
|
const totalContentLength = contentLength + additionalLength;
|
|
45
47
|
|
|
46
48
|
const onContentScroll = event => {
|
|
47
|
-
if (isIndicatorDragging.current
|
|
49
|
+
if (!isIndicatorDragging.current) {
|
|
48
50
|
const contentPercentage = offsetToPercentage(event.nativeEvent.contentOffset.y, totalContentLength);
|
|
49
51
|
const offset = percentageToOffset(contentPercentage, movementRange);
|
|
50
52
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useEffect","useImperativeHandle","useRef","useState","View","Gesture","GestureDetector","Animated","runOnJS","useAnimatedStyle","useSharedValue","withDelay","withTiming","ChevronDown","ChevronUp","StyleSheet","offsetToPercentage","percentageToOffset","styles","create","indicator","width","height","backgroundColor","flexDirection","alignItems","borderRadius","view","position","FastScroll","forwardRef","props","ref","absolutePosition","additionalLength","contentLength","movementRange","scrollContentToOffset","visibleDurations","hideMillis","showMillis","lastIndicatorOffset","indicatorOffset","value","isIndicatorDragging","indicatorOpacity","visible","setVisible","animatedStyle","transform","translateY","opacity","totalContentLength","onContentScroll","event","current","contentPercentage","nativeEvent","contentOffset","y","offset","getIsIndicatorDragging","handleUpdate","setIsIndicatorDragging","pan","Pan","onBegin","e","onUpdate","translationY","onFinalize","hide","duration","show"],"sources":["FastScroll.tsx"],"sourcesContent":["import React, { useEffect, useImperativeHandle, useRef, useState } from 'react';\nimport { NativeScrollEvent, NativeSyntheticEvent, View } from 'react-native';\nimport { Gesture, GestureDetector } from 'react-native-gesture-handler';\nimport Animated, { runOnJS, useAnimatedStyle, useSharedValue, withDelay, withTiming } from 'react-native-reanimated';\nimport { ChevronDown, ChevronUp } from '@fountain-ui/icons';\nimport { StyleSheet } from '@fountain-ui/core';\nimport FastScrollProps from './FastScrollProps';\nimport { offsetToPercentage, percentageToOffset } from './util';\n\nconst styles = StyleSheet.create({\n indicator: {\n width: 24,\n height: 40,\n backgroundColor: '#767676',\n flexDirection: 'column',\n alignItems: 'center',\n borderRadius: 4,\n },\n view: { position: 'absolute' },\n});\n\nconst FastScroll = React.forwardRef((props: FastScrollProps, ref) => {\n const {\n absolutePosition,\n additionalLength = 0,\n contentLength,\n movementRange,\n scrollContentToOffset,\n visibleDurations = { hideMillis: 200, showMillis: 350 },\n } = props;\n\n const lastIndicatorOffset = useSharedValue(0);\n const indicatorOffset = useSharedValue(lastIndicatorOffset.value);\n\n const isIndicatorDragging = useRef(false);\n\n const indicatorOpacity = useSharedValue(1);\n const [visible, setVisible] = useState(true);\n\n const animatedStyle = useAnimatedStyle(() => ({\n transform: [{ translateY: indicatorOffset.value }],\n opacity: indicatorOpacity.value,\n }));\n\n const totalContentLength = contentLength + additionalLength;\n\n const onContentScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {\n if (isIndicatorDragging.current === false) {\n const contentPercentage = offsetToPercentage(event.nativeEvent.contentOffset.y, totalContentLength);\n const offset = percentageToOffset(contentPercentage, movementRange);\n\n if (offset < 0 || indicatorOffset.value < 0) {\n lastIndicatorOffset.value = 0;\n indicatorOffset.value = 0;\n return;\n }\n\n if (offset > movementRange || indicatorOffset.value > movementRange) {\n lastIndicatorOffset.value = movementRange;\n indicatorOffset.value = movementRange;\n return;\n }\n\n lastIndicatorOffset.value = offset;\n } else {\n setVisible(true);\n }\n };\n\n const getIsIndicatorDragging = () => isIndicatorDragging.current;\n\n useImperativeHandle(\n ref,\n () => ({\n getIsIndicatorDragging,\n onContentScroll,\n setVisible,\n }),\n [],\n );\n\n const handleUpdate = () => {\n const contentPercentage = offsetToPercentage(indicatorOffset.value, movementRange);\n const offset = percentageToOffset(contentPercentage, totalContentLength);\n\n scrollContentToOffset(offset);\n };\n\n const setIsIndicatorDragging = (value: boolean) => isIndicatorDragging.current = value;\n\n const pan = Gesture.Pan()\n .onBegin((e) => {\n indicatorOffset.value = lastIndicatorOffset.value;\n runOnJS(setIsIndicatorDragging)(true);\n })\n .onUpdate((e) => {\n if (indicatorOffset.value <= 0 && e.translationY < 0) {\n indicatorOffset.value = 0;\n return;\n }\n\n if (indicatorOffset.value >= movementRange && e.translationY > 0) {\n indicatorOffset.value = movementRange;\n return;\n }\n\n indicatorOffset.value = lastIndicatorOffset.value + e.translationY;\n\n runOnJS(handleUpdate)();\n })\n .onFinalize((e) => {\n lastIndicatorOffset.value = indicatorOffset.value;\n runOnJS(setIsIndicatorDragging)(false);\n });\n\n const hide = () => indicatorOpacity.value = withDelay(0, withTiming(0, { duration: visibleDurations.hideMillis }));\n\n const show = () => indicatorOpacity.value = withDelay(0, withTiming(1, { duration: visibleDurations.showMillis }));\n\n useEffect(() => {\n if (visible) {\n indicatorOffset.value = lastIndicatorOffset.value;\n show();\n } else {\n hide();\n }\n }, [visible]);\n\n return (\n <View\n style={[\n { height: movementRange },\n styles.view,\n absolutePosition,\n ]}\n >\n <GestureDetector gesture={pan}>\n <Animated.View style={[\n animatedStyle,\n styles.indicator,\n ]}>\n <ChevronUp\n fill={'#ededed'}\n height={20}\n width={20}\n />\n <ChevronDown\n fill={'#ededed'}\n height={20}\n width={20}\n />\n </Animated.View>\n </GestureDetector>\n </View>\n );\n});\n\nexport default FastScroll;"],"mappings":"AAAA,OAAOA,KAAP,IAAgBC,SAAhB,EAA2BC,mBAA3B,EAAgDC,MAAhD,EAAwDC,QAAxD,QAAwE,OAAxE;AACA,SAAkDC,IAAlD,QAA8D,cAA9D;AACA,SAASC,OAAT,EAAkBC,eAAlB,QAAyC,8BAAzC;AACA,OAAOC,QAAP,IAAmBC,OAAnB,EAA4BC,gBAA5B,EAA8CC,cAA9C,EAA8DC,SAA9D,EAAyEC,UAAzE,QAA2F,yBAA3F;AACA,SAASC,WAAT,EAAsBC,SAAtB,QAAuC,oBAAvC;AACA,SAASC,UAAT,QAA2B,mBAA3B;AAEA,SAASC,kBAAT,EAA6BC,kBAA7B,QAAuD,QAAvD;AAEA,MAAMC,MAAM,GAAGH,UAAU,CAACI,MAAX,CAAkB;EAC7BC,SAAS,EAAE;IACPC,KAAK,EAAE,EADA;IAEPC,MAAM,EAAE,EAFD;IAGPC,eAAe,EAAE,SAHV;IAIPC,aAAa,EAAE,QAJR;IAKPC,UAAU,EAAE,QALL;IAMPC,YAAY,EAAE;EANP,CADkB;EAS7BC,IAAI,EAAE;IAAEC,QAAQ,EAAE;EAAZ;AATuB,CAAlB,CAAf;AAYA,MAAMC,UAAU,gBAAG9B,KAAK,CAAC+B,UAAN,CAAiB,CAACC,KAAD,EAAyBC,GAAzB,KAAiC;EACjE,MAAM;IACFC,gBADE;IAEFC,gBAAgB,GAAG,CAFjB;IAGFC,aAHE;IAIFC,aAJE;IAKFC,qBALE;IAMFC,gBAAgB,GAAG;MAAEC,UAAU,EAAE,GAAd;MAAmBC,UAAU,EAAE;IAA/B;EANjB,IAOFT,KAPJ;EASA,MAAMU,mBAAmB,GAAG/B,cAAc,CAAC,CAAD,CAA1C;EACA,MAAMgC,eAAe,GAAGhC,cAAc,CAAC+B,mBAAmB,CAACE,KAArB,CAAtC;EAEA,MAAMC,mBAAmB,GAAG1C,MAAM,CAAC,KAAD,CAAlC;EAEA,MAAM2C,gBAAgB,GAAGnC,cAAc,CAAC,CAAD,CAAvC;EACA,MAAM,CAACoC,OAAD,EAAUC,UAAV,IAAwB5C,QAAQ,CAAC,IAAD,CAAtC;EAEA,MAAM6C,aAAa,GAAGvC,gBAAgB,CAAC,OAAO;IAC1CwC,SAAS,EAAE,CAAC;MAAEC,UAAU,EAAER,eAAe,CAACC;IAA9B,CAAD,CAD+B;IAE1CQ,OAAO,EAAEN,gBAAgB,CAACF;EAFgB,CAAP,CAAD,CAAtC;EAKA,MAAMS,kBAAkB,GAAGjB,aAAa,GAAGD,gBAA3C;;EAEA,MAAMmB,eAAe,GAAIC,KAAD,IAAoD;IACxE,IAAIV,mBAAmB,CAACW,OAApB,KAAgC,KAApC,EAA2C;MACvC,MAAMC,iBAAiB,GAAGxC,kBAAkB,CAACsC,KAAK,CAACG,WAAN,CAAkBC,aAAlB,CAAgCC,CAAjC,EAAoCP,kBAApC,CAA5C;MACA,MAAMQ,MAAM,GAAG3C,kBAAkB,CAACuC,iBAAD,EAAoBpB,aAApB,CAAjC;;MAEA,IAAIwB,MAAM,GAAG,CAAT,IAAclB,eAAe,CAACC,KAAhB,GAAwB,CAA1C,EAA6C;QACzCF,mBAAmB,CAACE,KAApB,GAA4B,CAA5B;QACAD,eAAe,CAACC,KAAhB,GAAwB,CAAxB;QACA;MACH;;MAED,IAAIiB,MAAM,GAAGxB,aAAT,IAA0BM,eAAe,CAACC,KAAhB,GAAwBP,aAAtD,EAAqE;QACjEK,mBAAmB,CAACE,KAApB,GAA4BP,aAA5B;QACAM,eAAe,CAACC,KAAhB,GAAwBP,aAAxB;QACA;MACH;;MAEDK,mBAAmB,CAACE,KAApB,GAA4BiB,MAA5B;IACH,CAjBD,MAiBO;MACHb,UAAU,CAAC,IAAD,CAAV;IACH;EACJ,CArBD;;EAuBA,MAAMc,sBAAsB,GAAG,MAAMjB,mBAAmB,CAACW,OAAzD;;EAEAtD,mBAAmB,CACf+B,GADe,EAEf,OAAO;IACH6B,sBADG;IAEHR,eAFG;IAGHN;EAHG,CAAP,CAFe,EAOf,EAPe,CAAnB;;EAUA,MAAMe,YAAY,GAAG,MAAM;IACvB,MAAMN,iBAAiB,GAAGxC,kBAAkB,CAAC0B,eAAe,CAACC,KAAjB,EAAwBP,aAAxB,CAA5C;IACA,MAAMwB,MAAM,GAAG3C,kBAAkB,CAACuC,iBAAD,EAAoBJ,kBAApB,CAAjC;IAEAf,qBAAqB,CAACuB,MAAD,CAArB;EACH,CALD;;EAOA,MAAMG,sBAAsB,GAAIpB,KAAD,IAAoBC,mBAAmB,CAACW,OAApB,GAA8BZ,KAAjF;;EAEA,MAAMqB,GAAG,GAAG3D,OAAO,CAAC4D,GAAR,GACPC,OADO,CACEC,CAAD,IAAO;IACZzB,eAAe,CAACC,KAAhB,GAAwBF,mBAAmB,CAACE,KAA5C;IACAnC,OAAO,CAACuD,sBAAD,CAAP,CAAgC,IAAhC;EACH,CAJO,EAKPK,QALO,CAKGD,CAAD,IAAO;IACb,IAAIzB,eAAe,CAACC,KAAhB,IAAyB,CAAzB,IAA8BwB,CAAC,CAACE,YAAF,GAAiB,CAAnD,EAAsD;MAClD3B,eAAe,CAACC,KAAhB,GAAwB,CAAxB;MACA;IACH;;IAED,IAAID,eAAe,CAACC,KAAhB,IAAyBP,aAAzB,IAA0C+B,CAAC,CAACE,YAAF,GAAiB,CAA/D,EAAkE;MAC9D3B,eAAe,CAACC,KAAhB,GAAwBP,aAAxB;MACA;IACH;;IAEDM,eAAe,CAACC,KAAhB,GAAwBF,mBAAmB,CAACE,KAApB,GAA4BwB,CAAC,CAACE,YAAtD;IAEA7D,OAAO,CAACsD,YAAD,CAAP;EACH,CAnBO,EAoBPQ,UApBO,CAoBKH,CAAD,IAAO;IACf1B,mBAAmB,CAACE,KAApB,GAA4BD,eAAe,CAACC,KAA5C;IACAnC,OAAO,CAACuD,sBAAD,CAAP,CAAgC,KAAhC;EACH,CAvBO,CAAZ;;EAyBA,MAAMQ,IAAI,GAAG,MAAM1B,gBAAgB,CAACF,KAAjB,GAAyBhC,SAAS,CAAC,CAAD,EAAIC,UAAU,CAAC,CAAD,EAAI;IAAE4D,QAAQ,EAAElC,gBAAgB,CAACC;EAA7B,CAAJ,CAAd,CAArD;;EAEA,MAAMkC,IAAI,GAAG,MAAM5B,gBAAgB,CAACF,KAAjB,GAAyBhC,SAAS,CAAC,CAAD,EAAIC,UAAU,CAAC,CAAD,EAAI;IAAE4D,QAAQ,EAAElC,gBAAgB,CAACE;EAA7B,CAAJ,CAAd,CAArD;;EAEAxC,SAAS,CAAC,MAAM;IACZ,IAAI8C,OAAJ,EAAa;MACTJ,eAAe,CAACC,KAAhB,GAAwBF,mBAAmB,CAACE,KAA5C;MACA8B,IAAI;IACP,CAHD,MAGO;MACHF,IAAI;IACP;EACJ,CAPQ,EAON,CAACzB,OAAD,CAPM,CAAT;EASA,oBACI,oBAAC,IAAD;IACI,KAAK,EAAE,CACH;MAAExB,MAAM,EAAEc;IAAV,CADG,EAEHlB,MAAM,CAACS,IAFJ,EAGHM,gBAHG;EADX,gBAOI,oBAAC,eAAD;IAAiB,OAAO,EAAE+B;EAA1B,gBACI,oBAAC,QAAD,CAAU,IAAV;IAAe,KAAK,EAAE,CAClBhB,aADkB,EAElB9B,MAAM,CAACE,SAFW;EAAtB,gBAII,oBAAC,SAAD;IACI,IAAI,EAAE,SADV;IAEI,MAAM,EAAE,EAFZ;IAGI,KAAK,EAAE;EAHX,EAJJ,eASI,oBAAC,WAAD;IACI,IAAI,EAAE,SADV;IAEI,MAAM,EAAE,EAFZ;IAGI,KAAK,EAAE;EAHX,EATJ,CADJ,CAPJ,CADJ;AA2BH,CAtIkB,CAAnB;AAwIA,eAAeS,UAAf"}
|
|
1
|
+
{"version":3,"names":["React","useEffect","useImperativeHandle","useRef","useState","View","Gesture","GestureDetector","Animated","runOnJS","useAnimatedStyle","useSharedValue","withDelay","withTiming","ChevronDown","ChevronUp","StyleSheet","offsetToPercentage","percentageToOffset","styles","create","indicator","width","height","backgroundColor","flexDirection","alignItems","justifyContent","borderRadius","view","padding","position","FastScroll","forwardRef","props","ref","absolutePosition","additionalLength","contentLength","movementRange","scrollContentToOffset","visibleDurations","hideMillis","showMillis","lastIndicatorOffset","indicatorOffset","value","isIndicatorDragging","indicatorOpacity","visible","setVisible","animatedStyle","transform","translateY","opacity","totalContentLength","onContentScroll","event","current","contentPercentage","nativeEvent","contentOffset","y","offset","getIsIndicatorDragging","handleUpdate","setIsIndicatorDragging","pan","Pan","onBegin","e","onUpdate","translationY","onFinalize","hide","duration","show"],"sources":["FastScroll.tsx"],"sourcesContent":["import React, { useEffect, useImperativeHandle, useRef, useState } from 'react';\nimport { NativeScrollEvent, NativeSyntheticEvent, View } from 'react-native';\nimport { Gesture, GestureDetector } from 'react-native-gesture-handler';\nimport Animated, { runOnJS, useAnimatedStyle, useSharedValue, withDelay, withTiming } from 'react-native-reanimated';\nimport { ChevronDown, ChevronUp } from '@fountain-ui/icons';\nimport { StyleSheet } from '@fountain-ui/core';\nimport FastScrollProps from './FastScrollProps';\nimport { offsetToPercentage, percentageToOffset } from './util';\n\nconst styles = StyleSheet.create({\n indicator: {\n width: 28,\n height: 48,\n backgroundColor: '#767676',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 16,\n },\n view: { padding: 4, position: 'absolute' },\n});\n\nconst FastScroll = React.forwardRef((props: FastScrollProps, ref) => {\n const {\n absolutePosition,\n additionalLength = 0,\n contentLength,\n movementRange,\n scrollContentToOffset,\n visibleDurations = { hideMillis: 200, showMillis: 350 },\n } = props;\n\n const lastIndicatorOffset = useSharedValue(0);\n const indicatorOffset = useSharedValue(lastIndicatorOffset.value);\n\n const isIndicatorDragging = useRef(false);\n\n const indicatorOpacity = useSharedValue(1);\n const [visible, setVisible] = useState(true);\n\n const animatedStyle = useAnimatedStyle(() => ({\n transform: [{ translateY: indicatorOffset.value }],\n opacity: indicatorOpacity.value,\n }));\n\n const totalContentLength = contentLength + additionalLength;\n\n const onContentScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {\n if (!isIndicatorDragging.current) {\n const contentPercentage = offsetToPercentage(event.nativeEvent.contentOffset.y, totalContentLength);\n const offset = percentageToOffset(contentPercentage, movementRange);\n\n if (offset < 0 || indicatorOffset.value < 0) {\n lastIndicatorOffset.value = 0;\n indicatorOffset.value = 0;\n return;\n }\n\n if (offset > movementRange || indicatorOffset.value > movementRange) {\n lastIndicatorOffset.value = movementRange;\n indicatorOffset.value = movementRange;\n return;\n }\n\n lastIndicatorOffset.value = offset;\n } else {\n setVisible(true);\n }\n };\n\n const getIsIndicatorDragging = () => isIndicatorDragging.current;\n\n useImperativeHandle(\n ref,\n () => ({\n getIsIndicatorDragging,\n onContentScroll,\n setVisible,\n }),\n [],\n );\n\n const handleUpdate = () => {\n const contentPercentage = offsetToPercentage(indicatorOffset.value, movementRange);\n const offset = percentageToOffset(contentPercentage, totalContentLength);\n\n scrollContentToOffset(offset);\n };\n\n const setIsIndicatorDragging = (value: boolean) => isIndicatorDragging.current = value;\n\n const pan = Gesture.Pan()\n .onBegin((e) => {\n indicatorOffset.value = lastIndicatorOffset.value;\n runOnJS(setIsIndicatorDragging)(true);\n })\n .onUpdate((e) => {\n if (indicatorOffset.value <= 0 && e.translationY < 0) {\n indicatorOffset.value = 0;\n return;\n }\n\n if (indicatorOffset.value >= movementRange && e.translationY > 0) {\n indicatorOffset.value = movementRange;\n return;\n }\n\n indicatorOffset.value = lastIndicatorOffset.value + e.translationY;\n\n runOnJS(handleUpdate)();\n })\n .onFinalize((e) => {\n lastIndicatorOffset.value = indicatorOffset.value;\n runOnJS(setIsIndicatorDragging)(false);\n });\n\n const hide = () => indicatorOpacity.value = withDelay(0, withTiming(0, { duration: visibleDurations.hideMillis }));\n\n const show = () => indicatorOpacity.value = withDelay(0, withTiming(1, { duration: visibleDurations.showMillis }));\n\n useEffect(() => {\n if (visible) {\n indicatorOffset.value = lastIndicatorOffset.value;\n show();\n } else {\n hide();\n }\n }, [visible]);\n\n return (\n <View\n style={[\n { height: movementRange },\n styles.view,\n absolutePosition,\n ]}\n >\n <GestureDetector gesture={pan}>\n <Animated.View style={[\n animatedStyle,\n styles.indicator,\n ]}>\n <ChevronUp\n fill={'#ededed'}\n height={20}\n width={20}\n />\n <ChevronDown\n fill={'#ededed'}\n height={20}\n width={20}\n />\n </Animated.View>\n </GestureDetector>\n </View>\n );\n});\n\nexport default FastScroll;"],"mappings":"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"}
|
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.54",
|
|
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": "f9c278a3d035ceaf0745d32398b6036369327678"
|
|
74
74
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
-
import { FlatList, ListRenderItem, NativeScrollEvent, NativeSyntheticEvent, ViewToken } from 'react-native';
|
|
2
|
+
import { FlatList, ListRenderItem, NativeScrollEvent, NativeSyntheticEvent, Platform, ViewToken } from 'react-native';
|
|
3
3
|
import * as R from 'ramda';
|
|
4
4
|
import { default as ComicViewerProps, Dimension, IntrinsicImage } from './ComicViewerProps';
|
|
5
5
|
import ViewerItem from './ViewerItem';
|
|
@@ -56,8 +56,6 @@ const mapIndexed = R.addIndex<IntrinsicImage>(R.map);
|
|
|
56
56
|
|
|
57
57
|
const MAXIMUM_WIDTH = 720;
|
|
58
58
|
|
|
59
|
-
const NUMBER_OF_ADJACENT_ITEM = 5;
|
|
60
|
-
|
|
61
59
|
export default function ComicViewer(props: ComicViewerProps) {
|
|
62
60
|
const {
|
|
63
61
|
debounceMillis = 100,
|
|
@@ -82,8 +80,6 @@ export default function ComicViewer(props: ComicViewerProps) {
|
|
|
82
80
|
|
|
83
81
|
const flatListRef = useRef<FlatList>(null);
|
|
84
82
|
|
|
85
|
-
const maybeLoadableItemsIndexRange = useRef<[number, number]>([-1, 0]);
|
|
86
|
-
|
|
87
83
|
const actualImageWidth = Math.min(viewportWidth, maxContentWidth);
|
|
88
84
|
|
|
89
85
|
const initialImageStates = useMemo<Array<ImageState>>(() => R.map(createInitialImageState, intrinsicImages), []);
|
|
@@ -147,14 +143,13 @@ export default function ComicViewer(props: ComicViewerProps) {
|
|
|
147
143
|
});
|
|
148
144
|
};
|
|
149
145
|
|
|
150
|
-
const
|
|
146
|
+
const updateTryRenderingMillis = () => {
|
|
151
147
|
const tryRenderingMillis = new Date().getTime();
|
|
152
148
|
|
|
153
149
|
updateImageState((imageState, i) => {
|
|
154
150
|
const urlState = imageState.urlState;
|
|
155
|
-
const shouldRerender = R.includes(i, R.defaultTo([], indexes));
|
|
156
151
|
|
|
157
|
-
if (
|
|
152
|
+
if (urlState?.validity === 'invalid') {
|
|
158
153
|
return {
|
|
159
154
|
...imageState,
|
|
160
155
|
tryRenderingMillis,
|
|
@@ -164,30 +159,8 @@ export default function ComicViewer(props: ComicViewerProps) {
|
|
|
164
159
|
return imageState;
|
|
165
160
|
});
|
|
166
161
|
};
|
|
167
|
-
|
|
168
|
-
const renderMaybeLoadableItems = () => {
|
|
169
|
-
const [startIndex, endIndex] = maybeLoadableItemsIndexRange.current;
|
|
170
|
-
const affectedIndexes = R.range(startIndex, endIndex);
|
|
171
|
-
|
|
172
|
-
updateItems(affectedIndexes);
|
|
173
|
-
};
|
|
174
|
-
|
|
175
162
|
const onViewableItemsChanged = useRef(({ viewableItems }: { viewableItems: Array<ViewToken> }) => {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
const firstViewableIndex = R.head(orderedViewableItems)?.index;
|
|
179
|
-
const lastViewableItemIndex = R.last(orderedViewableItems)?.index;
|
|
180
|
-
|
|
181
|
-
if (R.isNil(firstViewableIndex) || R.isNil(lastViewableItemIndex)) {
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const startIndex = R.max(firstViewableIndex - NUMBER_OF_ADJACENT_ITEM, 0);
|
|
186
|
-
const endIndex = R.min(lastViewableItemIndex + NUMBER_OF_ADJACENT_ITEM, itemStates.length - 1);
|
|
187
|
-
|
|
188
|
-
maybeLoadableItemsIndexRange.current = [startIndex, endIndex + 1];
|
|
189
|
-
|
|
190
|
-
renderMaybeLoadableItems();
|
|
163
|
+
updateTryRenderingMillis();
|
|
191
164
|
});
|
|
192
165
|
|
|
193
166
|
const handleScroll = useCallback((event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
@@ -228,16 +201,13 @@ export default function ComicViewer(props: ComicViewerProps) {
|
|
|
228
201
|
return;
|
|
229
202
|
}
|
|
230
203
|
|
|
231
|
-
|
|
232
|
-
if (index >= startIndex || index < endIndex) {
|
|
233
|
-
renderMaybeLoadableItems();
|
|
234
|
-
}
|
|
204
|
+
updateTryRenderingMillis();
|
|
235
205
|
};
|
|
236
206
|
|
|
237
207
|
const handleReloadPress = () => {
|
|
238
208
|
onReloadPress && onReloadPress();
|
|
239
209
|
|
|
240
|
-
|
|
210
|
+
updateTryRenderingMillis();
|
|
241
211
|
};
|
|
242
212
|
|
|
243
213
|
const onLoad = () => {
|
|
@@ -275,10 +245,29 @@ export default function ComicViewer(props: ComicViewerProps) {
|
|
|
275
245
|
}, [onItemPress, renderedDimensions]);
|
|
276
246
|
|
|
277
247
|
useEffect(() => {
|
|
278
|
-
const
|
|
248
|
+
const scroll = () => {
|
|
249
|
+
const offset = Math.floor((initialScrollPercentage / 100) * totalHeight);
|
|
250
|
+
|
|
251
|
+
if (flatListRef.current) {
|
|
252
|
+
flatListRef.current.scrollToOffset({ offset, animated: false });
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
let timeoutId: NodeJS.Timeout | undefined = undefined;
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* @FIXME
|
|
260
|
+
* scrollToOffset has issue(no effect) in useEffect hook on iOS.
|
|
261
|
+
* ref: https://github.com/facebook/react-native/issues/35575
|
|
262
|
+
*/
|
|
263
|
+
if (Platform.OS === 'ios') {
|
|
264
|
+
timeoutId = setTimeout(scroll, 0);
|
|
265
|
+
} else {
|
|
266
|
+
scroll();
|
|
267
|
+
}
|
|
279
268
|
|
|
280
|
-
|
|
281
|
-
|
|
269
|
+
return () => {
|
|
270
|
+
timeoutId && clearTimeout(timeoutId);
|
|
282
271
|
}
|
|
283
272
|
}, []);
|
|
284
273
|
|
|
@@ -9,14 +9,15 @@ import { offsetToPercentage, percentageToOffset } from './util';
|
|
|
9
9
|
|
|
10
10
|
const styles = StyleSheet.create({
|
|
11
11
|
indicator: {
|
|
12
|
-
width:
|
|
13
|
-
height:
|
|
12
|
+
width: 28,
|
|
13
|
+
height: 48,
|
|
14
14
|
backgroundColor: '#767676',
|
|
15
15
|
flexDirection: 'column',
|
|
16
16
|
alignItems: 'center',
|
|
17
|
-
|
|
17
|
+
justifyContent: 'center',
|
|
18
|
+
borderRadius: 16,
|
|
18
19
|
},
|
|
19
|
-
view: { position: 'absolute' },
|
|
20
|
+
view: { padding: 4, position: 'absolute' },
|
|
20
21
|
});
|
|
21
22
|
|
|
22
23
|
const FastScroll = React.forwardRef((props: FastScrollProps, ref) => {
|
|
@@ -45,7 +46,7 @@ const FastScroll = React.forwardRef((props: FastScrollProps, ref) => {
|
|
|
45
46
|
const totalContentLength = contentLength + additionalLength;
|
|
46
47
|
|
|
47
48
|
const onContentScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
48
|
-
if (isIndicatorDragging.current
|
|
49
|
+
if (!isIndicatorDragging.current) {
|
|
49
50
|
const contentPercentage = offsetToPercentage(event.nativeEvent.contentOffset.y, totalContentLength);
|
|
50
51
|
const offset = percentageToOffset(contentPercentage, movementRange);
|
|
51
52
|
|