tooot/src/screens/Compose/EditAttachment/Image.tsx

174 lines
5.0 KiB
TypeScript
Raw Normal View History

import CustomText from '@components/Text'
2021-04-09 21:43:12 +02:00
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
2021-01-01 17:52:14 +01:00
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
2021-02-11 01:33:31 +01:00
import React, { useContext } from 'react'
2021-01-19 01:13:45 +01:00
import { useTranslation } from 'react-i18next'
import { Dimensions, Image, View } from 'react-native'
2022-08-19 01:58:17 +02:00
import { Gesture, GestureDetector } from 'react-native-gesture-handler'
import Animated, {
Extrapolate,
interpolate,
runOnJS,
useAnimatedStyle,
useSharedValue
} from 'react-native-reanimated'
2021-01-01 17:52:14 +01:00
import ComposeContext from '../utils/createContext'
2020-12-30 00:56:25 +01:00
export interface Props {
index: number
}
2021-03-09 14:43:31 +01:00
const ComposeEditAttachmentImage: React.FC<Props> = ({ index }) => {
2021-03-28 23:31:10 +02:00
const { t } = useTranslation('screenCompose')
2022-02-12 14:51:01 +01:00
const { colors } = useTheme()
2021-04-09 21:43:12 +02:00
const { screenReaderEnabled } = useAccessibility()
2020-12-30 00:56:25 +01:00
2021-03-09 14:43:31 +01:00
const { composeState, composeDispatch } = useContext(ComposeContext)
const theAttachmentRemote = composeState.attachments.uploads[index].remote!
2021-01-22 01:34:20 +01:00
const theAttachmentLocal = composeState.attachments.uploads[index].local
2020-12-30 00:56:25 +01:00
2022-08-19 01:58:17 +02:00
const windowWidth = Dimensions.get('window').width
2021-01-04 14:55:34 +01:00
const imageWidthBase =
2021-01-22 01:34:20 +01:00
theAttachmentRemote?.meta?.original?.aspect < 1
2022-08-19 01:58:17 +02:00
? windowWidth * theAttachmentRemote?.meta?.original?.aspect
: windowWidth
2020-12-30 00:56:25 +01:00
const imageDimensionis = {
2021-01-04 14:55:34 +01:00
width: imageWidthBase,
2020-12-30 00:56:25 +01:00
height:
2021-01-04 14:55:34 +01:00
imageWidthBase /
2022-08-19 01:58:17 +02:00
((theAttachmentRemote as Mastodon.AttachmentImage)?.meta?.original?.aspect || 1)
2020-12-30 00:56:25 +01:00
}
const updateFocus = ({ x, y }: { x: number; y: number }) => {
2021-03-09 14:43:31 +01:00
composeDispatch({
type: 'attachment/edit',
payload: {
...theAttachmentRemote,
meta: {
...theAttachmentRemote.meta,
focus: {
x: x > 1 ? 1 : x,
y: y > 1 ? 1 : y
}
}
}
})
}
2021-03-09 14:43:31 +01:00
2022-08-19 01:58:17 +02:00
const pan = useSharedValue({
x:
(((theAttachmentRemote as Mastodon.AttachmentImage)?.meta?.focus?.x || 0) *
imageDimensionis.width) /
2,
y:
(((theAttachmentRemote as Mastodon.AttachmentImage)?.meta?.focus?.y || 0) *
imageDimensionis.height) /
2
})
const start = useSharedValue({ x: 0, y: 0 })
const gesture = Gesture.Pan()
.onBegin(() => {
start.value = pan.value
})
.onUpdate(e => {
pan.value = {
x: e.translationX + start.value.x,
y: e.translationY + start.value.y
}
})
.onEnd(() => {
runOnJS(updateFocus)({
2022-08-19 01:58:17 +02:00
x: pan.value.x / (imageDimensionis.width / 2),
y: pan.value.y / (imageDimensionis.height / 2)
})
2022-08-19 01:58:17 +02:00
})
.onFinalize(() => {
start.value = pan.value
})
const styleTransform = useAnimatedStyle(() => {
return {
transform: [
{
translateX: interpolate(
2022-08-19 01:58:17 +02:00
pan.value.x,
[-imageDimensionis.width / 2, imageDimensionis.width / 2],
[-imageDimensionis.width / 2, imageDimensionis.width / 2],
Extrapolate.CLAMP
)
},
{
translateY: interpolate(
2022-08-19 01:58:17 +02:00
pan.value.y,
[-imageDimensionis.height / 2, imageDimensionis.height / 2],
[-imageDimensionis.height / 2, imageDimensionis.height / 2],
Extrapolate.CLAMP
)
}
]
2020-12-30 00:56:25 +01:00
}
})
return (
<>
<View style={{ overflow: 'hidden', flex: 1, alignItems: 'center' }}>
2021-03-19 21:44:52 +01:00
<Image
2020-12-30 00:56:25 +01:00
style={{
width: imageDimensionis.width,
height: imageDimensionis.height
}}
source={{
2022-08-19 01:58:17 +02:00
uri: theAttachmentLocal?.uri ? theAttachmentLocal.uri : theAttachmentRemote?.preview_url
2020-12-30 00:56:25 +01:00
}}
/>
2022-08-19 01:58:17 +02:00
<GestureDetector gesture={gesture}>
2020-12-30 00:56:25 +01:00
<Animated.View
style={[
styleTransform,
2020-12-30 00:56:25 +01:00
{
2022-08-19 01:58:17 +02:00
width: windowWidth * 2,
height: imageDimensionis.height * 2,
2020-12-30 00:56:25 +01:00
position: 'absolute',
2022-08-19 01:58:17 +02:00
left: -windowWidth / 2,
top: -imageDimensionis.height / 2,
backgroundColor: colors.backgroundOverlayInvert,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center'
2020-12-30 00:56:25 +01:00
}
]}
2022-08-19 01:58:17 +02:00
children={
<View
style={{
width: 48,
height: 48,
borderRadius: 24,
borderWidth: 2,
borderColor: colors.primaryOverlay,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center'
}}
/>
}
/>
</GestureDetector>
2020-12-30 00:56:25 +01:00
</View>
2021-04-09 21:43:12 +02:00
{screenReaderEnabled ? null : (
<CustomText
fontStyle='M'
style={{
padding: StyleConstants.Spacing.Global.PagePadding,
color: colors.primaryDefault
}}
>
2021-04-09 21:43:12 +02:00
{t('content.editAttachment.content.imageFocus')}
</CustomText>
2021-04-09 21:43:12 +02:00
)}
2020-12-30 00:56:25 +01:00
</>
)
}
export default ComposeEditAttachmentImage