mirror of
https://github.com/tooot-app/app
synced 2025-06-05 22:19:13 +02:00
Use native view drawing instead of svg
This commit is contained in:
@@ -5,16 +5,14 @@ import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { useContext } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Dimensions, Image, View } from 'react-native'
|
||||
import { PanGestureHandler } from 'react-native-gesture-handler'
|
||||
import { Gesture, GestureDetector } from 'react-native-gesture-handler'
|
||||
import Animated, {
|
||||
Extrapolate,
|
||||
interpolate,
|
||||
runOnJS,
|
||||
useAnimatedGestureHandler,
|
||||
useAnimatedStyle,
|
||||
useSharedValue
|
||||
} from 'react-native-reanimated'
|
||||
import Svg, { Circle, G, Path } from 'react-native-svg'
|
||||
import ComposeContext from '../utils/createContext'
|
||||
|
||||
export interface Props {
|
||||
@@ -30,30 +28,19 @@ const ComposeEditAttachmentImage: React.FC<Props> = ({ index }) => {
|
||||
const theAttachmentRemote = composeState.attachments.uploads[index].remote!
|
||||
const theAttachmentLocal = composeState.attachments.uploads[index].local
|
||||
|
||||
const windowWidth = Dimensions.get('window').width
|
||||
|
||||
const imageWidthBase =
|
||||
theAttachmentRemote?.meta?.original?.aspect < 1
|
||||
? Dimensions.get('screen').width *
|
||||
theAttachmentRemote?.meta?.original?.aspect
|
||||
: Dimensions.get('screen').width
|
||||
const padding = (Dimensions.get('screen').width - imageWidthBase) / 2
|
||||
? windowWidth * theAttachmentRemote?.meta?.original?.aspect
|
||||
: windowWidth
|
||||
const imageDimensionis = {
|
||||
width: imageWidthBase,
|
||||
height:
|
||||
imageWidthBase /
|
||||
((theAttachmentRemote as Mastodon.AttachmentImage)?.meta?.original
|
||||
?.aspect || 1)
|
||||
((theAttachmentRemote as Mastodon.AttachmentImage)?.meta?.original?.aspect || 1)
|
||||
}
|
||||
|
||||
const panX = useSharedValue(
|
||||
(((theAttachmentRemote as Mastodon.AttachmentImage)?.meta?.focus?.x || 0) *
|
||||
imageDimensionis.width) /
|
||||
2
|
||||
)
|
||||
const panY = useSharedValue(
|
||||
(((theAttachmentRemote as Mastodon.AttachmentImage)?.meta?.focus?.y || 0) *
|
||||
imageDimensionis.height) /
|
||||
2
|
||||
)
|
||||
const updateFocus = ({ x, y }: { x: number; y: number }) => {
|
||||
composeDispatch({
|
||||
type: 'attachment/edit',
|
||||
@@ -70,46 +57,50 @@ const ComposeEditAttachmentImage: React.FC<Props> = ({ index }) => {
|
||||
})
|
||||
}
|
||||
|
||||
type PanContext = {
|
||||
startX: number
|
||||
startY: number
|
||||
}
|
||||
const onGestureEvent = useAnimatedGestureHandler({
|
||||
onStart: (_, context: PanContext) => {
|
||||
context.startX = panX.value
|
||||
context.startY = panY.value
|
||||
},
|
||||
onActive: ({ translationX, translationY }, context: PanContext) => {
|
||||
panX.value = context.startX + translationX
|
||||
panY.value = context.startY + translationY
|
||||
},
|
||||
onEnd: ({ translationX, translationY }, context: PanContext) => {
|
||||
runOnJS(updateFocus)({
|
||||
x: (context.startX + translationX) / (imageDimensionis.width / 2),
|
||||
y: (context.startY + translationY) / (imageDimensionis.height / 2)
|
||||
})
|
||||
}
|
||||
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)({
|
||||
x: pan.value.x / (imageDimensionis.width / 2),
|
||||
y: pan.value.y / (imageDimensionis.height / 2)
|
||||
})
|
||||
})
|
||||
.onFinalize(() => {
|
||||
start.value = pan.value
|
||||
})
|
||||
const styleTransform = useAnimatedStyle(() => {
|
||||
return {
|
||||
transform: [
|
||||
{
|
||||
translateX: interpolate(
|
||||
panX.value,
|
||||
[
|
||||
-imageDimensionis.width / 2 + padding,
|
||||
imageDimensionis.width / 2 + padding
|
||||
],
|
||||
[
|
||||
-imageDimensionis.width / 2 + padding,
|
||||
imageDimensionis.width / 2 + padding
|
||||
],
|
||||
pan.value.x,
|
||||
[-imageDimensionis.width / 2, imageDimensionis.width / 2],
|
||||
[-imageDimensionis.width / 2, imageDimensionis.width / 2],
|
||||
Extrapolate.CLAMP
|
||||
)
|
||||
},
|
||||
{
|
||||
translateY: interpolate(
|
||||
panY.value,
|
||||
pan.value.y,
|
||||
[-imageDimensionis.height / 2, imageDimensionis.height / 2],
|
||||
[-imageDimensionis.height / 2, imageDimensionis.height / 2],
|
||||
Extrapolate.CLAMP
|
||||
@@ -128,47 +119,41 @@ const ComposeEditAttachmentImage: React.FC<Props> = ({ index }) => {
|
||||
height: imageDimensionis.height
|
||||
}}
|
||||
source={{
|
||||
uri: theAttachmentLocal?.uri
|
||||
? theAttachmentLocal.uri
|
||||
: theAttachmentRemote?.preview_url
|
||||
uri: theAttachmentLocal?.uri ? theAttachmentLocal.uri : theAttachmentRemote?.preview_url
|
||||
}}
|
||||
/>
|
||||
<PanGestureHandler onGestureEvent={onGestureEvent}>
|
||||
<GestureDetector gesture={gesture}>
|
||||
<Animated.View
|
||||
style={[
|
||||
styleTransform,
|
||||
{
|
||||
width: windowWidth * 2,
|
||||
height: imageDimensionis.height * 2,
|
||||
position: 'absolute',
|
||||
top: -500 + imageDimensionis.height / 2,
|
||||
left: -500 + imageDimensionis.width / 2
|
||||
left: -windowWidth / 2,
|
||||
top: -imageDimensionis.height / 2,
|
||||
backgroundColor: colors.backgroundOverlayInvert,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}
|
||||
]}
|
||||
>
|
||||
<Svg width='1000' height='1000' viewBox='0 0 1000 1000'>
|
||||
<G stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'>
|
||||
<G>
|
||||
<Path
|
||||
d='M1000,0 L1000,1000 L0,1000 L0,0 L1000,0 Z M500,475 C486.192881,475 475,486.192881 475,500 C475,513.807119 486.192881,525 500,525 C513.807119,525 525,513.807119 525,500 C525,486.192881 513.807119,475 500,475 Z'
|
||||
fill={colors.backgroundOverlayInvert}
|
||||
/>
|
||||
<Circle
|
||||
stroke={colors.primaryOverlay}
|
||||
stroke-width='2'
|
||||
cx='500'
|
||||
cy='500'
|
||||
r='24'
|
||||
/>
|
||||
<Circle
|
||||
fill={colors.primaryOverlay}
|
||||
cx='500'
|
||||
cy='500'
|
||||
r='2'
|
||||
/>
|
||||
</G>
|
||||
</G>
|
||||
</Svg>
|
||||
</Animated.View>
|
||||
</PanGestureHandler>
|
||||
children={
|
||||
<View
|
||||
style={{
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: 24,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.primaryOverlay,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</GestureDetector>
|
||||
</View>
|
||||
{screenReaderEnabled ? null : (
|
||||
<CustomText
|
||||
|
||||
Reference in New Issue
Block a user