@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.
@@ -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 updateItems = indexes => {
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 (shouldRerender && (urlState === null || urlState === void 0 ? void 0 : urlState.validity) !== 'valid') {
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
- const orderedViewableItems = R.sort((a, b) => (a.index || 0) - (b.index || 0), viewableItems);
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
- const [startIndex, endIndex] = maybeLoadableItemsIndexRange.current;
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
- updateItems([index]);
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 offset = Math.floor(initialScrollPercentage / 100 * totalHeight);
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
- if (flatListRef.current) {
265
- flatListRef.current.scrollToOffset({
266
- offset,
267
- animated: false
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: 24,
29
- height: 40,
28
+ width: 28,
29
+ height: 48,
30
30
  backgroundColor: '#767676',
31
31
  flexDirection: 'column',
32
32
  alignItems: 'center',
33
- borderRadius: 4
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 === false) {
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 updateItems = indexes => {
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 (shouldRerender && (urlState === null || urlState === void 0 ? void 0 : urlState.validity) !== 'valid') {
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
- const orderedViewableItems = R.sort((a, b) => (a.index || 0) - (b.index || 0), viewableItems);
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
- const [startIndex, endIndex] = maybeLoadableItemsIndexRange.current;
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
- updateItems([index]);
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 offset = Math.floor(initialScrollPercentage / 100 * totalHeight);
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
- if (flatListRef.current) {
247
- flatListRef.current.scrollToOffset({
248
- offset,
249
- animated: false
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: 24,
11
- height: 40,
10
+ width: 28,
11
+ height: 48,
12
12
  backgroundColor: '#767676',
13
13
  flexDirection: 'column',
14
14
  alignItems: 'center',
15
- borderRadius: 4
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 === false) {
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":"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"}
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.52",
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": "ba0faed7f492a6b00b7614c06f23f2fab290e01e"
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 updateItems = (indexes: number[]) => {
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 (shouldRerender && urlState?.validity !== 'valid') {
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
- const orderedViewableItems = R.sort((a, b) => (a.index || 0) - (b.index || 0), viewableItems);
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
- const [startIndex, endIndex] = maybeLoadableItemsIndexRange.current;
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
- updateItems([index]);
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 offset = Math.floor((initialScrollPercentage / 100) * totalHeight);
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
- if (flatListRef.current) {
281
- flatListRef.current.scrollToOffset({ offset, animated: false });
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: 24,
13
- height: 40,
12
+ width: 28,
13
+ height: 48,
14
14
  backgroundColor: '#767676',
15
15
  flexDirection: 'column',
16
16
  alignItems: 'center',
17
- borderRadius: 4,
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 === false) {
49
+ if (!isIndicatorDragging.current) {
49
50
  const contentPercentage = offsetToPercentage(event.nativeEvent.contentOffset.y, totalContentLength);
50
51
  const offset = percentageToOffset(contentPercentage, movementRange);
51
52