Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

条漫模式下漫画模糊问题优化 #134

Closed
wants to merge 9 commits into from
126 changes: 61 additions & 65 deletions src/components/ComicImage.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, { useCallback, useState, useMemo, useRef, memo } from 'react';
import { aspectFit, AsyncStatus, LayoutMode, Orientation, ScrambleType, unscramble } from '~/utils';
import { Image as ReactNativeImage, StyleSheet, Dimensions, DimensionValue } from 'react-native';
import { StyleSheet, Dimensions, DimensionValue } from 'react-native';
import { useDebouncedSafeAreaFrame, useDebouncedSafeAreaInsets } from '~/hooks';
import { CachedImage, CacheManager } from '@georstat/react-native-image-cache';
import { CacheManager } from '@georstat/react-native-image-cache';
import { useFocusEffect } from '@react-navigation/native';
import { Center, Image } from 'native-base';
import ErrorWithRetry from '~/components/ErrorWithRetry';
import FastImage, { ResizeMode } from 'react-native-fast-image';
import FastImage, { OnLoadEvent, ResizeMode } from 'react-native-fast-image';
import Canvas, { Image as CanvasImage } from 'react-native-canvas';

const groundPoundGif = require('~/assets/ground_pound.gif');
Expand Down Expand Up @@ -100,64 +100,38 @@ const DefaultImage = ({
const handleError = useCallback(() => {
updateData({ ...imageState, loadStatus: AsyncStatus.Rejected });
}, [imageState, updateData]);
const loadImage = useCallback(() => {

const handleImageLoadStart = useCallback(() => {
setImageState({ ...imageState, loadStatus: AsyncStatus.Pending });
CacheManager.prefetchBlob(uri, { headers })
.then((base64) => {
if (!base64) {
handleError();
return;
}
if (layoutMode === LayoutMode.Horizontal) {
updateData({ ...imageState, dataUrl: uri, loadStatus: AsyncStatus.Fulfilled });
return;
}
}, [imageState]);

ReactNativeImage.getSize(
'data:image/png;base64,' + base64,
(width, height) => {
const { dWidth, dHeight } = aspectFit(
{ width, height },
{
width: (windowWidth - left - right) / 2,
height: windowHeight - top - bottom,
}
);
updateData({
...imageState,
dataUrl: uri,
multipleFitWidth: dWidth,
multipleFitHeight: dHeight,
landscapeHeight: (height / width) * Math.max(windowWidth, windowHeight),
portraitHeight: (height / width) * Math.min(windowWidth, windowHeight),
loadStatus: AsyncStatus.Fulfilled,
});
},
handleError
);
})
.catch(handleError);
}, [
uri,
headers,
imageState,
layoutMode,
updateData,
handleError,
windowWidth,
windowHeight,
top,
left,
right,
bottom,
]);
useFocusEffect(
useCallback(() => {
if (imageState.loadStatus === AsyncStatus.Default) {
loadImage();
const handleImageLoad = useCallback(
(e: OnLoadEvent) => {
if (layoutMode === LayoutMode.Horizontal) {
updateData({ ...imageState, dataUrl: uri, loadStatus: AsyncStatus.Fulfilled });
return;
}
}, [imageState, loadImage])
const { width, height } = e.nativeEvent;
const { dWidth, dHeight } = aspectFit(
{ width, height },
{
width: (windowWidth - left - right) / 2,
height: windowHeight - top - bottom,
}
);
updateData({
...imageState,
dataUrl: uri,
multipleFitWidth: dWidth,
multipleFitHeight: dHeight,
landscapeHeight: (height / width) * Math.max(windowWidth, windowHeight),
portraitHeight: (height / width) * Math.min(windowWidth, windowHeight),
loadStatus: AsyncStatus.Fulfilled,
});
},
[updateData, layoutMode, imageState, uri, windowWidth, windowHeight, left, right, top, bottom]
);

useFocusEffect(
useCallback(() => {
if (uriRef.current !== uri) {
Expand All @@ -168,18 +142,17 @@ const DefaultImage = ({
);

const handleRetry = () => {
CacheManager.removeCacheEntry(uri)
.then(() => {})
.catch(() => {})
.finally(() => updateData({ ...imageState, loadStatus: AsyncStatus.Default }));
updateData({ ...imageState, loadStatus: AsyncStatus.Default });
};

if (
imageState.loadStatus === AsyncStatus.Pending ||
imageState.loadStatus === AsyncStatus.Default
) {
// onLoad() prop returns wrong values in 'height' and 'width' on Android
// https://github.com/DylanVann/react-native-fast-image/issues/944
return (
<Center style={style}>
<Center style={[style, styles.relativeBox]}>
<Image
style={{ width: Math.min(windowWidth * 0.3, 180), height: windowHeight }}
resizeMode="contain"
Expand All @@ -188,6 +161,17 @@ const DefaultImage = ({
source={groundPoundGif}
alt="groundpound"
/>
<FastImage
style={[style, styles.loadingImage]}
source={{
uri,
headers,
}}
resizeMode="contain"
onLoadStart={handleImageLoadStart}
onLoad={handleImageLoad}
onError={handleError}
/>
</Center>
);
}
Expand All @@ -200,10 +184,12 @@ const DefaultImage = ({
}

return (
<CachedImage
source={uri}
options={{ headers }}
<FastImage
style={style}
source={{
uri,
headers,
}}
resizeMode={resizeModeDict[layoutMode]}
onError={handleError}
/>
Expand Down Expand Up @@ -415,6 +401,16 @@ const styles = StyleSheet.create({
opacity: 0,
position: 'absolute',
},
relativeBox: {
position: 'relative',
},
loadingImage: {
opacity: 0,
zIndex: -1,
position: 'absolute',
top: 0,
right: 0,
},
});

const ComicImage = ({ scrambleType, needUnscramble, ...props }: ComicImageProps) => {
Expand Down