-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: diable refetch when window on focus
- Loading branch information
liaoliao666
committed
Jan 3, 2023
1 parent
16c88c7
commit 9963d38
Showing
30 changed files
with
312 additions
and
288 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,136 +1,122 @@ | ||
import { Ionicons } from '@expo/vector-icons' | ||
import { ComponentProps } from 'react' | ||
import { | ||
Modal, | ||
Pressable, | ||
Text, | ||
TouchableWithoutFeedback, | ||
View, | ||
useWindowDimensions, | ||
} from 'react-native' | ||
import ImageViewer from 'react-native-image-zoom-viewer' | ||
import { useSafeAreaInsets } from 'react-native-safe-area-context' | ||
import { useCallback, useState } from 'react' | ||
import { Pressable, Text, View } from 'react-native' | ||
import ImageView from 'react-native-image-viewing' | ||
import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context' | ||
import Toast from 'react-native-toast-message' | ||
|
||
import { savePicture } from '@/utils/savePicture' | ||
import tw from '@/utils/tw' | ||
|
||
import { NAV_BAR_HEIGHT } from './NavBar' | ||
import StyledImage from './StyledImage' | ||
import StyledToast from './StyledToast' | ||
const StyledImageViewer: typeof ImageView = props => { | ||
const safeAreaInsets = useSafeAreaInsets() | ||
|
||
const [menuVisible, setMenuVisible] = useState(false) | ||
|
||
const FooterComponent = useCallback(() => { | ||
return ( | ||
<Pressable | ||
onPress={() => { | ||
setMenuVisible(false) | ||
}} | ||
style={tw`bg-mask h-screen`} | ||
> | ||
<View | ||
style={tw.style( | ||
`bg-body-1 absolute bottom-0 inset-x-0 rounded-t-[32px] overflow-hidden`, | ||
{ | ||
paddingBottom: safeAreaInsets.bottom, | ||
} | ||
)} | ||
> | ||
{[ | ||
{ | ||
label: '保存', | ||
value: 'saveToLocal', | ||
onPress: async () => { | ||
try { | ||
const { images, imageIndex } = props | ||
|
||
export interface StyledImageViewerProps | ||
extends Omit<ComponentProps<typeof ImageViewer>, 'onCancel'> { | ||
visible?: boolean | ||
onClose?: () => void | ||
await savePicture((images[imageIndex] as any).uri) | ||
Toast.show({ | ||
type: 'success', | ||
text1: '保存成功', | ||
}) | ||
} catch (error) { | ||
Toast.show({ | ||
type: 'error', | ||
text1: '保存失败', | ||
}) | ||
} | ||
}, | ||
}, | ||
{ | ||
label: '取消', | ||
value: 'cancel', | ||
onPress: () => { | ||
setMenuVisible(false) | ||
}, | ||
}, | ||
].map(item => ( | ||
<Pressable | ||
key={item.value} | ||
onPress={item.onPress} | ||
style={({ pressed }) => | ||
tw.style( | ||
`h-[53px] justify-center items-center border-tint-border border-t border-solid`, | ||
pressed && `bg-message-press` | ||
) | ||
} | ||
> | ||
<Text style={tw`text-body-5 text-tint-primary`}> | ||
{item.label} | ||
</Text> | ||
</Pressable> | ||
))} | ||
</View> | ||
</Pressable> | ||
) | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, []) | ||
|
||
return ( | ||
<ImageView | ||
{...props} | ||
onLongPress={() => { | ||
setMenuVisible(true) | ||
}} | ||
keyExtractor={image => (image as any).uri} | ||
FooterComponent={ | ||
menuVisible | ||
? FooterComponent | ||
: ({ imageIndex }) => ( | ||
<ImageFooter | ||
imageIndex={imageIndex} | ||
imagesCount={props.images.length} | ||
/> | ||
) | ||
} | ||
/> | ||
) | ||
} | ||
|
||
export default function StyledImageViewer({ | ||
visible, | ||
onClose, | ||
...props | ||
}: StyledImageViewerProps) { | ||
function ImageFooter({ | ||
imageIndex, | ||
imagesCount, | ||
}: { | ||
imageIndex: number | ||
imagesCount: number | ||
}) { | ||
const safeAreaInsets = useSafeAreaInsets() | ||
|
||
const { width } = useWindowDimensions() | ||
|
||
return ( | ||
<Modal | ||
presentationStyle="fullScreen" | ||
visible={visible} | ||
onRequestClose={onClose} | ||
<View | ||
style={tw`px-4 flex-row justify-center pb-[${safeAreaInsets.bottom}px]`} | ||
> | ||
<ImageViewer | ||
enableSwipeDown | ||
onCancel={onClose} | ||
menus={({ cancel, saveToLocal }) => ( | ||
<Pressable onPress={cancel} style={tw`bg-mask absolute inset-0`}> | ||
<View | ||
style={tw.style( | ||
`bg-body-1 absolute bottom-0 inset-x-0 rounded-t-[32px] overflow-hidden`, | ||
{ | ||
paddingBottom: safeAreaInsets.bottom, | ||
} | ||
)} | ||
> | ||
{[ | ||
{ | ||
label: '保存', | ||
value: 'saveToLocal', | ||
onPress: saveToLocal, | ||
}, | ||
{ | ||
label: '取消', | ||
value: 'cancel', | ||
onPress: cancel, | ||
}, | ||
].map(item => ( | ||
<Pressable | ||
key={item.value} | ||
onPress={item.onPress} | ||
style={({ pressed }) => | ||
tw.style( | ||
`h-[53px] justify-center items-center border-tint-border border-t border-solid`, | ||
pressed && `bg-message-press` | ||
) | ||
} | ||
> | ||
<Text style={tw`text-body-5 text-tint-primary`}> | ||
{item.label} | ||
</Text> | ||
</Pressable> | ||
))} | ||
</View> | ||
</Pressable> | ||
)} | ||
onSave={async url => { | ||
try { | ||
await savePicture(url) | ||
Toast.show({ | ||
type: 'success', | ||
text1: '保存成功', | ||
}) | ||
} catch (error) { | ||
Toast.show({ | ||
type: 'error', | ||
text1: '保存失败', | ||
}) | ||
} | ||
}} | ||
renderHeader={() => ( | ||
<View | ||
style={tw`pt-[${safeAreaInsets.top}px] px-4 z-20 absolute top-0 inset-x-0 flex-row justify-end`} | ||
> | ||
<TouchableWithoutFeedback | ||
onPress={onClose} | ||
style={tw`h-[${NAV_BAR_HEIGHT}px] justify-center items-center`} | ||
> | ||
<Ionicons name="close-sharp" size={24} color={'#fff'} /> | ||
</TouchableWithoutFeedback> | ||
</View> | ||
)} | ||
renderIndicator={(currentIndex, allSize) => ( | ||
<View | ||
style={tw`pt-[${safeAreaInsets.top}px] px-4 z-10 absolute top-0 inset-x-0 flex-row justify-center`} | ||
> | ||
<Text style={tw`text-white text-body-4`}> | ||
{currentIndex + '/' + allSize} | ||
</Text> | ||
</View> | ||
)} | ||
renderImage={imageProps => ( | ||
<StyledImage | ||
{...imageProps} | ||
style={{ | ||
...props.style, | ||
width, | ||
}} | ||
/> | ||
)} | ||
{...props} | ||
/> | ||
|
||
<StyledToast /> | ||
</Modal> | ||
<Text style={tw`text-white text-body-4`}> | ||
{imageIndex + 1 + '/' + imagesCount} | ||
</Text> | ||
</View> | ||
) | ||
} | ||
|
||
export default StyledImageViewer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,8 @@ | ||
import { atom } from 'jotai' | ||
import ImageView from 'react-native-image-viewing' | ||
|
||
import { StyledImageViewerProps } from '@/components/StyledImageViewer' | ||
|
||
export const imageViewerAtom = atom<StyledImageViewerProps>({ | ||
index: 0, | ||
export const imageViewerAtom = atom<Partial<Parameters<typeof ImageView>[0]>>({ | ||
imageIndex: 0, | ||
visible: false, | ||
imageUrls: [], | ||
images: [], | ||
}) |
Oops, something went wrong.