mirror of
https://github.com/tooot-app/app
synced 2025-04-23 22:57:23 +02:00
Fixed #9
This commit is contained in:
parent
a9326c381a
commit
13efb56324
2
src/@types/react-navigation.d.ts
vendored
2
src/@types/react-navigation.d.ts
vendored
@ -51,6 +51,8 @@ declare namespace Nav {
|
|||||||
'Screen-ImagesViewer': {
|
'Screen-ImagesViewer': {
|
||||||
imageUrls: {
|
imageUrls: {
|
||||||
url: Mastodon.AttachmentImage['url']
|
url: Mastodon.AttachmentImage['url']
|
||||||
|
width?: number
|
||||||
|
height?: number
|
||||||
preview_url: Mastodon.AttachmentImage['preview_url']
|
preview_url: Mastodon.AttachmentImage['preview_url']
|
||||||
remote_url?: Mastodon.AttachmentImage['remote_url']
|
remote_url?: Mastodon.AttachmentImage['remote_url']
|
||||||
imageIndex: number
|
imageIndex: number
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import React, { useCallback, useMemo, useState } from 'react'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
|
import React, { useCallback, useMemo, useRef, useState } from 'react'
|
||||||
import { Pressable, StyleProp, StyleSheet, ViewStyle } from 'react-native'
|
import { Pressable, StyleProp, StyleSheet, ViewStyle } from 'react-native'
|
||||||
import { Blurhash } from 'react-native-blurhash'
|
import { Blurhash } from 'react-native-blurhash'
|
||||||
import FastImage, { ImageStyle } from 'react-native-fast-image'
|
import FastImage, { ImageStyle } from 'react-native-fast-image'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
|
||||||
|
// blurhas -> if blurhash, show before any loading succeed
|
||||||
|
// original -> load original
|
||||||
|
// original, remote -> if original failed, then remote
|
||||||
|
// preview, original -> first show preview, then original
|
||||||
|
// preview, original, remote -> first show preview, then original, if original failed, then remote
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
sharedElement?: string
|
|
||||||
hidden?: boolean
|
hidden?: boolean
|
||||||
uri: { preview?: string; original: string; remote?: string }
|
uri: { preview?: string; original: string; remote?: string }
|
||||||
blurhash?: string
|
blurhash?: string
|
||||||
@ -14,115 +19,113 @@ export interface Props {
|
|||||||
onPress?: () => void
|
onPress?: () => void
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
imageStyle?: StyleProp<ImageStyle>
|
imageStyle?: StyleProp<ImageStyle>
|
||||||
|
// For image viewer when there is no image size available
|
||||||
|
setImageDimensions?: React.Dispatch<
|
||||||
|
React.SetStateAction<{
|
||||||
|
width: number
|
||||||
|
height: number
|
||||||
|
}>
|
||||||
|
>
|
||||||
}
|
}
|
||||||
|
|
||||||
const GracefullyImage = React.memo(
|
const GracefullyImage = React.memo(
|
||||||
({
|
({
|
||||||
sharedElement,
|
|
||||||
hidden = false,
|
hidden = false,
|
||||||
uri,
|
uri,
|
||||||
blurhash,
|
blurhash,
|
||||||
dimension,
|
dimension,
|
||||||
onPress,
|
onPress,
|
||||||
style,
|
style,
|
||||||
imageStyle
|
imageStyle,
|
||||||
|
setImageDimensions
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const { mode, theme } = useTheme()
|
const { theme } = useTheme()
|
||||||
const [previewLoaded, setPreviewLoaded] = useState(
|
const originalFailed = useRef(false)
|
||||||
uri.preview ? false : true
|
const [imageLoaded, setImageLoaded] = useState(false)
|
||||||
|
|
||||||
|
const source = useMemo(() => {
|
||||||
|
if (originalFailed.current) {
|
||||||
|
return { uri: uri.remote || undefined }
|
||||||
|
} else {
|
||||||
|
return { uri: uri.original }
|
||||||
|
}
|
||||||
|
}, [originalFailed.current])
|
||||||
|
const onLoad = useCallback(
|
||||||
|
({ nativeEvent }) => {
|
||||||
|
setImageLoaded(true)
|
||||||
|
setImageDimensions &&
|
||||||
|
setImageDimensions({
|
||||||
|
width: nativeEvent.width,
|
||||||
|
height: nativeEvent.height
|
||||||
|
})
|
||||||
|
},
|
||||||
|
[source.uri]
|
||||||
)
|
)
|
||||||
const [originalLoaded, setOriginalLoaded] = useState(false)
|
|
||||||
const [originalFailed, setOriginalFailed] = useState(false)
|
|
||||||
const [remoteLoaded, setRemoteLoaded] = useState(uri.remote ? false : true)
|
|
||||||
|
|
||||||
const sourceUri = useMemo(() => {
|
|
||||||
if (previewLoaded) {
|
|
||||||
if (originalFailed) {
|
|
||||||
return uri.remote
|
|
||||||
} else {
|
|
||||||
return uri.original
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return uri.preview
|
|
||||||
}
|
|
||||||
}, [previewLoaded, originalLoaded, originalFailed, remoteLoaded])
|
|
||||||
const onLoad = useCallback(() => {
|
|
||||||
if (previewLoaded) {
|
|
||||||
if (originalFailed) {
|
|
||||||
return setRemoteLoaded(true)
|
|
||||||
} else {
|
|
||||||
return setOriginalLoaded(true)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return setPreviewLoaded(true)
|
|
||||||
}
|
|
||||||
}, [previewLoaded, originalLoaded, originalFailed, remoteLoaded])
|
|
||||||
const onError = useCallback(() => {
|
const onError = useCallback(() => {
|
||||||
if (previewLoaded) {
|
if (!originalFailed.current) {
|
||||||
if (originalFailed) {
|
originalFailed.current = true
|
||||||
return
|
|
||||||
} else {
|
|
||||||
return setOriginalFailed(true)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}, [previewLoaded, originalLoaded, originalFailed, remoteLoaded])
|
}, [originalFailed.current])
|
||||||
|
|
||||||
const children = useCallback(() => {
|
const previewView = useMemo(
|
||||||
return (
|
() =>
|
||||||
<>
|
uri.preview && !imageLoaded ? (
|
||||||
<FastImage
|
<FastImage
|
||||||
source={{ uri: sourceUri }}
|
source={{ uri: uri.preview }}
|
||||||
style={[styles.image, imageStyle]}
|
style={[{ flex: 1 }, imageStyle]}
|
||||||
onLoad={onLoad}
|
|
||||||
onError={onError}
|
|
||||||
/>
|
/>
|
||||||
{blurhash &&
|
) : null,
|
||||||
(hidden || !(previewLoaded || originalLoaded || remoteLoaded)) ? (
|
[imageLoaded]
|
||||||
<Blurhash
|
)
|
||||||
decodeAsync
|
const originalView = useMemo(
|
||||||
blurhash={blurhash}
|
() => (
|
||||||
style={{
|
<FastImage
|
||||||
width: '100%',
|
source={source}
|
||||||
height: '100%',
|
style={[{ flex: imageLoaded ? 1 : undefined }, imageStyle]}
|
||||||
position: 'absolute',
|
onLoad={onLoad}
|
||||||
top: StyleConstants.Spacing.XS / 2,
|
onError={onError}
|
||||||
left: StyleConstants.Spacing.XS / 2
|
/>
|
||||||
}}
|
),
|
||||||
/>
|
[source, imageLoaded]
|
||||||
) : null}
|
)
|
||||||
</>
|
const blurhashView = useMemo(() => {
|
||||||
)
|
return blurhash && (hidden || !imageLoaded) ? (
|
||||||
}, [hidden, previewLoaded, originalLoaded, remoteLoaded, mode, uri])
|
<Blurhash decodeAsync blurhash={blurhash} style={styles.blurhash} />
|
||||||
|
) : null
|
||||||
|
}, [hidden, imageLoaded])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Pressable
|
<Pressable
|
||||||
children={children}
|
style={[style, dimension, { backgroundColor: theme.shimmerDefault }]}
|
||||||
style={[
|
|
||||||
style,
|
|
||||||
{ backgroundColor: theme.shimmerDefault },
|
|
||||||
dimension && { ...dimension }
|
|
||||||
]}
|
|
||||||
{...(onPress
|
{...(onPress
|
||||||
? hidden
|
? hidden
|
||||||
? { disabled: true }
|
? { disabled: true }
|
||||||
: { onPress }
|
: { onPress }
|
||||||
: { disabled: true })}
|
: { disabled: true })}
|
||||||
/>
|
>
|
||||||
|
{previewView}
|
||||||
|
{originalView}
|
||||||
|
{blurhashView}
|
||||||
|
</Pressable>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
(prev, next) => {
|
(prev, next) => {
|
||||||
let skipUpdate = true
|
let skipUpdate = true
|
||||||
skipUpdate = prev.hidden === next.hidden
|
skipUpdate = prev.hidden === next.hidden
|
||||||
|
skipUpdate = prev.uri.preview === next.uri.preview
|
||||||
skipUpdate = prev.uri.original === next.uri.original
|
skipUpdate = prev.uri.original === next.uri.original
|
||||||
|
skipUpdate = prev.uri.remote === next.uri.remote
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
image: {
|
blurhash: {
|
||||||
flex: 1
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
position: 'absolute',
|
||||||
|
top: StyleConstants.Spacing.XS / 2,
|
||||||
|
left: StyleConstants.Spacing.XS / 2
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -32,11 +32,7 @@ const TimelineAttachment: React.FC<Props> = ({ status }) => {
|
|||||||
haptics('Light')
|
haptics('Light')
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
let imageUrls: (App.IImageInfo & {
|
let imageUrls: Nav.RootStackParamList['Screen-ImagesViewer']['imageUrls'] = []
|
||||||
preview_url: Mastodon.AttachmentImage['preview_url']
|
|
||||||
remote_url?: Mastodon.AttachmentImage['remote_url']
|
|
||||||
imageIndex: number
|
|
||||||
})[] = []
|
|
||||||
const navigation = useNavigation()
|
const navigation = useNavigation()
|
||||||
const navigateToImagesViewer = (imageIndex: number) =>
|
const navigateToImagesViewer = (imageIndex: number) =>
|
||||||
navigation.navigate('Screen-ImagesViewer', {
|
navigation.navigate('Screen-ImagesViewer', {
|
||||||
@ -52,6 +48,8 @@ const TimelineAttachment: React.FC<Props> = ({ status }) => {
|
|||||||
url: attachment.url,
|
url: attachment.url,
|
||||||
preview_url: attachment.preview_url,
|
preview_url: attachment.preview_url,
|
||||||
remote_url: attachment.remote_url,
|
remote_url: attachment.remote_url,
|
||||||
|
width: attachment.meta?.original?.width,
|
||||||
|
height: attachment.meta?.original?.height,
|
||||||
imageIndex: index
|
imageIndex: index
|
||||||
})
|
})
|
||||||
return (
|
return (
|
||||||
|
@ -28,12 +28,7 @@ const AttachmentImage: React.FC<Props> = ({
|
|||||||
return (
|
return (
|
||||||
<GracefullyImage
|
<GracefullyImage
|
||||||
hidden={sensitiveShown}
|
hidden={sensitiveShown}
|
||||||
uri={{
|
uri={{ original: image.preview_url, remote: image.remote_url }}
|
||||||
preview: image.preview_url,
|
|
||||||
original: image.url,
|
|
||||||
remote: image.remote_url
|
|
||||||
}}
|
|
||||||
sharedElement={image.url}
|
|
||||||
blurhash={image.blurhash}
|
blurhash={image.blurhash}
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
style={[
|
style={[
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import React, { useCallback } from 'react'
|
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
|
||||||
import { useNavigation } from '@react-navigation/native'
|
|
||||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
|
||||||
import GracefullyImage from '@components/GracefullyImage'
|
|
||||||
import { StackNavigationProp } from '@react-navigation/stack'
|
|
||||||
import analytics from '@components/analytics'
|
import analytics from '@components/analytics'
|
||||||
|
import GracefullyImage from '@components/GracefullyImage'
|
||||||
|
import { useNavigation } from '@react-navigation/native'
|
||||||
|
import { StackNavigationProp } from '@react-navigation/stack'
|
||||||
|
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||||
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
|
import React, { useCallback } from 'react'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
queryKey?: QueryKeyTimeline
|
queryKey?: QueryKeyTimeline
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit c93d6462d598a7b65086f58d40b6b5589be2eefe
|
Subproject commit c8af057d3cc4d6757fd377f97d18f8df33fa1d61
|
@ -1,6 +1,6 @@
|
|||||||
import analytics from '@components/analytics'
|
import analytics from '@components/analytics'
|
||||||
|
import haptics from '@components/haptics'
|
||||||
import { HeaderCenter, HeaderLeft, HeaderRight } from '@components/Header'
|
import { HeaderCenter, HeaderLeft, HeaderRight } from '@components/Header'
|
||||||
import { toast } from '@components/toast'
|
|
||||||
import { useActionSheet } from '@expo/react-native-action-sheet'
|
import { useActionSheet } from '@expo/react-native-action-sheet'
|
||||||
import CameraRoll from '@react-native-community/cameraroll'
|
import CameraRoll from '@react-native-community/cameraroll'
|
||||||
import { StackScreenProps } from '@react-navigation/stack'
|
import { StackScreenProps } from '@react-navigation/stack'
|
||||||
@ -13,10 +13,119 @@ import {
|
|||||||
Platform,
|
Platform,
|
||||||
Share,
|
Share,
|
||||||
StatusBar,
|
StatusBar,
|
||||||
StyleSheet,
|
|
||||||
View
|
View
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import { SafeAreaView } from 'react-native-safe-area-context'
|
import {
|
||||||
|
SafeAreaProvider,
|
||||||
|
useSafeAreaInsets
|
||||||
|
} from 'react-native-safe-area-context'
|
||||||
|
|
||||||
|
const HeaderComponent = React.memo(
|
||||||
|
({
|
||||||
|
navigation,
|
||||||
|
currentIndex,
|
||||||
|
imageUrls
|
||||||
|
}: {
|
||||||
|
navigation: ScreenImagesViewerProp['navigation']
|
||||||
|
currentIndex: number
|
||||||
|
imageUrls: {
|
||||||
|
url: string
|
||||||
|
width?: number | undefined
|
||||||
|
height?: number | undefined
|
||||||
|
preview_url: string
|
||||||
|
remote_url?: string | undefined
|
||||||
|
imageIndex: number
|
||||||
|
}[]
|
||||||
|
}) => {
|
||||||
|
const insets = useSafeAreaInsets()
|
||||||
|
const { t } = useTranslation('screenImageViewer')
|
||||||
|
const { showActionSheetWithOptions } = useActionSheet()
|
||||||
|
|
||||||
|
const hasAndroidPermission = async () => {
|
||||||
|
const permission = PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE
|
||||||
|
|
||||||
|
const hasPermission = await PermissionsAndroid.check(permission)
|
||||||
|
if (hasPermission) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const status = await PermissionsAndroid.request(permission)
|
||||||
|
return status === 'granted'
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveImage = async () => {
|
||||||
|
if (Platform.OS === 'android' && !(await hasAndroidPermission())) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
CameraRoll.save(
|
||||||
|
imageUrls[currentIndex].url ||
|
||||||
|
imageUrls[currentIndex].remote_url ||
|
||||||
|
imageUrls[currentIndex].preview_url
|
||||||
|
)
|
||||||
|
.then(() => haptics('Success'))
|
||||||
|
.catch(() => haptics('Error'))
|
||||||
|
}
|
||||||
|
|
||||||
|
const onPress = useCallback(() => {
|
||||||
|
analytics('imageviewer_more_press')
|
||||||
|
showActionSheetWithOptions(
|
||||||
|
{
|
||||||
|
options: [
|
||||||
|
t('content.options.save'),
|
||||||
|
t('content.options.share'),
|
||||||
|
t('content.options.cancel')
|
||||||
|
],
|
||||||
|
cancelButtonIndex: 2
|
||||||
|
},
|
||||||
|
async buttonIndex => {
|
||||||
|
switch (buttonIndex) {
|
||||||
|
case 0:
|
||||||
|
analytics('imageviewer_more_save_press')
|
||||||
|
saveImage()
|
||||||
|
break
|
||||||
|
case 1:
|
||||||
|
analytics('imageviewer_more_share_press')
|
||||||
|
switch (Platform.OS) {
|
||||||
|
case 'ios':
|
||||||
|
return Share.share({ url: imageUrls[currentIndex].url })
|
||||||
|
case 'android':
|
||||||
|
return Share.share({ message: imageUrls[currentIndex].url })
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}, [currentIndex])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginTop: insets.top
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<HeaderLeft
|
||||||
|
content='X'
|
||||||
|
native={false}
|
||||||
|
onPress={() => navigation.goBack()}
|
||||||
|
/>
|
||||||
|
<HeaderCenter
|
||||||
|
inverted
|
||||||
|
content={`${currentIndex + 1} / ${imageUrls.length}`}
|
||||||
|
/>
|
||||||
|
<HeaderRight
|
||||||
|
content='MoreHorizontal'
|
||||||
|
native={false}
|
||||||
|
onPress={onPress}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
(prev, next) => prev.currentIndex === next.currentIndex
|
||||||
|
)
|
||||||
|
|
||||||
export type ScreenImagesViewerProp = StackScreenProps<
|
export type ScreenImagesViewerProp = StackScreenProps<
|
||||||
Nav.RootStackParamList,
|
Nav.RootStackParamList,
|
||||||
@ -37,120 +146,24 @@ const ScreenImagesViewer = ({
|
|||||||
findIndex(imageUrls, ['imageIndex', imageIndex])
|
findIndex(imageUrls, ['imageIndex', imageIndex])
|
||||||
)
|
)
|
||||||
|
|
||||||
const hasAndroidPermission = async () => {
|
|
||||||
const permission = PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE
|
|
||||||
|
|
||||||
const hasPermission = await PermissionsAndroid.check(permission)
|
|
||||||
if (hasPermission) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
const status = await PermissionsAndroid.request(permission)
|
|
||||||
return status === 'granted'
|
|
||||||
}
|
|
||||||
const saveImage = async () => {
|
|
||||||
if (Platform.OS === 'android' && !(await hasAndroidPermission())) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
CameraRoll.save(
|
|
||||||
imageUrls[imageIndex].url ||
|
|
||||||
imageUrls[imageIndex].remote_url ||
|
|
||||||
imageUrls[imageIndex].preview_url
|
|
||||||
)
|
|
||||||
.then(() =>
|
|
||||||
toast({ type: 'success', message: t('content.save.success') })
|
|
||||||
)
|
|
||||||
.catch(() =>
|
|
||||||
toast({
|
|
||||||
type: 'error',
|
|
||||||
message: t('common:toastMessage.error.message', {
|
|
||||||
function: t('content.save.function')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const { t } = useTranslation('screenImageViewer')
|
|
||||||
const { showActionSheetWithOptions } = useActionSheet()
|
|
||||||
const onPress = useCallback(() => {
|
|
||||||
analytics('imageviewer_more_press')
|
|
||||||
showActionSheetWithOptions(
|
|
||||||
{
|
|
||||||
options: [
|
|
||||||
t('content.options.save'),
|
|
||||||
t('content.options.share'),
|
|
||||||
t('content.options.cancel')
|
|
||||||
],
|
|
||||||
cancelButtonIndex: 2
|
|
||||||
},
|
|
||||||
async buttonIndex => {
|
|
||||||
switch (buttonIndex) {
|
|
||||||
case 0:
|
|
||||||
analytics('imageviewer_more_save_press')
|
|
||||||
saveImage()
|
|
||||||
break
|
|
||||||
case 1:
|
|
||||||
analytics('imageviewer_more_share_press')
|
|
||||||
switch (Platform.OS) {
|
|
||||||
case 'ios':
|
|
||||||
return Share.share({ url: imageUrls[currentIndex].url })
|
|
||||||
case 'android':
|
|
||||||
return Share.share({ message: imageUrls[currentIndex].url })
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}, [currentIndex])
|
|
||||||
|
|
||||||
const HeaderComponent = useCallback(
|
|
||||||
() => (
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
flex: 1,
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
alignItems: 'center'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<HeaderLeft
|
|
||||||
content='X'
|
|
||||||
native={false}
|
|
||||||
onPress={() => navigation.goBack()}
|
|
||||||
/>
|
|
||||||
<HeaderCenter
|
|
||||||
inverted
|
|
||||||
content={`${currentIndex + 1} / ${imageUrls.length}`}
|
|
||||||
/>
|
|
||||||
<HeaderRight
|
|
||||||
content='MoreHorizontal'
|
|
||||||
native={false}
|
|
||||||
onPress={onPress}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
),
|
|
||||||
[currentIndex]
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.base} edges={['top']}>
|
<SafeAreaProvider>
|
||||||
<StatusBar backgroundColor='rgb(0,0,0)' />
|
<StatusBar backgroundColor='rgb(0,0,0)' />
|
||||||
<ImageView
|
<ImageView
|
||||||
images={imageUrls.map(urls => ({ uri: urls.url }))}
|
images={imageUrls}
|
||||||
imageIndex={imageIndex}
|
imageIndex={imageIndex}
|
||||||
onImageIndexChange={index => setCurrentIndex(index)}
|
onImageIndexChange={index => setCurrentIndex(index)}
|
||||||
onRequestClose={() => navigation.goBack()}
|
onRequestClose={() => navigation.goBack()}
|
||||||
HeaderComponent={HeaderComponent}
|
HeaderComponent={() => (
|
||||||
|
<HeaderComponent
|
||||||
|
navigation={navigation}
|
||||||
|
currentIndex={currentIndex}
|
||||||
|
imageUrls={imageUrls}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</SafeAreaView>
|
</SafeAreaProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
base: {
|
|
||||||
flex: 1,
|
|
||||||
backgroundColor: 'black'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
export default ScreenImagesViewer
|
export default ScreenImagesViewer
|
||||||
|
Loading…
x
Reference in New Issue
Block a user