@fountain-ui/lab 2.0.0-beta.33 → 2.0.0-beta.34

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.
@@ -36,6 +36,7 @@ function ComicViewer(props) {
36
36
  data,
37
37
  errorDebounceMillis = 500,
38
38
  errorRetryCount = 3,
39
+ responseTimestamp,
39
40
  initialNumToRender = 1,
40
41
  initialScrollPercentage = 0,
41
42
  itemVisiblePercentThreshold = 0,
@@ -52,7 +53,6 @@ function ComicViewer(props) {
52
53
  const flatListRef = (0, _react.useRef)(null);
53
54
  const errors = (0, _react.useRef)(new Map());
54
55
  const debounceTimeOut = (0, _react.useRef)(null);
55
- const resourceString = R.toString(R.map(itemData => itemData.url)(data));
56
56
  const imageWidth = Math.min(viewerWidth, 720);
57
57
  const initialItems = R.map(itemData => ({ ...itemData,
58
58
  isViewable: false,
@@ -62,7 +62,7 @@ function ComicViewer(props) {
62
62
  const [items, setItems] = (0, _react.useState)(initialItems);
63
63
  const initialItemState = R.map(itemData => ({
64
64
  sortKey: itemData.sortKey,
65
- state: R.isEmpty(itemData.expiresAt) ? _ComicViewerProps.STATE.INIT : _ComicViewerProps.STATE.URL_LOADED
65
+ state: R.isNil(itemData.id) ? _ComicViewerProps.STATE.INIT : _ComicViewerProps.STATE.URL_LOADED
66
66
  }))(data);
67
67
  const itemStates = (0, _react.useRef)(initialItemState);
68
68
  const itemHeights = [...getItemHeights(items)];
@@ -159,6 +159,7 @@ function ComicViewer(props) {
159
159
  const itemState = R.find(state => state.sortKey === item.sortKey)(itemStates.current);
160
160
  const props = { ...item,
161
161
  itemState,
162
+ responseTimestamp,
162
163
  errorRetryCount,
163
164
  onError: itemErrorHandler,
164
165
  onLoaded: itemLoadedHandler,
@@ -168,14 +169,14 @@ function ComicViewer(props) {
168
169
  return /*#__PURE__*/_react.default.createElement(_ViewerItem.default, {
169
170
  props: props
170
171
  });
171
- }, [resourceString, itemErrorHandler, itemLoadedHandler, onItemPress]);
172
+ }, [responseTimestamp, itemErrorHandler, itemLoadedHandler, onItemPress]);
172
173
  (0, _react.useEffect)(() => {
173
174
  setItems(prev => {
174
175
  return R.map(prevItem => {
175
176
  const currentData = R.find(currentItemData => prevItem.sortKey === currentItemData.sortKey)(data);
176
177
  const itemState = R.find(state => state.sortKey === (currentData === null || currentData === void 0 ? void 0 : currentData.sortKey))(itemStates.current);
177
178
 
178
- if (currentData && itemState && itemState.state !== _ComicViewerProps.STATE.LOADED && currentData.url !== prevItem.url) {
179
+ if (currentData && currentData.id && itemState && itemState.state !== _ComicViewerProps.STATE.LOADED) {
179
180
  itemState.state = _ComicViewerProps.STATE.URL_LOADED;
180
181
  return { ...prevItem,
181
182
  url: currentData.url,
@@ -187,7 +188,7 @@ function ComicViewer(props) {
187
188
  })([...prev]);
188
189
  ;
189
190
  });
190
- }, [resourceString]);
191
+ }, [responseTimestamp]);
191
192
  (0, _react.useEffect)(() => {
192
193
  const newItems = R.map(item => ({ ...item,
193
194
  width: imageWidth,
@@ -1 +1 @@
1
- {"version":3,"names":["getItemHeights","items","R","map","content","height","appender","left","right","getHeightAccum","itemHeights","mapAccum","keyExtractor","item","sortKey","ComicViewer","props","data","errorDebounceMillis","errorRetryCount","initialNumToRender","initialScrollPercentage","itemVisiblePercentThreshold","onError","onScroll","onItemPress","getNextPage","viewerWidth","windowSize","pageUnit","ListFooterComponent","otherProps","flatListRef","useRef","errors","Map","debounceTimeOut","resourceString","toString","itemData","url","imageWidth","Math","min","initialItems","isViewable","width","setItems","useState","initialItemState","state","isEmpty","expiresAt","STATE","INIT","URL_LOADED","itemStates","itemHeightAccum","viewabilityConfig","useMemo","getItemLayout","useCallback","index","offsets","prepend","length","offset","onViewableItemsChanged","viewableItems","prev","viewableItemSortKeys","viewableItem","firstViewableSortKey","head","lastViewableItemSortKey","last","firstItem","lastItem","isNil","frontBoundary","max","backBoundary","viewableItemBoundary","range","newItems","prevItem","includes","itemLoadedHandler","itemState","find","current","LOADED","error","undefined","itemErrorHandler","errorInfo","count","set","FAIL","handleError","errorsArray","Array","from","entries","errorsInfo","key","value","clear","clearTimeout","size","setTimeout","renderItem","onLoaded","useEffect","currentData","currentItemData","totalHeight","floor","scrollToOffset","animated"],"sources":["ComicViewer.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { FlatList, ListRenderItem, ViewToken } from 'react-native';\nimport * as R from 'ramda';\nimport {\n ComicViewerItemData,\n ComicViewerItemState,\n default as ComicViewerProps,\n ErrorInfo,\n STATE,\n} from './ComicViewerProps';\nimport type ComicViewerItemProps from './ComicViewerItemProps';\nimport ViewerItem from './ViewerItem';\n\nconst getItemHeights = <T, >(items: ComicViewerItemProps<T>[]): number[] => R.map((content: ComicViewerItemProps<T>) => content.height)(items);\nconst appender = (left: number, right: number): [number, number] => [left + right, left + right];\nconst getHeightAccum = (itemHeights: number[]): [number, number[]] => R.mapAccum(appender, 0, itemHeights);\n\nconst keyExtractor = <T, >(item: ComicViewerItemProps<T>) => `${item.sortKey}`;\n\nexport default function ComicViewer<T>(props: ComicViewerProps<T>) {\n const {\n data,\n errorDebounceMillis = 500,\n errorRetryCount = 3,\n initialNumToRender = 1,\n initialScrollPercentage = 0,\n itemVisiblePercentThreshold = 0,\n onError,\n onScroll,\n onItemPress,\n getNextPage,\n viewerWidth,\n windowSize = 3,\n pageUnit,\n ListFooterComponent,\n ...otherProps\n } = props;\n\n const flatListRef = useRef<FlatList>(null);\n\n const errors = useRef<Map<number, ErrorInfo>>(new Map());\n\n const debounceTimeOut = useRef<NodeJS.Timeout | null>(null);\n\n const resourceString = R.toString(R.map((itemData: ComicViewerItemData) => itemData.url)(data));\n\n const imageWidth = Math.min(viewerWidth, 720);\n const initialItems = R.map((itemData: ComicViewerItemData<T>) => ({\n ...itemData,\n isViewable: false,\n width: imageWidth,\n height: (itemData.height * imageWidth) / itemData.width,\n }))(data);\n\n const [items, setItems] = useState<ComicViewerItemProps<T>[]>(initialItems);\n\n const initialItemState: ComicViewerItemState[] = R.map((itemData: ComicViewerItemData<T>) => ({\n sortKey: itemData.sortKey,\n state: R.isEmpty(itemData.expiresAt) ? STATE.INIT : STATE.URL_LOADED,\n }))(data);\n\n const itemStates = useRef<Array<ComicViewerItemState>>(initialItemState);\n\n const itemHeights = [...getItemHeights(items)];\n const itemHeightAccum = getHeightAccum(itemHeights);\n\n const viewabilityConfig = useMemo(() => ({\n itemVisiblePercentThreshold,\n }), [itemVisiblePercentThreshold]);\n\n const getItemLayout = useCallback((data: any, index: number) => {\n const offsets = R.prepend(0, itemHeightAccum[1]);\n\n return {\n length: itemHeights[index],\n offset: offsets[index],\n index,\n };\n }, [itemHeights]);\n\n const onViewableItemsChanged = useRef(({ viewableItems }: {\n viewableItems: Array<ViewToken>,\n }) => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n const viewableItemSortKeys: number[] = R.map((viewableItem: ViewToken) => viewableItem.item.sortKey)(viewableItems);\n const firstViewableSortKey = R.head(viewableItemSortKeys);\n const lastViewableItemSortKey = R.last(viewableItemSortKeys);\n const firstItem = R.head(prev);\n const lastItem = R.last(prev);\n\n if (R.isNil(firstViewableSortKey)\n || R.isNil(lastViewableItemSortKey)\n || R.isNil(firstItem)\n || R.isNil(lastItem)\n ) {\n return prev;\n }\n\n const frontBoundary = R.max(firstItem.sortKey, firstViewableSortKey - 1);\n const backBoundary = R.min(lastItem.sortKey, lastViewableItemSortKey + 1);\n\n const viewableItemBoundary = R.range(frontBoundary, backBoundary + 1);\n const newItems = R.map((prevItem: ComicViewerItemProps<T>) => ({\n ...prevItem,\n isViewable: R.includes(prevItem.sortKey, viewableItemBoundary),\n }))([...prev]);\n\n return newItems;\n });\n });\n\n const itemLoadedHandler = useCallback((sortKey: number) => {\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === sortKey)(itemStates.current);\n\n if (R.isNil(itemState)) {\n return;\n }\n\n itemState.state = STATE.LOADED;\n itemState.error = undefined;\n }, [itemStates]);\n\n const itemErrorHandler = useCallback((errorInfo: ErrorInfo) => {\n const { sortKey, count } = errorInfo;\n\n if (count >= errorRetryCount) {\n return;\n }\n\n errors.current.set(sortKey, errorInfo);\n\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === sortKey)(itemStates.current);\n\n if (R.isNil(itemState)) {\n return;\n }\n\n itemState.state = STATE.FAIL;\n itemState.error = errorInfo;\n\n const handleError = () => {\n const errorsArray = Array.from(errors.current.entries());\n const errorsInfo = R.map(([key, value]: [number, ErrorInfo]) => value)(errorsArray);\n\n onError && onError([...errorsInfo]);\n errors.current.clear();\n };\n\n if (debounceTimeOut.current) {\n clearTimeout(debounceTimeOut.current);\n }\n\n if (errors.current.size === pageUnit) {\n handleError();\n } else {\n debounceTimeOut.current = setTimeout(handleError, errorDebounceMillis);\n }\n }, [errors.current, itemStates]);\n\n const renderItem: ListRenderItem<ComicViewerItemProps<T>> = useCallback(({ item }) => {\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === item.sortKey)(itemStates.current);\n\n const props = {\n ...item,\n itemState,\n errorRetryCount,\n onError: itemErrorHandler,\n onLoaded: itemLoadedHandler,\n onItemPress,\n getNextPage,\n };\n\n return <ViewerItem props={props}/>;\n }, [resourceString, itemErrorHandler, itemLoadedHandler, onItemPress]);\n\n useEffect(() => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n return R.map((prevItem: ComicViewerItemProps<T>) => {\n const currentData: ComicViewerItemData | undefined = R.find((currentItemData: ComicViewerItemData<T>) => prevItem.sortKey === currentItemData.sortKey)(data);\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === currentData?.sortKey)(itemStates.current);\n\n if (currentData\n && itemState\n && itemState.state !== STATE.LOADED\n && (currentData.url !== prevItem.url)) {\n\n itemState.state = STATE.URL_LOADED;\n\n return {\n ...prevItem,\n url: currentData.url,\n expiresAt: currentData.expiresAt,\n };\n }\n\n return prevItem;\n })([...prev]);\n ;\n });\n }, [resourceString]);\n\n useEffect(() => {\n const newItems = R.map((item: ComicViewerItemProps<T>) => ({\n ...item,\n width: imageWidth,\n height: (item.height * imageWidth) / item.width,\n }))(items);\n\n setItems(newItems);\n }, [imageWidth]);\n\n useEffect(() => {\n const totalHeight = itemHeightAccum[0];\n const offset = Math.floor((initialScrollPercentage / 100) * totalHeight);\n\n if (flatListRef.current) {\n flatListRef.current.scrollToOffset({ offset, animated: false });\n }\n }, [flatListRef.current]);\n\n return (\n <FlatList\n data={items}\n getItemLayout={getItemLayout}\n initialNumToRender={initialNumToRender}\n keyExtractor={keyExtractor}\n onViewableItemsChanged={onViewableItemsChanged.current}\n onScroll={onScroll}\n ref={flatListRef}\n renderItem={renderItem}\n viewabilityConfig={viewabilityConfig}\n windowSize={windowSize}\n ListFooterComponent={ListFooterComponent}\n {...otherProps}\n />\n );\n};\n"],"mappings":";;;;;;;AAAA;;AACA;;AACA;;AACA;;AAQA;;;;;;;;;;AAEA,MAAMA,cAAc,GAASC,KAAN,IAAqDC,CAAC,CAACC,GAAF,CAAOC,OAAD,IAAsCA,OAAO,CAACC,MAApD,EAA4DJ,KAA5D,CAA5E;;AACA,MAAMK,QAAQ,GAAG,CAACC,IAAD,EAAeC,KAAf,KAAmD,CAACD,IAAI,GAAGC,KAAR,EAAeD,IAAI,GAAGC,KAAtB,CAApE;;AACA,MAAMC,cAAc,GAAIC,WAAD,IAA+CR,CAAC,CAACS,QAAF,CAAWL,QAAX,EAAqB,CAArB,EAAwBI,WAAxB,CAAtE;;AAEA,MAAME,YAAY,GAASC,IAAN,IAAyC,GAAEA,IAAI,CAACC,OAAQ,EAA7E;;AAEe,SAASC,WAAT,CAAwBC,KAAxB,EAAoD;EAC/D,MAAM;IACFC,IADE;IAEFC,mBAAmB,GAAG,GAFpB;IAGFC,eAAe,GAAG,CAHhB;IAIFC,kBAAkB,GAAG,CAJnB;IAKFC,uBAAuB,GAAG,CALxB;IAMFC,2BAA2B,GAAG,CAN5B;IAOFC,OAPE;IAQFC,QARE;IASFC,WATE;IAUFC,WAVE;IAWFC,WAXE;IAYFC,UAAU,GAAG,CAZX;IAaFC,QAbE;IAcFC,mBAdE;IAeF,GAAGC;EAfD,IAgBFf,KAhBJ;EAkBA,MAAMgB,WAAW,GAAG,IAAAC,aAAA,EAAiB,IAAjB,CAApB;EAEA,MAAMC,MAAM,GAAG,IAAAD,aAAA,EAA+B,IAAIE,GAAJ,EAA/B,CAAf;EAEA,MAAMC,eAAe,GAAG,IAAAH,aAAA,EAA8B,IAA9B,CAAxB;EAEA,MAAMI,cAAc,GAAGnC,CAAC,CAACoC,QAAF,CAAWpC,CAAC,CAACC,GAAF,CAAOoC,QAAD,IAAmCA,QAAQ,CAACC,GAAlD,EAAuDvB,IAAvD,CAAX,CAAvB;EAEA,MAAMwB,UAAU,GAAGC,IAAI,CAACC,GAAL,CAAShB,WAAT,EAAsB,GAAtB,CAAnB;EACA,MAAMiB,YAAY,GAAG1C,CAAC,CAACC,GAAF,CAAOoC,QAAD,KAAuC,EAC9D,GAAGA,QAD2D;IAE9DM,UAAU,EAAE,KAFkD;IAG9DC,KAAK,EAAEL,UAHuD;IAI9DpC,MAAM,EAAGkC,QAAQ,CAAClC,MAAT,GAAkBoC,UAAnB,GAAiCF,QAAQ,CAACO;EAJY,CAAvC,CAAN,EAKjB7B,IALiB,CAArB;EAOA,MAAM,CAAChB,KAAD,EAAQ8C,QAAR,IAAoB,IAAAC,eAAA,EAAoCJ,YAApC,CAA1B;EAEA,MAAMK,gBAAwC,GAAG/C,CAAC,CAACC,GAAF,CAAOoC,QAAD,KAAuC;IACtFzB,OAAO,EAAEyB,QAAQ,CAACzB,OADoE;IAEtFoC,KAAK,EAAEhD,CAAC,CAACiD,OAAF,CAAUZ,QAAQ,CAACa,SAAnB,IAAgCC,uBAAA,CAAMC,IAAtC,GAA6CD,uBAAA,CAAME;EAF4B,CAAvC,CAAN,EAGzCtC,IAHyC,CAAjD;EAKA,MAAMuC,UAAU,GAAG,IAAAvB,aAAA,EAAoCgB,gBAApC,CAAnB;EAEA,MAAMvC,WAAW,GAAG,CAAC,GAAGV,cAAc,CAACC,KAAD,CAAlB,CAApB;EACA,MAAMwD,eAAe,GAAGhD,cAAc,CAACC,WAAD,CAAtC;EAEA,MAAMgD,iBAAiB,GAAG,IAAAC,cAAA,EAAQ,OAAO;IACrCrC;EADqC,CAAP,CAAR,EAEtB,CAACA,2BAAD,CAFsB,CAA1B;EAIA,MAAMsC,aAAa,GAAG,IAAAC,kBAAA,EAAY,CAAC5C,IAAD,EAAY6C,KAAZ,KAA8B;IAC5D,MAAMC,OAAO,GAAG7D,CAAC,CAAC8D,OAAF,CAAU,CAAV,EAAaP,eAAe,CAAC,CAAD,CAA5B,CAAhB;IAEA,OAAO;MACHQ,MAAM,EAAEvD,WAAW,CAACoD,KAAD,CADhB;MAEHI,MAAM,EAAEH,OAAO,CAACD,KAAD,CAFZ;MAGHA;IAHG,CAAP;EAKH,CARqB,EAQnB,CAACpD,WAAD,CARmB,CAAtB;EAUA,MAAMyD,sBAAsB,GAAG,IAAAlC,aAAA,EAAO,QAEhC;IAAA,IAFiC;MAAEmC;IAAF,CAEjC;IACFrB,QAAQ,CAAEsB,IAAD,IAAqC;MAC1C,MAAMC,oBAA8B,GAAGpE,CAAC,CAACC,GAAF,CAAOoE,YAAD,IAA6BA,YAAY,CAAC1D,IAAb,CAAkBC,OAArD,EAA8DsD,aAA9D,CAAvC;MACA,MAAMI,oBAAoB,GAAGtE,CAAC,CAACuE,IAAF,CAAOH,oBAAP,CAA7B;MACA,MAAMI,uBAAuB,GAAGxE,CAAC,CAACyE,IAAF,CAAOL,oBAAP,CAAhC;MACA,MAAMM,SAAS,GAAG1E,CAAC,CAACuE,IAAF,CAAOJ,IAAP,CAAlB;MACA,MAAMQ,QAAQ,GAAG3E,CAAC,CAACyE,IAAF,CAAON,IAAP,CAAjB;;MAEA,IAAInE,CAAC,CAAC4E,KAAF,CAAQN,oBAAR,KACGtE,CAAC,CAAC4E,KAAF,CAAQJ,uBAAR,CADH,IAEGxE,CAAC,CAAC4E,KAAF,CAAQF,SAAR,CAFH,IAGG1E,CAAC,CAAC4E,KAAF,CAAQD,QAAR,CAHP,EAIE;QACE,OAAOR,IAAP;MACH;;MAED,MAAMU,aAAa,GAAG7E,CAAC,CAAC8E,GAAF,CAAMJ,SAAS,CAAC9D,OAAhB,EAAyB0D,oBAAoB,GAAG,CAAhD,CAAtB;MACA,MAAMS,YAAY,GAAG/E,CAAC,CAACyC,GAAF,CAAMkC,QAAQ,CAAC/D,OAAf,EAAwB4D,uBAAuB,GAAG,CAAlD,CAArB;MAEA,MAAMQ,oBAAoB,GAAGhF,CAAC,CAACiF,KAAF,CAAQJ,aAAR,EAAuBE,YAAY,GAAG,CAAtC,CAA7B;MACA,MAAMG,QAAQ,GAAGlF,CAAC,CAACC,GAAF,CAAOkF,QAAD,KAAwC,EAC3D,GAAGA,QADwD;QAE3DxC,UAAU,EAAE3C,CAAC,CAACoF,QAAF,CAAWD,QAAQ,CAACvE,OAApB,EAA6BoE,oBAA7B;MAF+C,CAAxC,CAAN,EAGb,CAAC,GAAGb,IAAJ,CAHa,CAAjB;MAKA,OAAOe,QAAP;IACH,CAzBO,CAAR;EA0BH,CA7B8B,CAA/B;EA+BA,MAAMG,iBAAiB,GAAG,IAAA1B,kBAAA,EAAa/C,OAAD,IAAqB;IACvD,MAAM0E,SAA2C,GAAGtF,CAAC,CAACuF,IAAF,CAAQvC,KAAD,IAAiCA,KAAK,CAACpC,OAAN,KAAkBA,OAA1D,EAAmE0C,UAAU,CAACkC,OAA9E,CAApD;;IAEA,IAAIxF,CAAC,CAAC4E,KAAF,CAAQU,SAAR,CAAJ,EAAwB;MACpB;IACH;;IAEDA,SAAS,CAACtC,KAAV,GAAkBG,uBAAA,CAAMsC,MAAxB;IACAH,SAAS,CAACI,KAAV,GAAkBC,SAAlB;EACH,CATyB,EASvB,CAACrC,UAAD,CATuB,CAA1B;EAWA,MAAMsC,gBAAgB,GAAG,IAAAjC,kBAAA,EAAakC,SAAD,IAA0B;IAC3D,MAAM;MAAEjF,OAAF;MAAWkF;IAAX,IAAqBD,SAA3B;;IAEA,IAAIC,KAAK,IAAI7E,eAAb,EAA8B;MAC1B;IACH;;IAEDe,MAAM,CAACwD,OAAP,CAAeO,GAAf,CAAmBnF,OAAnB,EAA4BiF,SAA5B;IAEA,MAAMP,SAA2C,GAAGtF,CAAC,CAACuF,IAAF,CAAQvC,KAAD,IAAiCA,KAAK,CAACpC,OAAN,KAAkBA,OAA1D,EAAmE0C,UAAU,CAACkC,OAA9E,CAApD;;IAEA,IAAIxF,CAAC,CAAC4E,KAAF,CAAQU,SAAR,CAAJ,EAAwB;MACpB;IACH;;IAEDA,SAAS,CAACtC,KAAV,GAAkBG,uBAAA,CAAM6C,IAAxB;IACAV,SAAS,CAACI,KAAV,GAAkBG,SAAlB;;IAEA,MAAMI,WAAW,GAAG,MAAM;MACtB,MAAMC,WAAW,GAAGC,KAAK,CAACC,IAAN,CAAWpE,MAAM,CAACwD,OAAP,CAAea,OAAf,EAAX,CAApB;MACA,MAAMC,UAAU,GAAGtG,CAAC,CAACC,GAAF,CAAM;QAAA,IAAC,CAACsG,GAAD,EAAMC,KAAN,CAAD;QAAA,OAAuCA,KAAvC;MAAA,CAAN,EAAoDN,WAApD,CAAnB;MAEA7E,OAAO,IAAIA,OAAO,CAAC,CAAC,GAAGiF,UAAJ,CAAD,CAAlB;MACAtE,MAAM,CAACwD,OAAP,CAAeiB,KAAf;IACH,CAND;;IAQA,IAAIvE,eAAe,CAACsD,OAApB,EAA6B;MACzBkB,YAAY,CAACxE,eAAe,CAACsD,OAAjB,CAAZ;IACH;;IAED,IAAIxD,MAAM,CAACwD,OAAP,CAAemB,IAAf,KAAwBhF,QAA5B,EAAsC;MAClCsE,WAAW;IACd,CAFD,MAEO;MACH/D,eAAe,CAACsD,OAAhB,GAA0BoB,UAAU,CAACX,WAAD,EAAcjF,mBAAd,CAApC;IACH;EACJ,CAnCwB,EAmCtB,CAACgB,MAAM,CAACwD,OAAR,EAAiBlC,UAAjB,CAnCsB,CAAzB;EAqCA,MAAMuD,UAAmD,GAAG,IAAAlD,kBAAA,EAAY,SAAc;IAAA,IAAb;MAAEhD;IAAF,CAAa;IAClF,MAAM2E,SAA2C,GAAGtF,CAAC,CAACuF,IAAF,CAAQvC,KAAD,IAAiCA,KAAK,CAACpC,OAAN,KAAkBD,IAAI,CAACC,OAA/D,EAAwE0C,UAAU,CAACkC,OAAnF,CAApD;IAEA,MAAM1E,KAAK,GAAG,EACV,GAAGH,IADO;MAEV2E,SAFU;MAGVrE,eAHU;MAIVI,OAAO,EAAEuE,gBAJC;MAKVkB,QAAQ,EAAEzB,iBALA;MAMV9D,WANU;MAOVC;IAPU,CAAd;IAUA,oBAAO,6BAAC,mBAAD;MAAY,KAAK,EAAEV;IAAnB,EAAP;EACH,CAd2D,EAczD,CAACqB,cAAD,EAAiByD,gBAAjB,EAAmCP,iBAAnC,EAAsD9D,WAAtD,CAdyD,CAA5D;EAgBA,IAAAwF,gBAAA,EAAU,MAAM;IACZlE,QAAQ,CAAEsB,IAAD,IAAqC;MAC1C,OAAOnE,CAAC,CAACC,GAAF,CAAOkF,QAAD,IAAuC;QAChD,MAAM6B,WAA4C,GAAGhH,CAAC,CAACuF,IAAF,CAAQ0B,eAAD,IAA6C9B,QAAQ,CAACvE,OAAT,KAAqBqG,eAAe,CAACrG,OAAzF,EAAkGG,IAAlG,CAArD;QACA,MAAMuE,SAA2C,GAAGtF,CAAC,CAACuF,IAAF,CAAQvC,KAAD,IAAiCA,KAAK,CAACpC,OAAN,MAAkBoG,WAAlB,aAAkBA,WAAlB,uBAAkBA,WAAW,CAAEpG,OAA/B,CAAxC,EAAgF0C,UAAU,CAACkC,OAA3F,CAApD;;QAEA,IAAIwB,WAAW,IACR1B,SADH,IAEGA,SAAS,CAACtC,KAAV,KAAoBG,uBAAA,CAAMsC,MAF7B,IAGIuB,WAAW,CAAC1E,GAAZ,KAAoB6C,QAAQ,CAAC7C,GAHrC,EAG2C;UAEvCgD,SAAS,CAACtC,KAAV,GAAkBG,uBAAA,CAAME,UAAxB;UAEA,OAAO,EACH,GAAG8B,QADA;YAEH7C,GAAG,EAAE0E,WAAW,CAAC1E,GAFd;YAGHY,SAAS,EAAE8D,WAAW,CAAC9D;UAHpB,CAAP;QAKH;;QAED,OAAOiC,QAAP;MACH,CAnBM,EAmBJ,CAAC,GAAGhB,IAAJ,CAnBI,CAAP;MAoBA;IACH,CAtBO,CAAR;EAuBH,CAxBD,EAwBG,CAAChC,cAAD,CAxBH;EA0BA,IAAA4E,gBAAA,EAAU,MAAM;IACZ,MAAM7B,QAAQ,GAAGlF,CAAC,CAACC,GAAF,CAAOU,IAAD,KAAoC,EACvD,GAAGA,IADoD;MAEvDiC,KAAK,EAAEL,UAFgD;MAGvDpC,MAAM,EAAGQ,IAAI,CAACR,MAAL,GAAcoC,UAAf,GAA6B5B,IAAI,CAACiC;IAHa,CAApC,CAAN,EAIb7C,KAJa,CAAjB;IAMA8C,QAAQ,CAACqC,QAAD,CAAR;EACH,CARD,EAQG,CAAC3C,UAAD,CARH;EAUA,IAAAwE,gBAAA,EAAU,MAAM;IACZ,MAAMG,WAAW,GAAG3D,eAAe,CAAC,CAAD,CAAnC;IACA,MAAMS,MAAM,GAAGxB,IAAI,CAAC2E,KAAL,CAAYhG,uBAAuB,GAAG,GAA3B,GAAkC+F,WAA7C,CAAf;;IAEA,IAAIpF,WAAW,CAAC0D,OAAhB,EAAyB;MACrB1D,WAAW,CAAC0D,OAAZ,CAAoB4B,cAApB,CAAmC;QAAEpD,MAAF;QAAUqD,QAAQ,EAAE;MAApB,CAAnC;IACH;EACJ,CAPD,EAOG,CAACvF,WAAW,CAAC0D,OAAb,CAPH;EASA,oBACI,6BAAC,qBAAD;IACI,IAAI,EAAEzF,KADV;IAEI,aAAa,EAAE2D,aAFnB;IAGI,kBAAkB,EAAExC,kBAHxB;IAII,YAAY,EAAER,YAJlB;IAKI,sBAAsB,EAAEuD,sBAAsB,CAACuB,OALnD;IAMI,QAAQ,EAAElE,QANd;IAOI,GAAG,EAAEQ,WAPT;IAQI,UAAU,EAAE+E,UARhB;IASI,iBAAiB,EAAErD,iBATvB;IAUI,UAAU,EAAE9B,UAVhB;IAWI,mBAAmB,EAAEE;EAXzB,GAYQC,UAZR,EADJ;AAgBH;;AAAA"}
1
+ {"version":3,"names":["getItemHeights","items","R","map","content","height","appender","left","right","getHeightAccum","itemHeights","mapAccum","keyExtractor","item","sortKey","ComicViewer","props","data","errorDebounceMillis","errorRetryCount","responseTimestamp","initialNumToRender","initialScrollPercentage","itemVisiblePercentThreshold","onError","onScroll","onItemPress","getNextPage","viewerWidth","windowSize","pageUnit","ListFooterComponent","otherProps","flatListRef","useRef","errors","Map","debounceTimeOut","imageWidth","Math","min","initialItems","itemData","isViewable","width","setItems","useState","initialItemState","state","isNil","id","STATE","INIT","URL_LOADED","itemStates","itemHeightAccum","viewabilityConfig","useMemo","getItemLayout","useCallback","index","offsets","prepend","length","offset","onViewableItemsChanged","viewableItems","prev","viewableItemSortKeys","viewableItem","firstViewableSortKey","head","lastViewableItemSortKey","last","firstItem","lastItem","frontBoundary","max","backBoundary","viewableItemBoundary","range","newItems","prevItem","includes","itemLoadedHandler","itemState","find","current","LOADED","error","undefined","itemErrorHandler","errorInfo","count","set","FAIL","handleError","errorsArray","Array","from","entries","errorsInfo","key","value","clear","clearTimeout","size","setTimeout","renderItem","onLoaded","useEffect","currentData","currentItemData","url","expiresAt","totalHeight","floor","scrollToOffset","animated"],"sources":["ComicViewer.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { FlatList, ListRenderItem, ViewToken } from 'react-native';\nimport * as R from 'ramda';\nimport {\n ComicViewerItemData,\n ComicViewerItemState,\n default as ComicViewerProps,\n ErrorInfo,\n STATE,\n} from './ComicViewerProps';\nimport type ComicViewerItemProps from './ComicViewerItemProps';\nimport ViewerItem from './ViewerItem';\n\nconst getItemHeights = <T, >(items: ComicViewerItemProps<T>[]): number[] => R.map((content: ComicViewerItemProps<T>) => content.height)(items);\nconst appender = (left: number, right: number): [number, number] => [left + right, left + right];\nconst getHeightAccum = (itemHeights: number[]): [number, number[]] => R.mapAccum(appender, 0, itemHeights);\n\nconst keyExtractor = <T, >(item: ComicViewerItemProps<T>) => `${item.sortKey}`;\n\nexport default function ComicViewer<T>(props: ComicViewerProps<T>) {\n const {\n data,\n errorDebounceMillis = 500,\n errorRetryCount = 3,\n responseTimestamp,\n initialNumToRender = 1,\n initialScrollPercentage = 0,\n itemVisiblePercentThreshold = 0,\n onError,\n onScroll,\n onItemPress,\n getNextPage,\n viewerWidth,\n windowSize = 3,\n pageUnit,\n ListFooterComponent,\n ...otherProps\n } = props;\n\n const flatListRef = useRef<FlatList>(null);\n\n const errors = useRef<Map<number, ErrorInfo>>(new Map());\n\n const debounceTimeOut = useRef<NodeJS.Timeout | null>(null);\n\n const imageWidth = Math.min(viewerWidth, 720);\n const initialItems = R.map((itemData: ComicViewerItemData<T>) => ({\n ...itemData,\n isViewable: false,\n width: imageWidth,\n height: (itemData.height * imageWidth) / itemData.width,\n }))(data);\n\n const [items, setItems] = useState<ComicViewerItemProps<T>[]>(initialItems);\n\n const initialItemState: ComicViewerItemState[] = R.map((itemData: ComicViewerItemData<T>) => ({\n sortKey: itemData.sortKey,\n state: R.isNil(itemData.id) ? STATE.INIT : STATE.URL_LOADED,\n }))(data);\n\n const itemStates = useRef<Array<ComicViewerItemState>>(initialItemState);\n\n const itemHeights = [...getItemHeights(items)];\n const itemHeightAccum = getHeightAccum(itemHeights);\n\n const viewabilityConfig = useMemo(() => ({\n itemVisiblePercentThreshold,\n }), [itemVisiblePercentThreshold]);\n\n const getItemLayout = useCallback((data: any, index: number) => {\n const offsets = R.prepend(0, itemHeightAccum[1]);\n\n return {\n length: itemHeights[index],\n offset: offsets[index],\n index,\n };\n }, [itemHeights]);\n\n const onViewableItemsChanged = useRef(({ viewableItems }: {\n viewableItems: Array<ViewToken>,\n }) => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n const viewableItemSortKeys: number[] = R.map((viewableItem: ViewToken) => viewableItem.item.sortKey)(viewableItems);\n const firstViewableSortKey = R.head(viewableItemSortKeys);\n const lastViewableItemSortKey = R.last(viewableItemSortKeys);\n const firstItem = R.head(prev);\n const lastItem = R.last(prev);\n\n if (R.isNil(firstViewableSortKey)\n || R.isNil(lastViewableItemSortKey)\n || R.isNil(firstItem)\n || R.isNil(lastItem)\n ) {\n return prev;\n }\n\n const frontBoundary = R.max(firstItem.sortKey, firstViewableSortKey - 1);\n const backBoundary = R.min(lastItem.sortKey, lastViewableItemSortKey + 1);\n\n const viewableItemBoundary = R.range(frontBoundary, backBoundary + 1);\n const newItems = R.map((prevItem: ComicViewerItemProps<T>) => ({\n ...prevItem,\n isViewable: R.includes(prevItem.sortKey, viewableItemBoundary),\n }))([...prev]);\n\n return newItems;\n });\n });\n\n const itemLoadedHandler = useCallback((sortKey: number) => {\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === sortKey)(itemStates.current);\n\n if (R.isNil(itemState)) {\n return;\n }\n\n itemState.state = STATE.LOADED;\n itemState.error = undefined;\n }, [itemStates]);\n\n const itemErrorHandler = useCallback((errorInfo: ErrorInfo) => {\n const { sortKey, count } = errorInfo;\n\n if (count >= errorRetryCount) {\n return;\n }\n\n errors.current.set(sortKey, errorInfo);\n\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === sortKey)(itemStates.current);\n\n if (R.isNil(itemState)) {\n return;\n }\n\n itemState.state = STATE.FAIL;\n itemState.error = errorInfo;\n\n const handleError = () => {\n const errorsArray = Array.from(errors.current.entries());\n const errorsInfo = R.map(([key, value]: [number, ErrorInfo]) => value)(errorsArray);\n\n onError && onError([...errorsInfo]);\n errors.current.clear();\n };\n\n if (debounceTimeOut.current) {\n clearTimeout(debounceTimeOut.current);\n }\n\n if (errors.current.size === pageUnit) {\n handleError();\n } else {\n debounceTimeOut.current = setTimeout(handleError, errorDebounceMillis);\n }\n }, [errors.current, itemStates]);\n\n const renderItem: ListRenderItem<ComicViewerItemProps<T>> = useCallback(({ item }) => {\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === item.sortKey)(itemStates.current);\n\n const props = {\n ...item,\n itemState,\n responseTimestamp,\n errorRetryCount,\n onError: itemErrorHandler,\n onLoaded: itemLoadedHandler,\n onItemPress,\n getNextPage,\n };\n\n return <ViewerItem props={props}/>;\n }, [responseTimestamp, itemErrorHandler, itemLoadedHandler, onItemPress]);\n\n useEffect(() => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n return R.map((prevItem: ComicViewerItemProps<T>) => {\n const currentData: ComicViewerItemData | undefined = R.find((currentItemData: ComicViewerItemData<T>) => prevItem.sortKey === currentItemData.sortKey)(data);\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === currentData?.sortKey)(itemStates.current);\n\n if (currentData\n && currentData.id\n && itemState\n && itemState.state !== STATE.LOADED) {\n\n itemState.state = STATE.URL_LOADED;\n\n return {\n ...prevItem,\n url: currentData.url,\n expiresAt: currentData.expiresAt,\n };\n }\n\n return prevItem;\n })([...prev]);\n ;\n });\n }, [responseTimestamp]);\n\n useEffect(() => {\n const newItems = R.map((item: ComicViewerItemProps<T>) => ({\n ...item,\n width: imageWidth,\n height: (item.height * imageWidth) / item.width,\n }))(items);\n\n setItems(newItems);\n }, [imageWidth]);\n\n useEffect(() => {\n const totalHeight = itemHeightAccum[0];\n const offset = Math.floor((initialScrollPercentage / 100) * totalHeight);\n\n if (flatListRef.current) {\n flatListRef.current.scrollToOffset({ offset, animated: false });\n }\n }, [flatListRef.current]);\n\n return (\n <FlatList\n data={items}\n getItemLayout={getItemLayout}\n initialNumToRender={initialNumToRender}\n keyExtractor={keyExtractor}\n onViewableItemsChanged={onViewableItemsChanged.current}\n onScroll={onScroll}\n ref={flatListRef}\n renderItem={renderItem}\n viewabilityConfig={viewabilityConfig}\n windowSize={windowSize}\n ListFooterComponent={ListFooterComponent}\n {...otherProps}\n />\n );\n};"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"names":["STATE","INIT","URL_LOADED","LOADED","FAIL"],"sources":["ComicViewerProps.ts"],"sourcesContent":["import React from 'react';\nimport { ComponentProps } from '@fountain-ui/core';\nimport { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';\n\nexport const STATE = {\n INIT: 'init',\n URL_LOADED: 'url_loaded',\n LOADED: 'loaded',\n FAIL: 'fail',\n} as const;\n\nexport type LoadingState = typeof STATE[keyof typeof STATE];\n\nexport interface ComicViewerItemState{\n /**\n * Comic viewer item sortKey.\n */\n sortKey: number;\n\n /**\n * Content's loading state.\n */\n state: LoadingState;\n\n /***\n * Content's error Info.\n */\n error?: ErrorInfo;\n}\n\nexport interface ErrorInfo {\n /**\n * ComicViewerItemData.sortKey.\n */\n sortKey: number;\n\n /**\n * Number of times an error occurred.\n */\n count: number;\n\n /**\n * Content is Expired: true\n */\n expired: boolean;\n}\n\nexport type ComicViewerItemData<T = {}> = T & {\n /**\n * Image height.\n */\n height: number;\n\n /**\n * Unique value for identifying.\n */\n id: number | undefined;\n\n /**\n * Image sourceUrl for displaying.\n */\n url: string;\n\n /**\n * Image width.\n */\n width: number;\n\n /**\n * SortKey\n */\n sortKey: number;\n\n /**\n * Image expire date.\n */\n expiresAt: string;\n}\n\nexport default interface ComicViewerProps<T> extends ComponentProps <{\n /**\n * Data for render.\n */\n data: ComicViewerItemData<T>[];\n\n /**\n * Delay Time to call the error handler.\n * @default 500\n */\n errorDebounceMillis?: number;\n\n /**\n * How many times retry onError when same item error occur\n * @default 3\n */\n errorRetryCount?: number;\n\n /**\n * How many items to render in the initial batch.\n * @default 1\n */\n initialNumToRender?: number;\n\n /**\n * Start at initialScrollPercentage.\n * If over 100, scroll to end.\n * @default 0\n */\n initialScrollPercentage?: number;\n\n /**\n * The value for FlatList viewabilityConfig.itemVisiblePercentThreshold.\n * @default 0\n */\n itemVisiblePercentThreshold?: number;\n\n /**\n * Comic viewer width.\n */\n viewerWidth: number;\n\n /**\n * The value for FlatList windowSize.\n * @default 3\n */\n windowSize?: number;\n\n /**\n * How many images in one page.\n */\n pageUnit: number;\n\n /**\n * Method for getting next page contents.\n * @param sortKey\n */\n getNextPage?: (sortKey: number) => void;\n\n /**\n * Handling all viewerItem errors at once.\n * @param errors Array of ViewerItems errorInfo.\n */\n onError?: (errors: ErrorInfo[]) => void;\n\n /**\n * Handle scroll event.\n * @param event Scroll event.\n */\n onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;\n\n /**\n * Handle item press event.\n */\n onItemPress?: () => void;\n\n /**\n * Component for comic viewer footer.\n */\n ListFooterComponent?: React.ReactElement;\n}> {}"],"mappings":";;;;;;AAIO,MAAMA,KAAK,GAAG;EACjBC,IAAI,EAAE,MADW;EAEjBC,UAAU,EAAE,YAFK;EAGjBC,MAAM,EAAE,QAHS;EAIjBC,IAAI,EAAE;AAJW,CAAd"}
1
+ {"version":3,"names":["STATE","INIT","URL_LOADED","LOADED","FAIL"],"sources":["ComicViewerProps.ts"],"sourcesContent":["import React from 'react';\nimport { ComponentProps } from '@fountain-ui/core';\nimport { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';\n\nexport const STATE = {\n INIT: 'init',\n URL_LOADED: 'url_loaded',\n LOADED: 'loaded',\n FAIL: 'fail',\n} as const;\n\nexport type LoadingState = typeof STATE[keyof typeof STATE];\n\nexport interface ComicViewerItemState{\n /**\n * Comic viewer item sortKey.\n */\n sortKey: number;\n\n /**\n * Content's loading state.\n */\n state: LoadingState;\n\n /***\n * Content's error Info.\n */\n error?: ErrorInfo;\n}\n\nexport interface ErrorInfo {\n /**\n * ComicViewerItemData.sortKey.\n */\n sortKey: number;\n\n /**\n * Number of times an error occurred.\n */\n count: number;\n\n /**\n * Content is Expired: true\n */\n expired: boolean;\n}\n\nexport type ComicViewerItemData<T = {}> = T & {\n /**\n * Image height.\n */\n height: number;\n\n /**\n * Unique value for identifying.\n */\n id: number | undefined;\n\n /**\n * Image sourceUrl for displaying.\n */\n url: string;\n\n /**\n * Image width.\n */\n width: number;\n\n /**\n * SortKey\n */\n sortKey: number;\n\n /**\n * Image expire date.\n */\n expiresAt: string;\n\n /***\n * Timestamp when get content response\n */\n responseTimestamp: number;\n}\n\nexport default interface ComicViewerProps<T> extends ComponentProps <{\n /**\n * Data for render.\n */\n data: ComicViewerItemData<T>[];\n\n /**\n * Delay Time to call the error handler.\n * @default 500\n */\n errorDebounceMillis?: number;\n\n /**\n * How many times retry onError when same item error occur\n * @default 3\n */\n errorRetryCount?: number;\n\n /**\n * How many items to render in the initial batch.\n * @default 1\n */\n initialNumToRender?: number;\n\n /**\n * Start at initialScrollPercentage.\n * If over 100, scroll to end.\n * @default 0\n */\n initialScrollPercentage?: number;\n\n /**\n * The value for FlatList viewabilityConfig.itemVisiblePercentThreshold.\n * @default 0\n */\n itemVisiblePercentThreshold?: number;\n\n /***\n * Timestamp when get content response\n */\n responseTimestamp: number;\n\n /**\n * Comic viewer width.\n */\n viewerWidth: number;\n\n /**\n * The value for FlatList windowSize.\n * @default 3\n */\n windowSize?: number;\n\n /**\n * How many images in one page.\n */\n pageUnit: number;\n\n /**\n * Method for getting next page contents.\n * @param sortKey\n */\n getNextPage?: (sortKey: number) => void;\n\n /**\n * Handling all viewerItem errors at once.\n * @param errors Array of ViewerItems errorInfo.\n */\n onError?: (errors: ErrorInfo[]) => void;\n\n /**\n * Handle scroll event.\n * @param event Scroll event.\n */\n onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;\n\n /**\n * Handle item press event.\n */\n onItemPress?: () => void;\n\n /**\n * Component for comic viewer footer.\n */\n ListFooterComponent?: React.ReactElement;\n}> {}"],"mappings":";;;;;;AAIO,MAAMA,KAAK,GAAG;EACjBC,IAAI,EAAE,MADW;EAEjBC,UAAU,EAAE,YAFK;EAGjBC,MAAM,EAAE,QAHS;EAIjBC,IAAI,EAAE;AAJW,CAAd"}
@@ -22,21 +22,13 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
22
22
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
23
23
 
24
24
  const useStyles = function () {
25
- const theme = (0, _core.useTheme)();
26
25
  return {
27
26
  root: {
28
27
  display: 'flex',
29
28
  flexDirection: 'row',
30
29
  justifyContent: 'center'
31
30
  },
32
- init: {
33
- backgroundColor: theme.palette.paper.grey
34
- },
35
- failed: {
36
- backgroundColor: theme.palette.paper.grey
37
- },
38
31
  reload: {
39
- backgroundColor: theme.palette.paper.grey,
40
32
  display: 'flex',
41
33
  alignItems: 'center'
42
34
  }
@@ -56,6 +48,7 @@ function ViewerItem(_ref) {
56
48
  itemState,
57
49
  isViewable,
58
50
  sortKey,
51
+ responseTimestamp,
59
52
  url,
60
53
  width,
61
54
  getNextPage,
@@ -70,7 +63,7 @@ function ViewerItem(_ref) {
70
63
  errorCount.current = 0;
71
64
  setIsLoaded(true);
72
65
  onLoaded && onLoaded(sortKey);
73
- }, [sortKey]);
66
+ }, [sortKey, onLoaded]);
74
67
  const handleError = (0, _react.useCallback)(() => {
75
68
  errorCount.current = errorCount.current + 1;
76
69
  const now = new Date();
@@ -81,7 +74,7 @@ function ViewerItem(_ref) {
81
74
  count: errorCount.current,
82
75
  expired
83
76
  });
84
- }, [errorCount.current]);
77
+ }, [errorCount.current, onError]);
85
78
  const onReloadPress = (0, _react.useCallback)(() => {
86
79
  errorCount.current = 1;
87
80
  onError && onError({
@@ -89,7 +82,7 @@ function ViewerItem(_ref) {
89
82
  count: errorCount.current,
90
83
  expired: false
91
84
  });
92
- }, [sortKey]);
85
+ }, [sortKey, onError]);
93
86
  const viewStyle = {
94
87
  width: '100%',
95
88
  height,
@@ -109,14 +102,22 @@ function ViewerItem(_ref) {
109
102
  failed
110
103
  } = props;
111
104
 
112
- if (!(isViewable || isLoaded) || failed || (itemState === null || itemState === void 0 ? void 0 : itemState.state) === _ComicViewerProps.STATE.INIT) {
113
- return /*#__PURE__*/_react.default.createElement(_reactNative.View, {
114
- style: [viewStyle, styles.init]
105
+ if (!(isViewable || isLoaded || failed) || (itemState === null || itemState === void 0 ? void 0 : itemState.state) === _ComicViewerProps.STATE.FAIL || (itemState === null || itemState === void 0 ? void 0 : itemState.state) === _ComicViewerProps.STATE.INIT) {
106
+ return /*#__PURE__*/_react.default.createElement(_reactNative.ImageBackground, {
107
+ source: {
108
+ uri: 'https://ssl.pstatic.net/static/m/comic/im/2012/bg_viewbody.jpg'
109
+ },
110
+ resizeMode: "repeat",
111
+ style: viewStyle
115
112
  });
116
113
  }
117
114
 
118
115
  if (errorCount.current >= errorRetryCount) {
119
- return /*#__PURE__*/_react.default.createElement(_reactNative.View, {
116
+ return /*#__PURE__*/_react.default.createElement(_reactNative.ImageBackground, {
117
+ source: {
118
+ uri: 'https://ssl.pstatic.net/static/m/comic/im/2012/bg_viewbody.jpg'
119
+ },
120
+ resizeMode: "repeat",
120
121
  style: [viewStyle, styles.reload]
121
122
  }, /*#__PURE__*/_react.default.createElement(_core.Spacer, {
122
123
  size: 20
@@ -135,8 +136,14 @@ function ViewerItem(_ref) {
135
136
  }));
136
137
  }
137
138
 
138
- return children;
139
- }, [isViewable, isLoaded, errorCount.current, url, onItemPress]);
139
+ return /*#__PURE__*/_react.default.createElement(_reactNative.ImageBackground, {
140
+ source: {
141
+ uri: 'https://ssl.pstatic.net/static/m/comic/im/2012/bg_viewbody.jpg'
142
+ },
143
+ resizeMode: "repeat",
144
+ style: viewStyle
145
+ }, children);
146
+ }, [isViewable, isLoaded, errorCount.current, itemState === null || itemState === void 0 ? void 0 : itemState.state, responseTimestamp]);
140
147
  (0, _react.useEffect)(() => {
141
148
  if ((itemState === null || itemState === void 0 ? void 0 : itemState.state) === _ComicViewerProps.STATE.INIT) {
142
149
  getNextPage === null || getNextPage === void 0 ? void 0 : getNextPage(sortKey);
@@ -148,6 +155,7 @@ function ViewerItem(_ref) {
148
155
  }, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
149
156
  style: [styles.root, viewStyle]
150
157
  }, /*#__PURE__*/_react.default.createElement(_core.Image, {
158
+ failDependency: [url, expiresAt, responseTimestamp],
151
159
  disableOutline: true,
152
160
  key: sortKey,
153
161
  disableLongClick: true,
@@ -160,19 +168,26 @@ function ViewerItem(_ref) {
160
168
  },
161
169
  style: imageStyle,
162
170
  square: true,
163
- Placeholder: Placeholder
171
+ Placeholder: Placeholder,
172
+ disablePlaceholder: true
164
173
  })));
165
174
  }
166
175
 
167
176
  var _default = /*#__PURE__*/_react.default.memo(ViewerItem, (prevProps, nextProps) => {
168
- var _prevProps$props$item, _nextProps$props$item;
177
+ var _prevProps$props$item, _nextProps$props$item, _prevProps$props$item2;
169
178
 
170
179
  if (prevProps.props.isViewable !== nextProps.props.isViewable) {
171
180
  return false;
172
- }
181
+ } // NO NEED ?
182
+
173
183
 
174
184
  if (prevProps.props.url !== nextProps.props.url) {
175
185
  return false;
186
+ } // NO NEED ?
187
+
188
+
189
+ if (prevProps.props.expiresAt !== nextProps.props.expiresAt) {
190
+ return false;
176
191
  }
177
192
 
178
193
  if (prevProps.props.width !== nextProps.props.width) {
@@ -183,6 +198,10 @@ var _default = /*#__PURE__*/_react.default.memo(ViewerItem, (prevProps, nextProp
183
198
  return false;
184
199
  }
185
200
 
201
+ if (((_prevProps$props$item2 = prevProps.props.itemState) === null || _prevProps$props$item2 === void 0 ? void 0 : _prevProps$props$item2.state) !== _ComicViewerProps.STATE.LOADED && prevProps.props.responseTimestamp !== nextProps.props.responseTimestamp) {
202
+ return false;
203
+ }
204
+
186
205
  return true;
187
206
  });
188
207
 
@@ -1 +1 @@
1
- {"version":3,"names":["useStyles","theme","useTheme","root","display","flexDirection","justifyContent","init","backgroundColor","palette","paper","grey","failed","reload","alignItems","ViewerItem","props","expiresAt","errorRetryCount","height","itemState","isViewable","sortKey","url","width","getNextPage","onError","onLoaded","onItemPress","isLoaded","setIsLoaded","useState","styles","errorCount","useRef","R","defaultTo","error","count","onLoad","useCallback","current","handleError","now","Date","utcNow","getTime","getTimezoneOffset","expired","onReloadPress","viewStyle","Platform","select","web","imageStyle","Placeholder","children","state","STATE","INIT","borderRadius","color","useEffect","uri","React","memo","prevProps","nextProps"],"sources":["ViewerItem.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { Platform, TouchableOpacity, View } from 'react-native';\nimport * as R from 'ramda';\nimport type { PlaceholderProps } from '@fountain-ui/core';\nimport { IconButton, Image, Spacer, useTheme } from '@fountain-ui/core';\nimport { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';\nimport { Restart } from '@fountain-ui/icons';\nimport ComicViewerItemProps from './ComicViewerItemProps';\nimport { STATE } from './ComicViewerProps';\n\ntype PlaceholderStyles = NamedStylesStringUnion<'init' | 'failed' | 'reload' | 'root'>;\n\nconst useStyles: UseStyles<PlaceholderStyles> = function (): PlaceholderStyles {\n const theme = useTheme();\n\n return {\n root: {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'center',\n },\n init: {\n backgroundColor: theme.palette.paper.grey,\n },\n failed: {\n backgroundColor: theme.palette.paper.grey,\n },\n reload: {\n backgroundColor: theme.palette.paper.grey,\n display: 'flex',\n alignItems: 'center',\n },\n };\n};\n\nfunction ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {\n const {\n expiresAt,\n errorRetryCount = 3,\n height,\n itemState,\n isViewable,\n sortKey,\n url,\n width,\n getNextPage,\n onError,\n onLoaded,\n onItemPress,\n } = props;\n\n const [isLoaded, setIsLoaded] = useState(false);\n\n const styles = useStyles();\n\n const errorCount = useRef<number>(R.defaultTo(0)(itemState?.error?.count));\n\n const onLoad = useCallback(() => {\n errorCount.current = 0;\n\n setIsLoaded(true);\n\n onLoaded && onLoaded(sortKey);\n }, [sortKey]);\n\n const handleError = useCallback(() => {\n errorCount.current = errorCount.current + 1;\n\n const now = new Date();\n const utcNow = now.getTime() + (now.getTimezoneOffset() * 60 * 1000);\n const expired = new Date(expiresAt).getTime() <= utcNow;\n\n onError && onError({\n sortKey,\n count: errorCount.current,\n expired,\n });\n }, [errorCount.current]);\n\n const onReloadPress = useCallback(() => {\n errorCount.current = 1;\n\n onError && onError({\n sortKey,\n count: errorCount.current,\n expired: false,\n });\n }, [sortKey]);\n\n const viewStyle = {\n width: '100%',\n height,\n ...Platform.select({\n web: { 'cursor': 'default' },\n }),\n };\n\n const imageStyle = { width, height };\n\n const Placeholder = useCallback((props: PlaceholderProps) => {\n const { children, failed } = props;\n\n if (!(isViewable || isLoaded)\n || failed\n || itemState?.state === STATE.INIT\n ) {\n return <View style={[\n viewStyle,\n styles.init,\n ]}/>;\n }\n\n if (errorCount.current >= errorRetryCount) {\n return <View style={[\n viewStyle,\n styles.reload,\n ]}>\n <Spacer size={20}/>\n\n <IconButton\n children={<Restart fill={'#ffffff'}/>}\n style={{\n width: 48,\n height: 48,\n borderRadius: 24,\n color: '#ffffff',\n backgroundColor: '#767676',\n }}\n onPress={onReloadPress}\n />\n </View>;\n }\n\n return children;\n }, [isViewable, isLoaded, errorCount.current, url, onItemPress]);\n\n useEffect(() => {\n if (itemState?.state === STATE.INIT) {\n getNextPage?.(sortKey);\n }\n }, []);\n\n return (\n <TouchableOpacity\n activeOpacity={1}\n onPress={onItemPress}\n >\n <View\n style={[\n styles.root,\n viewStyle,\n ]}\n >\n <Image\n disableOutline={true}\n key={sortKey}\n disableLongClick={true}\n disableDrag={true}\n onLoad={onLoad}\n onError={handleError}\n loading={'eager'}\n source={{ uri: url }}\n style={imageStyle}\n square={true}\n Placeholder={Placeholder}\n />\n </View>\n </TouchableOpacity>\n );\n}\n\nexport default React.memo(ViewerItem, (prevProps, nextProps) => {\n if (prevProps.props.isViewable !== nextProps.props.isViewable) {\n return false;\n }\n\n if (prevProps.props.url !== nextProps.props.url) {\n return false;\n }\n\n if (prevProps.props.width !== nextProps.props.width) {\n return false;\n }\n\n if (prevProps.props.itemState?.state !== nextProps.props.itemState?.state) {\n return false;\n }\n\n return true;\n});\n"],"mappings":"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"}
1
+ {"version":3,"names":["useStyles","root","display","flexDirection","justifyContent","reload","alignItems","ViewerItem","props","expiresAt","errorRetryCount","height","itemState","isViewable","sortKey","responseTimestamp","url","width","getNextPage","onError","onLoaded","onItemPress","isLoaded","setIsLoaded","useState","styles","errorCount","useRef","R","defaultTo","error","count","onLoad","useCallback","current","handleError","now","Date","utcNow","getTime","getTimezoneOffset","expired","onReloadPress","viewStyle","Platform","select","web","imageStyle","Placeholder","children","failed","state","STATE","FAIL","INIT","uri","borderRadius","color","backgroundColor","useEffect","React","memo","prevProps","nextProps","LOADED"],"sources":["ViewerItem.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { ImageBackground, Platform, TouchableOpacity, View } from 'react-native';\nimport * as R from 'ramda';\nimport type { PlaceholderProps } from '@fountain-ui/core';\nimport { IconButton, Image, Spacer } from '@fountain-ui/core';\nimport { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';\nimport { Restart } from '@fountain-ui/icons';\nimport ComicViewerItemProps from './ComicViewerItemProps';\nimport { STATE } from './ComicViewerProps';\n\ntype PlaceholderStyles = NamedStylesStringUnion<'reload' | 'root'>;\n\nconst useStyles: UseStyles<PlaceholderStyles> = function (): PlaceholderStyles {\n return {\n root: {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'center',\n },\n reload: {\n display: 'flex',\n alignItems: 'center',\n },\n };\n};\n\nfunction ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {\n const {\n expiresAt,\n errorRetryCount = 3,\n height,\n itemState,\n isViewable,\n sortKey,\n responseTimestamp,\n url,\n width,\n getNextPage,\n onError,\n onLoaded,\n onItemPress,\n } = props;\n\n const [isLoaded, setIsLoaded] = useState(false);\n\n const styles = useStyles();\n\n const errorCount = useRef<number>(R.defaultTo(0)(itemState?.error?.count));\n\n const onLoad = useCallback(() => {\n errorCount.current = 0;\n\n setIsLoaded(true);\n\n onLoaded && onLoaded(sortKey);\n }, [sortKey, onLoaded]);\n\n const handleError = useCallback(() => {\n errorCount.current = errorCount.current + 1;\n\n const now = new Date();\n const utcNow = now.getTime() + (now.getTimezoneOffset() * 60 * 1000);\n const expired = new Date(expiresAt).getTime() <= utcNow;\n\n onError && onError({\n sortKey,\n count: errorCount.current,\n expired,\n });\n }, [errorCount.current, onError]);\n\n const onReloadPress = useCallback(() => {\n errorCount.current = 1;\n\n onError && onError({\n sortKey,\n count: errorCount.current,\n expired: false,\n });\n }, [sortKey, onError]);\n\n const viewStyle = {\n width: '100%',\n height,\n ...Platform.select({\n web: { 'cursor': 'default' },\n }),\n };\n\n const imageStyle = { width, height };\n\n const Placeholder = useCallback((props: PlaceholderProps) => {\n const { children, failed } = props;\n\n if (!(isViewable || isLoaded || failed)\n || (itemState?.state === STATE.FAIL)\n || itemState?.state === STATE.INIT\n ) {\n return <ImageBackground\n source={{ uri: 'https://ssl.pstatic.net/static/m/comic/im/2012/bg_viewbody.jpg' }}\n resizeMode=\"repeat\"\n style={viewStyle}\n />;\n }\n\n if (errorCount.current >= errorRetryCount) {\n return <ImageBackground\n source={{ uri: 'https://ssl.pstatic.net/static/m/comic/im/2012/bg_viewbody.jpg' }}\n resizeMode=\"repeat\"\n style={[\n viewStyle,\n styles.reload,\n ]}\n >\n <Spacer size={20}/>\n\n <IconButton\n children={<Restart fill={'#ffffff'}/>}\n style={{\n width: 48,\n height: 48,\n borderRadius: 24,\n color: '#ffffff',\n backgroundColor: '#767676',\n }}\n onPress={onReloadPress}\n />\n </ImageBackground>;\n }\n\n return <ImageBackground\n source={{ uri: 'https://ssl.pstatic.net/static/m/comic/im/2012/bg_viewbody.jpg' }}\n resizeMode=\"repeat\"\n style={viewStyle}\n >\n {children}\n </ImageBackground>;\n }, [isViewable, isLoaded, errorCount.current, itemState?.state, responseTimestamp]);\n\n useEffect(() => {\n if (itemState?.state === STATE.INIT) {\n getNextPage?.(sortKey);\n }\n }, []);\n\n return (\n <TouchableOpacity\n activeOpacity={1}\n onPress={onItemPress}\n >\n <View\n style={[\n styles.root,\n viewStyle,\n ]}\n >\n <Image\n failDependency={[url, expiresAt, responseTimestamp]}\n disableOutline={true}\n key={sortKey}\n disableLongClick={true}\n disableDrag={true}\n onLoad={onLoad}\n onError={handleError}\n loading={'eager'}\n source={{ uri: url }}\n style={imageStyle}\n square={true}\n Placeholder={Placeholder}\n disablePlaceholder={true}\n />\n </View>\n </TouchableOpacity>\n );\n}\n\nexport default React.memo(ViewerItem, (prevProps, nextProps) => {\n if (prevProps.props.isViewable !== nextProps.props.isViewable) {\n return false;\n }\n\n // NO NEED ?\n if (prevProps.props.url !== nextProps.props.url) {\n return false;\n }\n\n // NO NEED ?\n if (prevProps.props.expiresAt !== nextProps.props.expiresAt) {\n return false;\n }\n\n if (prevProps.props.width !== nextProps.props.width) {\n return false;\n }\n\n if (prevProps.props.itemState?.state !== nextProps.props.itemState?.state) {\n return false;\n }\n\n if (prevProps.props.itemState?.state !== STATE.LOADED && prevProps.props.responseTimestamp !== nextProps.props.responseTimestamp) {\n return false;\n }\n\n return true;\n});"],"mappings":"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"}
@@ -19,6 +19,7 @@ export default function ComicViewer(props) {
19
19
  data,
20
20
  errorDebounceMillis = 500,
21
21
  errorRetryCount = 3,
22
+ responseTimestamp,
22
23
  initialNumToRender = 1,
23
24
  initialScrollPercentage = 0,
24
25
  itemVisiblePercentThreshold = 0,
@@ -35,7 +36,6 @@ export default function ComicViewer(props) {
35
36
  const flatListRef = useRef(null);
36
37
  const errors = useRef(new Map());
37
38
  const debounceTimeOut = useRef(null);
38
- const resourceString = R.toString(R.map(itemData => itemData.url)(data));
39
39
  const imageWidth = Math.min(viewerWidth, 720);
40
40
  const initialItems = R.map(itemData => ({ ...itemData,
41
41
  isViewable: false,
@@ -45,7 +45,7 @@ export default function ComicViewer(props) {
45
45
  const [items, setItems] = useState(initialItems);
46
46
  const initialItemState = R.map(itemData => ({
47
47
  sortKey: itemData.sortKey,
48
- state: R.isEmpty(itemData.expiresAt) ? STATE.INIT : STATE.URL_LOADED
48
+ state: R.isNil(itemData.id) ? STATE.INIT : STATE.URL_LOADED
49
49
  }))(data);
50
50
  const itemStates = useRef(initialItemState);
51
51
  const itemHeights = [...getItemHeights(items)];
@@ -142,6 +142,7 @@ export default function ComicViewer(props) {
142
142
  const itemState = R.find(state => state.sortKey === item.sortKey)(itemStates.current);
143
143
  const props = { ...item,
144
144
  itemState,
145
+ responseTimestamp,
145
146
  errorRetryCount,
146
147
  onError: itemErrorHandler,
147
148
  onLoaded: itemLoadedHandler,
@@ -151,14 +152,14 @@ export default function ComicViewer(props) {
151
152
  return /*#__PURE__*/React.createElement(ViewerItem, {
152
153
  props: props
153
154
  });
154
- }, [resourceString, itemErrorHandler, itemLoadedHandler, onItemPress]);
155
+ }, [responseTimestamp, itemErrorHandler, itemLoadedHandler, onItemPress]);
155
156
  useEffect(() => {
156
157
  setItems(prev => {
157
158
  return R.map(prevItem => {
158
159
  const currentData = R.find(currentItemData => prevItem.sortKey === currentItemData.sortKey)(data);
159
160
  const itemState = R.find(state => state.sortKey === (currentData === null || currentData === void 0 ? void 0 : currentData.sortKey))(itemStates.current);
160
161
 
161
- if (currentData && itemState && itemState.state !== STATE.LOADED && currentData.url !== prevItem.url) {
162
+ if (currentData && currentData.id && itemState && itemState.state !== STATE.LOADED) {
162
163
  itemState.state = STATE.URL_LOADED;
163
164
  return { ...prevItem,
164
165
  url: currentData.url,
@@ -170,7 +171,7 @@ export default function ComicViewer(props) {
170
171
  })([...prev]);
171
172
  ;
172
173
  });
173
- }, [resourceString]);
174
+ }, [responseTimestamp]);
174
175
  useEffect(() => {
175
176
  const newItems = R.map(item => ({ ...item,
176
177
  width: imageWidth,
@@ -1 +1 @@
1
- {"version":3,"names":["React","useCallback","useEffect","useMemo","useRef","useState","FlatList","R","STATE","ViewerItem","getItemHeights","items","map","content","height","appender","left","right","getHeightAccum","itemHeights","mapAccum","keyExtractor","item","sortKey","ComicViewer","props","data","errorDebounceMillis","errorRetryCount","initialNumToRender","initialScrollPercentage","itemVisiblePercentThreshold","onError","onScroll","onItemPress","getNextPage","viewerWidth","windowSize","pageUnit","ListFooterComponent","otherProps","flatListRef","errors","Map","debounceTimeOut","resourceString","toString","itemData","url","imageWidth","Math","min","initialItems","isViewable","width","setItems","initialItemState","state","isEmpty","expiresAt","INIT","URL_LOADED","itemStates","itemHeightAccum","viewabilityConfig","getItemLayout","index","offsets","prepend","length","offset","onViewableItemsChanged","viewableItems","prev","viewableItemSortKeys","viewableItem","firstViewableSortKey","head","lastViewableItemSortKey","last","firstItem","lastItem","isNil","frontBoundary","max","backBoundary","viewableItemBoundary","range","newItems","prevItem","includes","itemLoadedHandler","itemState","find","current","LOADED","error","undefined","itemErrorHandler","errorInfo","count","set","FAIL","handleError","errorsArray","Array","from","entries","errorsInfo","key","value","clear","clearTimeout","size","setTimeout","renderItem","onLoaded","currentData","currentItemData","totalHeight","floor","scrollToOffset","animated"],"sources":["ComicViewer.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { FlatList, ListRenderItem, ViewToken } from 'react-native';\nimport * as R from 'ramda';\nimport {\n ComicViewerItemData,\n ComicViewerItemState,\n default as ComicViewerProps,\n ErrorInfo,\n STATE,\n} from './ComicViewerProps';\nimport type ComicViewerItemProps from './ComicViewerItemProps';\nimport ViewerItem from './ViewerItem';\n\nconst getItemHeights = <T, >(items: ComicViewerItemProps<T>[]): number[] => R.map((content: ComicViewerItemProps<T>) => content.height)(items);\nconst appender = (left: number, right: number): [number, number] => [left + right, left + right];\nconst getHeightAccum = (itemHeights: number[]): [number, number[]] => R.mapAccum(appender, 0, itemHeights);\n\nconst keyExtractor = <T, >(item: ComicViewerItemProps<T>) => `${item.sortKey}`;\n\nexport default function ComicViewer<T>(props: ComicViewerProps<T>) {\n const {\n data,\n errorDebounceMillis = 500,\n errorRetryCount = 3,\n initialNumToRender = 1,\n initialScrollPercentage = 0,\n itemVisiblePercentThreshold = 0,\n onError,\n onScroll,\n onItemPress,\n getNextPage,\n viewerWidth,\n windowSize = 3,\n pageUnit,\n ListFooterComponent,\n ...otherProps\n } = props;\n\n const flatListRef = useRef<FlatList>(null);\n\n const errors = useRef<Map<number, ErrorInfo>>(new Map());\n\n const debounceTimeOut = useRef<NodeJS.Timeout | null>(null);\n\n const resourceString = R.toString(R.map((itemData: ComicViewerItemData) => itemData.url)(data));\n\n const imageWidth = Math.min(viewerWidth, 720);\n const initialItems = R.map((itemData: ComicViewerItemData<T>) => ({\n ...itemData,\n isViewable: false,\n width: imageWidth,\n height: (itemData.height * imageWidth) / itemData.width,\n }))(data);\n\n const [items, setItems] = useState<ComicViewerItemProps<T>[]>(initialItems);\n\n const initialItemState: ComicViewerItemState[] = R.map((itemData: ComicViewerItemData<T>) => ({\n sortKey: itemData.sortKey,\n state: R.isEmpty(itemData.expiresAt) ? STATE.INIT : STATE.URL_LOADED,\n }))(data);\n\n const itemStates = useRef<Array<ComicViewerItemState>>(initialItemState);\n\n const itemHeights = [...getItemHeights(items)];\n const itemHeightAccum = getHeightAccum(itemHeights);\n\n const viewabilityConfig = useMemo(() => ({\n itemVisiblePercentThreshold,\n }), [itemVisiblePercentThreshold]);\n\n const getItemLayout = useCallback((data: any, index: number) => {\n const offsets = R.prepend(0, itemHeightAccum[1]);\n\n return {\n length: itemHeights[index],\n offset: offsets[index],\n index,\n };\n }, [itemHeights]);\n\n const onViewableItemsChanged = useRef(({ viewableItems }: {\n viewableItems: Array<ViewToken>,\n }) => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n const viewableItemSortKeys: number[] = R.map((viewableItem: ViewToken) => viewableItem.item.sortKey)(viewableItems);\n const firstViewableSortKey = R.head(viewableItemSortKeys);\n const lastViewableItemSortKey = R.last(viewableItemSortKeys);\n const firstItem = R.head(prev);\n const lastItem = R.last(prev);\n\n if (R.isNil(firstViewableSortKey)\n || R.isNil(lastViewableItemSortKey)\n || R.isNil(firstItem)\n || R.isNil(lastItem)\n ) {\n return prev;\n }\n\n const frontBoundary = R.max(firstItem.sortKey, firstViewableSortKey - 1);\n const backBoundary = R.min(lastItem.sortKey, lastViewableItemSortKey + 1);\n\n const viewableItemBoundary = R.range(frontBoundary, backBoundary + 1);\n const newItems = R.map((prevItem: ComicViewerItemProps<T>) => ({\n ...prevItem,\n isViewable: R.includes(prevItem.sortKey, viewableItemBoundary),\n }))([...prev]);\n\n return newItems;\n });\n });\n\n const itemLoadedHandler = useCallback((sortKey: number) => {\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === sortKey)(itemStates.current);\n\n if (R.isNil(itemState)) {\n return;\n }\n\n itemState.state = STATE.LOADED;\n itemState.error = undefined;\n }, [itemStates]);\n\n const itemErrorHandler = useCallback((errorInfo: ErrorInfo) => {\n const { sortKey, count } = errorInfo;\n\n if (count >= errorRetryCount) {\n return;\n }\n\n errors.current.set(sortKey, errorInfo);\n\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === sortKey)(itemStates.current);\n\n if (R.isNil(itemState)) {\n return;\n }\n\n itemState.state = STATE.FAIL;\n itemState.error = errorInfo;\n\n const handleError = () => {\n const errorsArray = Array.from(errors.current.entries());\n const errorsInfo = R.map(([key, value]: [number, ErrorInfo]) => value)(errorsArray);\n\n onError && onError([...errorsInfo]);\n errors.current.clear();\n };\n\n if (debounceTimeOut.current) {\n clearTimeout(debounceTimeOut.current);\n }\n\n if (errors.current.size === pageUnit) {\n handleError();\n } else {\n debounceTimeOut.current = setTimeout(handleError, errorDebounceMillis);\n }\n }, [errors.current, itemStates]);\n\n const renderItem: ListRenderItem<ComicViewerItemProps<T>> = useCallback(({ item }) => {\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === item.sortKey)(itemStates.current);\n\n const props = {\n ...item,\n itemState,\n errorRetryCount,\n onError: itemErrorHandler,\n onLoaded: itemLoadedHandler,\n onItemPress,\n getNextPage,\n };\n\n return <ViewerItem props={props}/>;\n }, [resourceString, itemErrorHandler, itemLoadedHandler, onItemPress]);\n\n useEffect(() => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n return R.map((prevItem: ComicViewerItemProps<T>) => {\n const currentData: ComicViewerItemData | undefined = R.find((currentItemData: ComicViewerItemData<T>) => prevItem.sortKey === currentItemData.sortKey)(data);\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === currentData?.sortKey)(itemStates.current);\n\n if (currentData\n && itemState\n && itemState.state !== STATE.LOADED\n && (currentData.url !== prevItem.url)) {\n\n itemState.state = STATE.URL_LOADED;\n\n return {\n ...prevItem,\n url: currentData.url,\n expiresAt: currentData.expiresAt,\n };\n }\n\n return prevItem;\n })([...prev]);\n ;\n });\n }, [resourceString]);\n\n useEffect(() => {\n const newItems = R.map((item: ComicViewerItemProps<T>) => ({\n ...item,\n width: imageWidth,\n height: (item.height * imageWidth) / item.width,\n }))(items);\n\n setItems(newItems);\n }, [imageWidth]);\n\n useEffect(() => {\n const totalHeight = itemHeightAccum[0];\n const offset = Math.floor((initialScrollPercentage / 100) * totalHeight);\n\n if (flatListRef.current) {\n flatListRef.current.scrollToOffset({ offset, animated: false });\n }\n }, [flatListRef.current]);\n\n return (\n <FlatList\n data={items}\n getItemLayout={getItemLayout}\n initialNumToRender={initialNumToRender}\n keyExtractor={keyExtractor}\n onViewableItemsChanged={onViewableItemsChanged.current}\n onScroll={onScroll}\n ref={flatListRef}\n renderItem={renderItem}\n viewabilityConfig={viewabilityConfig}\n windowSize={windowSize}\n ListFooterComponent={ListFooterComponent}\n {...otherProps}\n />\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"names":["React","useCallback","useEffect","useMemo","useRef","useState","FlatList","R","STATE","ViewerItem","getItemHeights","items","map","content","height","appender","left","right","getHeightAccum","itemHeights","mapAccum","keyExtractor","item","sortKey","ComicViewer","props","data","errorDebounceMillis","errorRetryCount","responseTimestamp","initialNumToRender","initialScrollPercentage","itemVisiblePercentThreshold","onError","onScroll","onItemPress","getNextPage","viewerWidth","windowSize","pageUnit","ListFooterComponent","otherProps","flatListRef","errors","Map","debounceTimeOut","imageWidth","Math","min","initialItems","itemData","isViewable","width","setItems","initialItemState","state","isNil","id","INIT","URL_LOADED","itemStates","itemHeightAccum","viewabilityConfig","getItemLayout","index","offsets","prepend","length","offset","onViewableItemsChanged","viewableItems","prev","viewableItemSortKeys","viewableItem","firstViewableSortKey","head","lastViewableItemSortKey","last","firstItem","lastItem","frontBoundary","max","backBoundary","viewableItemBoundary","range","newItems","prevItem","includes","itemLoadedHandler","itemState","find","current","LOADED","error","undefined","itemErrorHandler","errorInfo","count","set","FAIL","handleError","errorsArray","Array","from","entries","errorsInfo","key","value","clear","clearTimeout","size","setTimeout","renderItem","onLoaded","currentData","currentItemData","url","expiresAt","totalHeight","floor","scrollToOffset","animated"],"sources":["ComicViewer.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { FlatList, ListRenderItem, ViewToken } from 'react-native';\nimport * as R from 'ramda';\nimport {\n ComicViewerItemData,\n ComicViewerItemState,\n default as ComicViewerProps,\n ErrorInfo,\n STATE,\n} from './ComicViewerProps';\nimport type ComicViewerItemProps from './ComicViewerItemProps';\nimport ViewerItem from './ViewerItem';\n\nconst getItemHeights = <T, >(items: ComicViewerItemProps<T>[]): number[] => R.map((content: ComicViewerItemProps<T>) => content.height)(items);\nconst appender = (left: number, right: number): [number, number] => [left + right, left + right];\nconst getHeightAccum = (itemHeights: number[]): [number, number[]] => R.mapAccum(appender, 0, itemHeights);\n\nconst keyExtractor = <T, >(item: ComicViewerItemProps<T>) => `${item.sortKey}`;\n\nexport default function ComicViewer<T>(props: ComicViewerProps<T>) {\n const {\n data,\n errorDebounceMillis = 500,\n errorRetryCount = 3,\n responseTimestamp,\n initialNumToRender = 1,\n initialScrollPercentage = 0,\n itemVisiblePercentThreshold = 0,\n onError,\n onScroll,\n onItemPress,\n getNextPage,\n viewerWidth,\n windowSize = 3,\n pageUnit,\n ListFooterComponent,\n ...otherProps\n } = props;\n\n const flatListRef = useRef<FlatList>(null);\n\n const errors = useRef<Map<number, ErrorInfo>>(new Map());\n\n const debounceTimeOut = useRef<NodeJS.Timeout | null>(null);\n\n const imageWidth = Math.min(viewerWidth, 720);\n const initialItems = R.map((itemData: ComicViewerItemData<T>) => ({\n ...itemData,\n isViewable: false,\n width: imageWidth,\n height: (itemData.height * imageWidth) / itemData.width,\n }))(data);\n\n const [items, setItems] = useState<ComicViewerItemProps<T>[]>(initialItems);\n\n const initialItemState: ComicViewerItemState[] = R.map((itemData: ComicViewerItemData<T>) => ({\n sortKey: itemData.sortKey,\n state: R.isNil(itemData.id) ? STATE.INIT : STATE.URL_LOADED,\n }))(data);\n\n const itemStates = useRef<Array<ComicViewerItemState>>(initialItemState);\n\n const itemHeights = [...getItemHeights(items)];\n const itemHeightAccum = getHeightAccum(itemHeights);\n\n const viewabilityConfig = useMemo(() => ({\n itemVisiblePercentThreshold,\n }), [itemVisiblePercentThreshold]);\n\n const getItemLayout = useCallback((data: any, index: number) => {\n const offsets = R.prepend(0, itemHeightAccum[1]);\n\n return {\n length: itemHeights[index],\n offset: offsets[index],\n index,\n };\n }, [itemHeights]);\n\n const onViewableItemsChanged = useRef(({ viewableItems }: {\n viewableItems: Array<ViewToken>,\n }) => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n const viewableItemSortKeys: number[] = R.map((viewableItem: ViewToken) => viewableItem.item.sortKey)(viewableItems);\n const firstViewableSortKey = R.head(viewableItemSortKeys);\n const lastViewableItemSortKey = R.last(viewableItemSortKeys);\n const firstItem = R.head(prev);\n const lastItem = R.last(prev);\n\n if (R.isNil(firstViewableSortKey)\n || R.isNil(lastViewableItemSortKey)\n || R.isNil(firstItem)\n || R.isNil(lastItem)\n ) {\n return prev;\n }\n\n const frontBoundary = R.max(firstItem.sortKey, firstViewableSortKey - 1);\n const backBoundary = R.min(lastItem.sortKey, lastViewableItemSortKey + 1);\n\n const viewableItemBoundary = R.range(frontBoundary, backBoundary + 1);\n const newItems = R.map((prevItem: ComicViewerItemProps<T>) => ({\n ...prevItem,\n isViewable: R.includes(prevItem.sortKey, viewableItemBoundary),\n }))([...prev]);\n\n return newItems;\n });\n });\n\n const itemLoadedHandler = useCallback((sortKey: number) => {\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === sortKey)(itemStates.current);\n\n if (R.isNil(itemState)) {\n return;\n }\n\n itemState.state = STATE.LOADED;\n itemState.error = undefined;\n }, [itemStates]);\n\n const itemErrorHandler = useCallback((errorInfo: ErrorInfo) => {\n const { sortKey, count } = errorInfo;\n\n if (count >= errorRetryCount) {\n return;\n }\n\n errors.current.set(sortKey, errorInfo);\n\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === sortKey)(itemStates.current);\n\n if (R.isNil(itemState)) {\n return;\n }\n\n itemState.state = STATE.FAIL;\n itemState.error = errorInfo;\n\n const handleError = () => {\n const errorsArray = Array.from(errors.current.entries());\n const errorsInfo = R.map(([key, value]: [number, ErrorInfo]) => value)(errorsArray);\n\n onError && onError([...errorsInfo]);\n errors.current.clear();\n };\n\n if (debounceTimeOut.current) {\n clearTimeout(debounceTimeOut.current);\n }\n\n if (errors.current.size === pageUnit) {\n handleError();\n } else {\n debounceTimeOut.current = setTimeout(handleError, errorDebounceMillis);\n }\n }, [errors.current, itemStates]);\n\n const renderItem: ListRenderItem<ComicViewerItemProps<T>> = useCallback(({ item }) => {\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === item.sortKey)(itemStates.current);\n\n const props = {\n ...item,\n itemState,\n responseTimestamp,\n errorRetryCount,\n onError: itemErrorHandler,\n onLoaded: itemLoadedHandler,\n onItemPress,\n getNextPage,\n };\n\n return <ViewerItem props={props}/>;\n }, [responseTimestamp, itemErrorHandler, itemLoadedHandler, onItemPress]);\n\n useEffect(() => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n return R.map((prevItem: ComicViewerItemProps<T>) => {\n const currentData: ComicViewerItemData | undefined = R.find((currentItemData: ComicViewerItemData<T>) => prevItem.sortKey === currentItemData.sortKey)(data);\n const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === currentData?.sortKey)(itemStates.current);\n\n if (currentData\n && currentData.id\n && itemState\n && itemState.state !== STATE.LOADED) {\n\n itemState.state = STATE.URL_LOADED;\n\n return {\n ...prevItem,\n url: currentData.url,\n expiresAt: currentData.expiresAt,\n };\n }\n\n return prevItem;\n })([...prev]);\n ;\n });\n }, [responseTimestamp]);\n\n useEffect(() => {\n const newItems = R.map((item: ComicViewerItemProps<T>) => ({\n ...item,\n width: imageWidth,\n height: (item.height * imageWidth) / item.width,\n }))(items);\n\n setItems(newItems);\n }, [imageWidth]);\n\n useEffect(() => {\n const totalHeight = itemHeightAccum[0];\n const offset = Math.floor((initialScrollPercentage / 100) * totalHeight);\n\n if (flatListRef.current) {\n flatListRef.current.scrollToOffset({ offset, animated: false });\n }\n }, [flatListRef.current]);\n\n return (\n <FlatList\n data={items}\n getItemLayout={getItemLayout}\n initialNumToRender={initialNumToRender}\n keyExtractor={keyExtractor}\n onViewableItemsChanged={onViewableItemsChanged.current}\n onScroll={onScroll}\n ref={flatListRef}\n renderItem={renderItem}\n viewabilityConfig={viewabilityConfig}\n windowSize={windowSize}\n ListFooterComponent={ListFooterComponent}\n {...otherProps}\n />\n );\n};"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"names":["STATE","INIT","URL_LOADED","LOADED","FAIL"],"sources":["ComicViewerProps.ts"],"sourcesContent":["import React from 'react';\nimport { ComponentProps } from '@fountain-ui/core';\nimport { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';\n\nexport const STATE = {\n INIT: 'init',\n URL_LOADED: 'url_loaded',\n LOADED: 'loaded',\n FAIL: 'fail',\n} as const;\n\nexport type LoadingState = typeof STATE[keyof typeof STATE];\n\nexport interface ComicViewerItemState{\n /**\n * Comic viewer item sortKey.\n */\n sortKey: number;\n\n /**\n * Content's loading state.\n */\n state: LoadingState;\n\n /***\n * Content's error Info.\n */\n error?: ErrorInfo;\n}\n\nexport interface ErrorInfo {\n /**\n * ComicViewerItemData.sortKey.\n */\n sortKey: number;\n\n /**\n * Number of times an error occurred.\n */\n count: number;\n\n /**\n * Content is Expired: true\n */\n expired: boolean;\n}\n\nexport type ComicViewerItemData<T = {}> = T & {\n /**\n * Image height.\n */\n height: number;\n\n /**\n * Unique value for identifying.\n */\n id: number | undefined;\n\n /**\n * Image sourceUrl for displaying.\n */\n url: string;\n\n /**\n * Image width.\n */\n width: number;\n\n /**\n * SortKey\n */\n sortKey: number;\n\n /**\n * Image expire date.\n */\n expiresAt: string;\n}\n\nexport default interface ComicViewerProps<T> extends ComponentProps <{\n /**\n * Data for render.\n */\n data: ComicViewerItemData<T>[];\n\n /**\n * Delay Time to call the error handler.\n * @default 500\n */\n errorDebounceMillis?: number;\n\n /**\n * How many times retry onError when same item error occur\n * @default 3\n */\n errorRetryCount?: number;\n\n /**\n * How many items to render in the initial batch.\n * @default 1\n */\n initialNumToRender?: number;\n\n /**\n * Start at initialScrollPercentage.\n * If over 100, scroll to end.\n * @default 0\n */\n initialScrollPercentage?: number;\n\n /**\n * The value for FlatList viewabilityConfig.itemVisiblePercentThreshold.\n * @default 0\n */\n itemVisiblePercentThreshold?: number;\n\n /**\n * Comic viewer width.\n */\n viewerWidth: number;\n\n /**\n * The value for FlatList windowSize.\n * @default 3\n */\n windowSize?: number;\n\n /**\n * How many images in one page.\n */\n pageUnit: number;\n\n /**\n * Method for getting next page contents.\n * @param sortKey\n */\n getNextPage?: (sortKey: number) => void;\n\n /**\n * Handling all viewerItem errors at once.\n * @param errors Array of ViewerItems errorInfo.\n */\n onError?: (errors: ErrorInfo[]) => void;\n\n /**\n * Handle scroll event.\n * @param event Scroll event.\n */\n onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;\n\n /**\n * Handle item press event.\n */\n onItemPress?: () => void;\n\n /**\n * Component for comic viewer footer.\n */\n ListFooterComponent?: React.ReactElement;\n}> {}"],"mappings":"AAIA,OAAO,MAAMA,KAAK,GAAG;EACjBC,IAAI,EAAE,MADW;EAEjBC,UAAU,EAAE,YAFK;EAGjBC,MAAM,EAAE,QAHS;EAIjBC,IAAI,EAAE;AAJW,CAAd"}
1
+ {"version":3,"names":["STATE","INIT","URL_LOADED","LOADED","FAIL"],"sources":["ComicViewerProps.ts"],"sourcesContent":["import React from 'react';\nimport { ComponentProps } from '@fountain-ui/core';\nimport { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';\n\nexport const STATE = {\n INIT: 'init',\n URL_LOADED: 'url_loaded',\n LOADED: 'loaded',\n FAIL: 'fail',\n} as const;\n\nexport type LoadingState = typeof STATE[keyof typeof STATE];\n\nexport interface ComicViewerItemState{\n /**\n * Comic viewer item sortKey.\n */\n sortKey: number;\n\n /**\n * Content's loading state.\n */\n state: LoadingState;\n\n /***\n * Content's error Info.\n */\n error?: ErrorInfo;\n}\n\nexport interface ErrorInfo {\n /**\n * ComicViewerItemData.sortKey.\n */\n sortKey: number;\n\n /**\n * Number of times an error occurred.\n */\n count: number;\n\n /**\n * Content is Expired: true\n */\n expired: boolean;\n}\n\nexport type ComicViewerItemData<T = {}> = T & {\n /**\n * Image height.\n */\n height: number;\n\n /**\n * Unique value for identifying.\n */\n id: number | undefined;\n\n /**\n * Image sourceUrl for displaying.\n */\n url: string;\n\n /**\n * Image width.\n */\n width: number;\n\n /**\n * SortKey\n */\n sortKey: number;\n\n /**\n * Image expire date.\n */\n expiresAt: string;\n\n /***\n * Timestamp when get content response\n */\n responseTimestamp: number;\n}\n\nexport default interface ComicViewerProps<T> extends ComponentProps <{\n /**\n * Data for render.\n */\n data: ComicViewerItemData<T>[];\n\n /**\n * Delay Time to call the error handler.\n * @default 500\n */\n errorDebounceMillis?: number;\n\n /**\n * How many times retry onError when same item error occur\n * @default 3\n */\n errorRetryCount?: number;\n\n /**\n * How many items to render in the initial batch.\n * @default 1\n */\n initialNumToRender?: number;\n\n /**\n * Start at initialScrollPercentage.\n * If over 100, scroll to end.\n * @default 0\n */\n initialScrollPercentage?: number;\n\n /**\n * The value for FlatList viewabilityConfig.itemVisiblePercentThreshold.\n * @default 0\n */\n itemVisiblePercentThreshold?: number;\n\n /***\n * Timestamp when get content response\n */\n responseTimestamp: number;\n\n /**\n * Comic viewer width.\n */\n viewerWidth: number;\n\n /**\n * The value for FlatList windowSize.\n * @default 3\n */\n windowSize?: number;\n\n /**\n * How many images in one page.\n */\n pageUnit: number;\n\n /**\n * Method for getting next page contents.\n * @param sortKey\n */\n getNextPage?: (sortKey: number) => void;\n\n /**\n * Handling all viewerItem errors at once.\n * @param errors Array of ViewerItems errorInfo.\n */\n onError?: (errors: ErrorInfo[]) => void;\n\n /**\n * Handle scroll event.\n * @param event Scroll event.\n */\n onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;\n\n /**\n * Handle item press event.\n */\n onItemPress?: () => void;\n\n /**\n * Component for comic viewer footer.\n */\n ListFooterComponent?: React.ReactElement;\n}> {}"],"mappings":"AAIA,OAAO,MAAMA,KAAK,GAAG;EACjBC,IAAI,EAAE,MADW;EAEjBC,UAAU,EAAE,YAFK;EAGjBC,MAAM,EAAE,QAHS;EAIjBC,IAAI,EAAE;AAJW,CAAd"}
@@ -1,26 +1,18 @@
1
1
  import React, { useCallback, useEffect, useRef, useState } from 'react';
2
- import { Platform, TouchableOpacity, View } from 'react-native';
2
+ import { ImageBackground, Platform, TouchableOpacity, View } from 'react-native';
3
3
  import * as R from 'ramda';
4
- import { IconButton, Image, Spacer, useTheme } from '@fountain-ui/core';
4
+ import { IconButton, Image, Spacer } from '@fountain-ui/core';
5
5
  import { Restart } from '@fountain-ui/icons';
6
6
  import { STATE } from './ComicViewerProps';
7
7
 
8
8
  const useStyles = function () {
9
- const theme = useTheme();
10
9
  return {
11
10
  root: {
12
11
  display: 'flex',
13
12
  flexDirection: 'row',
14
13
  justifyContent: 'center'
15
14
  },
16
- init: {
17
- backgroundColor: theme.palette.paper.grey
18
- },
19
- failed: {
20
- backgroundColor: theme.palette.paper.grey
21
- },
22
15
  reload: {
23
- backgroundColor: theme.palette.paper.grey,
24
16
  display: 'flex',
25
17
  alignItems: 'center'
26
18
  }
@@ -40,6 +32,7 @@ function ViewerItem(_ref) {
40
32
  itemState,
41
33
  isViewable,
42
34
  sortKey,
35
+ responseTimestamp,
43
36
  url,
44
37
  width,
45
38
  getNextPage,
@@ -54,7 +47,7 @@ function ViewerItem(_ref) {
54
47
  errorCount.current = 0;
55
48
  setIsLoaded(true);
56
49
  onLoaded && onLoaded(sortKey);
57
- }, [sortKey]);
50
+ }, [sortKey, onLoaded]);
58
51
  const handleError = useCallback(() => {
59
52
  errorCount.current = errorCount.current + 1;
60
53
  const now = new Date();
@@ -65,7 +58,7 @@ function ViewerItem(_ref) {
65
58
  count: errorCount.current,
66
59
  expired
67
60
  });
68
- }, [errorCount.current]);
61
+ }, [errorCount.current, onError]);
69
62
  const onReloadPress = useCallback(() => {
70
63
  errorCount.current = 1;
71
64
  onError && onError({
@@ -73,7 +66,7 @@ function ViewerItem(_ref) {
73
66
  count: errorCount.current,
74
67
  expired: false
75
68
  });
76
- }, [sortKey]);
69
+ }, [sortKey, onError]);
77
70
  const viewStyle = {
78
71
  width: '100%',
79
72
  height,
@@ -93,14 +86,22 @@ function ViewerItem(_ref) {
93
86
  failed
94
87
  } = props;
95
88
 
96
- if (!(isViewable || isLoaded) || failed || (itemState === null || itemState === void 0 ? void 0 : itemState.state) === STATE.INIT) {
97
- return /*#__PURE__*/React.createElement(View, {
98
- style: [viewStyle, styles.init]
89
+ if (!(isViewable || isLoaded || failed) || (itemState === null || itemState === void 0 ? void 0 : itemState.state) === STATE.FAIL || (itemState === null || itemState === void 0 ? void 0 : itemState.state) === STATE.INIT) {
90
+ return /*#__PURE__*/React.createElement(ImageBackground, {
91
+ source: {
92
+ uri: 'https://ssl.pstatic.net/static/m/comic/im/2012/bg_viewbody.jpg'
93
+ },
94
+ resizeMode: "repeat",
95
+ style: viewStyle
99
96
  });
100
97
  }
101
98
 
102
99
  if (errorCount.current >= errorRetryCount) {
103
- return /*#__PURE__*/React.createElement(View, {
100
+ return /*#__PURE__*/React.createElement(ImageBackground, {
101
+ source: {
102
+ uri: 'https://ssl.pstatic.net/static/m/comic/im/2012/bg_viewbody.jpg'
103
+ },
104
+ resizeMode: "repeat",
104
105
  style: [viewStyle, styles.reload]
105
106
  }, /*#__PURE__*/React.createElement(Spacer, {
106
107
  size: 20
@@ -119,8 +120,14 @@ function ViewerItem(_ref) {
119
120
  }));
120
121
  }
121
122
 
122
- return children;
123
- }, [isViewable, isLoaded, errorCount.current, url, onItemPress]);
123
+ return /*#__PURE__*/React.createElement(ImageBackground, {
124
+ source: {
125
+ uri: 'https://ssl.pstatic.net/static/m/comic/im/2012/bg_viewbody.jpg'
126
+ },
127
+ resizeMode: "repeat",
128
+ style: viewStyle
129
+ }, children);
130
+ }, [isViewable, isLoaded, errorCount.current, itemState === null || itemState === void 0 ? void 0 : itemState.state, responseTimestamp]);
124
131
  useEffect(() => {
125
132
  if ((itemState === null || itemState === void 0 ? void 0 : itemState.state) === STATE.INIT) {
126
133
  getNextPage === null || getNextPage === void 0 ? void 0 : getNextPage(sortKey);
@@ -132,6 +139,7 @@ function ViewerItem(_ref) {
132
139
  }, /*#__PURE__*/React.createElement(View, {
133
140
  style: [styles.root, viewStyle]
134
141
  }, /*#__PURE__*/React.createElement(Image, {
142
+ failDependency: [url, expiresAt, responseTimestamp],
135
143
  disableOutline: true,
136
144
  key: sortKey,
137
145
  disableLongClick: true,
@@ -144,19 +152,26 @@ function ViewerItem(_ref) {
144
152
  },
145
153
  style: imageStyle,
146
154
  square: true,
147
- Placeholder: Placeholder
155
+ Placeholder: Placeholder,
156
+ disablePlaceholder: true
148
157
  })));
149
158
  }
150
159
 
151
160
  export default /*#__PURE__*/React.memo(ViewerItem, (prevProps, nextProps) => {
152
- var _prevProps$props$item, _nextProps$props$item;
161
+ var _prevProps$props$item, _nextProps$props$item, _prevProps$props$item2;
153
162
 
154
163
  if (prevProps.props.isViewable !== nextProps.props.isViewable) {
155
164
  return false;
156
- }
165
+ } // NO NEED ?
166
+
157
167
 
158
168
  if (prevProps.props.url !== nextProps.props.url) {
159
169
  return false;
170
+ } // NO NEED ?
171
+
172
+
173
+ if (prevProps.props.expiresAt !== nextProps.props.expiresAt) {
174
+ return false;
160
175
  }
161
176
 
162
177
  if (prevProps.props.width !== nextProps.props.width) {
@@ -167,6 +182,10 @@ export default /*#__PURE__*/React.memo(ViewerItem, (prevProps, nextProps) => {
167
182
  return false;
168
183
  }
169
184
 
185
+ if (((_prevProps$props$item2 = prevProps.props.itemState) === null || _prevProps$props$item2 === void 0 ? void 0 : _prevProps$props$item2.state) !== STATE.LOADED && prevProps.props.responseTimestamp !== nextProps.props.responseTimestamp) {
186
+ return false;
187
+ }
188
+
170
189
  return true;
171
190
  });
172
191
  //# sourceMappingURL=ViewerItem.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["React","useCallback","useEffect","useRef","useState","Platform","TouchableOpacity","View","R","IconButton","Image","Spacer","useTheme","Restart","STATE","useStyles","theme","root","display","flexDirection","justifyContent","init","backgroundColor","palette","paper","grey","failed","reload","alignItems","ViewerItem","props","expiresAt","errorRetryCount","height","itemState","isViewable","sortKey","url","width","getNextPage","onError","onLoaded","onItemPress","isLoaded","setIsLoaded","styles","errorCount","defaultTo","error","count","onLoad","current","handleError","now","Date","utcNow","getTime","getTimezoneOffset","expired","onReloadPress","viewStyle","select","web","imageStyle","Placeholder","children","state","INIT","borderRadius","color","uri","memo","prevProps","nextProps"],"sources":["ViewerItem.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { Platform, TouchableOpacity, View } from 'react-native';\nimport * as R from 'ramda';\nimport type { PlaceholderProps } from '@fountain-ui/core';\nimport { IconButton, Image, Spacer, useTheme } from '@fountain-ui/core';\nimport { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';\nimport { Restart } from '@fountain-ui/icons';\nimport ComicViewerItemProps from './ComicViewerItemProps';\nimport { STATE } from './ComicViewerProps';\n\ntype PlaceholderStyles = NamedStylesStringUnion<'init' | 'failed' | 'reload' | 'root'>;\n\nconst useStyles: UseStyles<PlaceholderStyles> = function (): PlaceholderStyles {\n const theme = useTheme();\n\n return {\n root: {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'center',\n },\n init: {\n backgroundColor: theme.palette.paper.grey,\n },\n failed: {\n backgroundColor: theme.palette.paper.grey,\n },\n reload: {\n backgroundColor: theme.palette.paper.grey,\n display: 'flex',\n alignItems: 'center',\n },\n };\n};\n\nfunction ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {\n const {\n expiresAt,\n errorRetryCount = 3,\n height,\n itemState,\n isViewable,\n sortKey,\n url,\n width,\n getNextPage,\n onError,\n onLoaded,\n onItemPress,\n } = props;\n\n const [isLoaded, setIsLoaded] = useState(false);\n\n const styles = useStyles();\n\n const errorCount = useRef<number>(R.defaultTo(0)(itemState?.error?.count));\n\n const onLoad = useCallback(() => {\n errorCount.current = 0;\n\n setIsLoaded(true);\n\n onLoaded && onLoaded(sortKey);\n }, [sortKey]);\n\n const handleError = useCallback(() => {\n errorCount.current = errorCount.current + 1;\n\n const now = new Date();\n const utcNow = now.getTime() + (now.getTimezoneOffset() * 60 * 1000);\n const expired = new Date(expiresAt).getTime() <= utcNow;\n\n onError && onError({\n sortKey,\n count: errorCount.current,\n expired,\n });\n }, [errorCount.current]);\n\n const onReloadPress = useCallback(() => {\n errorCount.current = 1;\n\n onError && onError({\n sortKey,\n count: errorCount.current,\n expired: false,\n });\n }, [sortKey]);\n\n const viewStyle = {\n width: '100%',\n height,\n ...Platform.select({\n web: { 'cursor': 'default' },\n }),\n };\n\n const imageStyle = { width, height };\n\n const Placeholder = useCallback((props: PlaceholderProps) => {\n const { children, failed } = props;\n\n if (!(isViewable || isLoaded)\n || failed\n || itemState?.state === STATE.INIT\n ) {\n return <View style={[\n viewStyle,\n styles.init,\n ]}/>;\n }\n\n if (errorCount.current >= errorRetryCount) {\n return <View style={[\n viewStyle,\n styles.reload,\n ]}>\n <Spacer size={20}/>\n\n <IconButton\n children={<Restart fill={'#ffffff'}/>}\n style={{\n width: 48,\n height: 48,\n borderRadius: 24,\n color: '#ffffff',\n backgroundColor: '#767676',\n }}\n onPress={onReloadPress}\n />\n </View>;\n }\n\n return children;\n }, [isViewable, isLoaded, errorCount.current, url, onItemPress]);\n\n useEffect(() => {\n if (itemState?.state === STATE.INIT) {\n getNextPage?.(sortKey);\n }\n }, []);\n\n return (\n <TouchableOpacity\n activeOpacity={1}\n onPress={onItemPress}\n >\n <View\n style={[\n styles.root,\n viewStyle,\n ]}\n >\n <Image\n disableOutline={true}\n key={sortKey}\n disableLongClick={true}\n disableDrag={true}\n onLoad={onLoad}\n onError={handleError}\n loading={'eager'}\n source={{ uri: url }}\n style={imageStyle}\n square={true}\n Placeholder={Placeholder}\n />\n </View>\n </TouchableOpacity>\n );\n}\n\nexport default React.memo(ViewerItem, (prevProps, nextProps) => {\n if (prevProps.props.isViewable !== nextProps.props.isViewable) {\n return false;\n }\n\n if (prevProps.props.url !== nextProps.props.url) {\n return false;\n }\n\n if (prevProps.props.width !== nextProps.props.width) {\n return false;\n }\n\n if (prevProps.props.itemState?.state !== nextProps.props.itemState?.state) {\n return false;\n }\n\n return true;\n});\n"],"mappings":"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"}
1
+ {"version":3,"names":["React","useCallback","useEffect","useRef","useState","ImageBackground","Platform","TouchableOpacity","View","R","IconButton","Image","Spacer","Restart","STATE","useStyles","root","display","flexDirection","justifyContent","reload","alignItems","ViewerItem","props","expiresAt","errorRetryCount","height","itemState","isViewable","sortKey","responseTimestamp","url","width","getNextPage","onError","onLoaded","onItemPress","isLoaded","setIsLoaded","styles","errorCount","defaultTo","error","count","onLoad","current","handleError","now","Date","utcNow","getTime","getTimezoneOffset","expired","onReloadPress","viewStyle","select","web","imageStyle","Placeholder","children","failed","state","FAIL","INIT","uri","borderRadius","color","backgroundColor","memo","prevProps","nextProps","LOADED"],"sources":["ViewerItem.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { ImageBackground, Platform, TouchableOpacity, View } from 'react-native';\nimport * as R from 'ramda';\nimport type { PlaceholderProps } from '@fountain-ui/core';\nimport { IconButton, Image, Spacer } from '@fountain-ui/core';\nimport { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';\nimport { Restart } from '@fountain-ui/icons';\nimport ComicViewerItemProps from './ComicViewerItemProps';\nimport { STATE } from './ComicViewerProps';\n\ntype PlaceholderStyles = NamedStylesStringUnion<'reload' | 'root'>;\n\nconst useStyles: UseStyles<PlaceholderStyles> = function (): PlaceholderStyles {\n return {\n root: {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'center',\n },\n reload: {\n display: 'flex',\n alignItems: 'center',\n },\n };\n};\n\nfunction ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {\n const {\n expiresAt,\n errorRetryCount = 3,\n height,\n itemState,\n isViewable,\n sortKey,\n responseTimestamp,\n url,\n width,\n getNextPage,\n onError,\n onLoaded,\n onItemPress,\n } = props;\n\n const [isLoaded, setIsLoaded] = useState(false);\n\n const styles = useStyles();\n\n const errorCount = useRef<number>(R.defaultTo(0)(itemState?.error?.count));\n\n const onLoad = useCallback(() => {\n errorCount.current = 0;\n\n setIsLoaded(true);\n\n onLoaded && onLoaded(sortKey);\n }, [sortKey, onLoaded]);\n\n const handleError = useCallback(() => {\n errorCount.current = errorCount.current + 1;\n\n const now = new Date();\n const utcNow = now.getTime() + (now.getTimezoneOffset() * 60 * 1000);\n const expired = new Date(expiresAt).getTime() <= utcNow;\n\n onError && onError({\n sortKey,\n count: errorCount.current,\n expired,\n });\n }, [errorCount.current, onError]);\n\n const onReloadPress = useCallback(() => {\n errorCount.current = 1;\n\n onError && onError({\n sortKey,\n count: errorCount.current,\n expired: false,\n });\n }, [sortKey, onError]);\n\n const viewStyle = {\n width: '100%',\n height,\n ...Platform.select({\n web: { 'cursor': 'default' },\n }),\n };\n\n const imageStyle = { width, height };\n\n const Placeholder = useCallback((props: PlaceholderProps) => {\n const { children, failed } = props;\n\n if (!(isViewable || isLoaded || failed)\n || (itemState?.state === STATE.FAIL)\n || itemState?.state === STATE.INIT\n ) {\n return <ImageBackground\n source={{ uri: 'https://ssl.pstatic.net/static/m/comic/im/2012/bg_viewbody.jpg' }}\n resizeMode=\"repeat\"\n style={viewStyle}\n />;\n }\n\n if (errorCount.current >= errorRetryCount) {\n return <ImageBackground\n source={{ uri: 'https://ssl.pstatic.net/static/m/comic/im/2012/bg_viewbody.jpg' }}\n resizeMode=\"repeat\"\n style={[\n viewStyle,\n styles.reload,\n ]}\n >\n <Spacer size={20}/>\n\n <IconButton\n children={<Restart fill={'#ffffff'}/>}\n style={{\n width: 48,\n height: 48,\n borderRadius: 24,\n color: '#ffffff',\n backgroundColor: '#767676',\n }}\n onPress={onReloadPress}\n />\n </ImageBackground>;\n }\n\n return <ImageBackground\n source={{ uri: 'https://ssl.pstatic.net/static/m/comic/im/2012/bg_viewbody.jpg' }}\n resizeMode=\"repeat\"\n style={viewStyle}\n >\n {children}\n </ImageBackground>;\n }, [isViewable, isLoaded, errorCount.current, itemState?.state, responseTimestamp]);\n\n useEffect(() => {\n if (itemState?.state === STATE.INIT) {\n getNextPage?.(sortKey);\n }\n }, []);\n\n return (\n <TouchableOpacity\n activeOpacity={1}\n onPress={onItemPress}\n >\n <View\n style={[\n styles.root,\n viewStyle,\n ]}\n >\n <Image\n failDependency={[url, expiresAt, responseTimestamp]}\n disableOutline={true}\n key={sortKey}\n disableLongClick={true}\n disableDrag={true}\n onLoad={onLoad}\n onError={handleError}\n loading={'eager'}\n source={{ uri: url }}\n style={imageStyle}\n square={true}\n Placeholder={Placeholder}\n disablePlaceholder={true}\n />\n </View>\n </TouchableOpacity>\n );\n}\n\nexport default React.memo(ViewerItem, (prevProps, nextProps) => {\n if (prevProps.props.isViewable !== nextProps.props.isViewable) {\n return false;\n }\n\n // NO NEED ?\n if (prevProps.props.url !== nextProps.props.url) {\n return false;\n }\n\n // NO NEED ?\n if (prevProps.props.expiresAt !== nextProps.props.expiresAt) {\n return false;\n }\n\n if (prevProps.props.width !== nextProps.props.width) {\n return false;\n }\n\n if (prevProps.props.itemState?.state !== nextProps.props.itemState?.state) {\n return false;\n }\n\n if (prevProps.props.itemState?.state !== STATE.LOADED && prevProps.props.responseTimestamp !== nextProps.props.responseTimestamp) {\n return false;\n }\n\n return true;\n});"],"mappings":"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"}
@@ -61,6 +61,10 @@ export declare type ComicViewerItemData<T = {}> = T & {
61
61
  * Image expire date.
62
62
  */
63
63
  expiresAt: string;
64
+ /***
65
+ * Timestamp when get content response
66
+ */
67
+ responseTimestamp: number;
64
68
  };
65
69
  export default interface ComicViewerProps<T> extends ComponentProps<{
66
70
  /**
@@ -93,6 +97,10 @@ export default interface ComicViewerProps<T> extends ComponentProps<{
93
97
  * @default 0
94
98
  */
95
99
  itemVisiblePercentThreshold?: number;
100
+ /***
101
+ * Timestamp when get content response
102
+ */
103
+ responseTimestamp: number;
96
104
  /**
97
105
  * Comic viewer width.
98
106
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fountain-ui/lab",
3
- "version": "2.0.0-beta.33",
3
+ "version": "2.0.0-beta.34",
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": "2c156aa34207beb3efdf1d1293b8b04269b9fd8a"
73
+ "gitHead": "44aa49c39c8a9f0986b9d12e06a8a2cfc3766ed9"
74
74
  }
@@ -22,6 +22,7 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
22
22
  data,
23
23
  errorDebounceMillis = 500,
24
24
  errorRetryCount = 3,
25
+ responseTimestamp,
25
26
  initialNumToRender = 1,
26
27
  initialScrollPercentage = 0,
27
28
  itemVisiblePercentThreshold = 0,
@@ -42,8 +43,6 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
42
43
 
43
44
  const debounceTimeOut = useRef<NodeJS.Timeout | null>(null);
44
45
 
45
- const resourceString = R.toString(R.map((itemData: ComicViewerItemData) => itemData.url)(data));
46
-
47
46
  const imageWidth = Math.min(viewerWidth, 720);
48
47
  const initialItems = R.map((itemData: ComicViewerItemData<T>) => ({
49
48
  ...itemData,
@@ -55,9 +54,9 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
55
54
  const [items, setItems] = useState<ComicViewerItemProps<T>[]>(initialItems);
56
55
 
57
56
  const initialItemState: ComicViewerItemState[] = R.map((itemData: ComicViewerItemData<T>) => ({
58
- sortKey: itemData.sortKey,
59
- state: R.isEmpty(itemData.expiresAt) ? STATE.INIT : STATE.URL_LOADED,
60
- }))(data);
57
+ sortKey: itemData.sortKey,
58
+ state: R.isNil(itemData.id) ? STATE.INIT : STATE.URL_LOADED,
59
+ }))(data);
61
60
 
62
61
  const itemStates = useRef<Array<ComicViewerItemState>>(initialItemState);
63
62
 
@@ -163,6 +162,7 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
163
162
  const props = {
164
163
  ...item,
165
164
  itemState,
165
+ responseTimestamp,
166
166
  errorRetryCount,
167
167
  onError: itemErrorHandler,
168
168
  onLoaded: itemLoadedHandler,
@@ -171,7 +171,7 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
171
171
  };
172
172
 
173
173
  return <ViewerItem props={props}/>;
174
- }, [resourceString, itemErrorHandler, itemLoadedHandler, onItemPress]);
174
+ }, [responseTimestamp, itemErrorHandler, itemLoadedHandler, onItemPress]);
175
175
 
176
176
  useEffect(() => {
177
177
  setItems((prev: ComicViewerItemProps<T>[]) => {
@@ -180,9 +180,9 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
180
180
  const itemState: ComicViewerItemState | undefined = R.find((state: ComicViewerItemState) => state.sortKey === currentData?.sortKey)(itemStates.current);
181
181
 
182
182
  if (currentData
183
+ && currentData.id
183
184
  && itemState
184
- && itemState.state !== STATE.LOADED
185
- && (currentData.url !== prevItem.url)) {
185
+ && itemState.state !== STATE.LOADED) {
186
186
 
187
187
  itemState.state = STATE.URL_LOADED;
188
188
 
@@ -197,7 +197,7 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
197
197
  })([...prev]);
198
198
  ;
199
199
  });
200
- }, [resourceString]);
200
+ }, [responseTimestamp]);
201
201
 
202
202
  useEffect(() => {
203
203
  const newItems = R.map((item: ComicViewerItemProps<T>) => ({
@@ -234,4 +234,4 @@ export default function ComicViewer<T>(props: ComicViewerProps<T>) {
234
234
  {...otherProps}
235
235
  />
236
236
  );
237
- };
237
+ };
@@ -75,6 +75,11 @@ export type ComicViewerItemData<T = {}> = T & {
75
75
  * Image expire date.
76
76
  */
77
77
  expiresAt: string;
78
+
79
+ /***
80
+ * Timestamp when get content response
81
+ */
82
+ responseTimestamp: number;
78
83
  }
79
84
 
80
85
  export default interface ComicViewerProps<T> extends ComponentProps <{
@@ -114,6 +119,11 @@ export default interface ComicViewerProps<T> extends ComponentProps <{
114
119
  */
115
120
  itemVisiblePercentThreshold?: number;
116
121
 
122
+ /***
123
+ * Timestamp when get content response
124
+ */
125
+ responseTimestamp: number;
126
+
117
127
  /**
118
128
  * Comic viewer width.
119
129
  */
@@ -1,32 +1,23 @@
1
1
  import React, { useCallback, useEffect, useRef, useState } from 'react';
2
- import { Platform, TouchableOpacity, View } from 'react-native';
2
+ import { ImageBackground, Platform, TouchableOpacity, View } from 'react-native';
3
3
  import * as R from 'ramda';
4
4
  import type { PlaceholderProps } from '@fountain-ui/core';
5
- import { IconButton, Image, Spacer, useTheme } from '@fountain-ui/core';
5
+ import { IconButton, Image, Spacer } from '@fountain-ui/core';
6
6
  import { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';
7
7
  import { Restart } from '@fountain-ui/icons';
8
8
  import ComicViewerItemProps from './ComicViewerItemProps';
9
9
  import { STATE } from './ComicViewerProps';
10
10
 
11
- type PlaceholderStyles = NamedStylesStringUnion<'init' | 'failed' | 'reload' | 'root'>;
11
+ type PlaceholderStyles = NamedStylesStringUnion<'reload' | 'root'>;
12
12
 
13
13
  const useStyles: UseStyles<PlaceholderStyles> = function (): PlaceholderStyles {
14
- const theme = useTheme();
15
-
16
14
  return {
17
15
  root: {
18
16
  display: 'flex',
19
17
  flexDirection: 'row',
20
18
  justifyContent: 'center',
21
19
  },
22
- init: {
23
- backgroundColor: theme.palette.paper.grey,
24
- },
25
- failed: {
26
- backgroundColor: theme.palette.paper.grey,
27
- },
28
20
  reload: {
29
- backgroundColor: theme.palette.paper.grey,
30
21
  display: 'flex',
31
22
  alignItems: 'center',
32
23
  },
@@ -41,6 +32,7 @@ function ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {
41
32
  itemState,
42
33
  isViewable,
43
34
  sortKey,
35
+ responseTimestamp,
44
36
  url,
45
37
  width,
46
38
  getNextPage,
@@ -61,7 +53,7 @@ function ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {
61
53
  setIsLoaded(true);
62
54
 
63
55
  onLoaded && onLoaded(sortKey);
64
- }, [sortKey]);
56
+ }, [sortKey, onLoaded]);
65
57
 
66
58
  const handleError = useCallback(() => {
67
59
  errorCount.current = errorCount.current + 1;
@@ -75,7 +67,7 @@ function ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {
75
67
  count: errorCount.current,
76
68
  expired,
77
69
  });
78
- }, [errorCount.current]);
70
+ }, [errorCount.current, onError]);
79
71
 
80
72
  const onReloadPress = useCallback(() => {
81
73
  errorCount.current = 1;
@@ -85,7 +77,7 @@ function ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {
85
77
  count: errorCount.current,
86
78
  expired: false,
87
79
  });
88
- }, [sortKey]);
80
+ }, [sortKey, onError]);
89
81
 
90
82
  const viewStyle = {
91
83
  width: '100%',
@@ -100,21 +92,26 @@ function ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {
100
92
  const Placeholder = useCallback((props: PlaceholderProps) => {
101
93
  const { children, failed } = props;
102
94
 
103
- if (!(isViewable || isLoaded)
104
- || failed
95
+ if (!(isViewable || isLoaded || failed)
96
+ || (itemState?.state === STATE.FAIL)
105
97
  || itemState?.state === STATE.INIT
106
98
  ) {
107
- return <View style={[
108
- viewStyle,
109
- styles.init,
110
- ]}/>;
99
+ return <ImageBackground
100
+ source={{ uri: 'https://ssl.pstatic.net/static/m/comic/im/2012/bg_viewbody.jpg' }}
101
+ resizeMode="repeat"
102
+ style={viewStyle}
103
+ />;
111
104
  }
112
105
 
113
106
  if (errorCount.current >= errorRetryCount) {
114
- return <View style={[
115
- viewStyle,
116
- styles.reload,
117
- ]}>
107
+ return <ImageBackground
108
+ source={{ uri: 'https://ssl.pstatic.net/static/m/comic/im/2012/bg_viewbody.jpg' }}
109
+ resizeMode="repeat"
110
+ style={[
111
+ viewStyle,
112
+ styles.reload,
113
+ ]}
114
+ >
118
115
  <Spacer size={20}/>
119
116
 
120
117
  <IconButton
@@ -128,11 +125,17 @@ function ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {
128
125
  }}
129
126
  onPress={onReloadPress}
130
127
  />
131
- </View>;
128
+ </ImageBackground>;
132
129
  }
133
130
 
134
- return children;
135
- }, [isViewable, isLoaded, errorCount.current, url, onItemPress]);
131
+ return <ImageBackground
132
+ source={{ uri: 'https://ssl.pstatic.net/static/m/comic/im/2012/bg_viewbody.jpg' }}
133
+ resizeMode="repeat"
134
+ style={viewStyle}
135
+ >
136
+ {children}
137
+ </ImageBackground>;
138
+ }, [isViewable, isLoaded, errorCount.current, itemState?.state, responseTimestamp]);
136
139
 
137
140
  useEffect(() => {
138
141
  if (itemState?.state === STATE.INIT) {
@@ -152,6 +155,7 @@ function ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {
152
155
  ]}
153
156
  >
154
157
  <Image
158
+ failDependency={[url, expiresAt, responseTimestamp]}
155
159
  disableOutline={true}
156
160
  key={sortKey}
157
161
  disableLongClick={true}
@@ -163,6 +167,7 @@ function ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {
163
167
  style={imageStyle}
164
168
  square={true}
165
169
  Placeholder={Placeholder}
170
+ disablePlaceholder={true}
166
171
  />
167
172
  </View>
168
173
  </TouchableOpacity>
@@ -174,10 +179,16 @@ export default React.memo(ViewerItem, (prevProps, nextProps) => {
174
179
  return false;
175
180
  }
176
181
 
182
+ // NO NEED ?
177
183
  if (prevProps.props.url !== nextProps.props.url) {
178
184
  return false;
179
185
  }
180
186
 
187
+ // NO NEED ?
188
+ if (prevProps.props.expiresAt !== nextProps.props.expiresAt) {
189
+ return false;
190
+ }
191
+
181
192
  if (prevProps.props.width !== nextProps.props.width) {
182
193
  return false;
183
194
  }
@@ -186,5 +197,9 @@ export default React.memo(ViewerItem, (prevProps, nextProps) => {
186
197
  return false;
187
198
  }
188
199
 
200
+ if (prevProps.props.itemState?.state !== STATE.LOADED && prevProps.props.responseTimestamp !== nextProps.props.responseTimestamp) {
201
+ return false;
202
+ }
203
+
189
204
  return true;
190
- });
205
+ });