import {useRef, useState} from 'react' import {Modal, Pressable, StyleSheet, View} from 'react-native' import Animated, { interpolate, runOnJS, useAnimatedStyle, useSharedValue, withSpring, withTiming, } from 'react-native-reanimated' import {useLingui} from '@lingui/react/macro' import {atoms as a} from '#/alf' import {ArrowShareRight_Stroke2_Corner2_Rounded as ShareIcon} from '#/components/icons/ArrowShareRight' import {type Props as IconProps} from '#/components/icons/common' import {DotGrid3x1_Stroke2_Corner0_Rounded as DotsIcon} from '#/components/icons/DotGrid' import {Download_Stroke2_Corner0_Rounded as DownloadIcon} from '#/components/icons/Download' import {Text} from '#/components/Typography' import {CircleChromeButton} from './CircleChromeButton' type Props = { onPressShare: () => void onPressSave: () => void } type Anchor = {x: number; y: number; width: number; height: number} const GAP = 6 const CARD_BG = '#000000' const CARD_BORDER = '#232e3e' const ITEM_TEXT = '#f9fafb' const SPRING_IN = {damping: 18, mass: 0.6, stiffness: 240} const TIMING_OUT = {duration: 150} export function ImageMenu({onPressShare, onPressSave}: Props) { const {t: l} = useLingui() const triggerRef = useRef(null) const [isMounted, setIsMounted] = useState(false) const [anchor, setAnchor] = useState(null) const progress = useSharedValue(0) const open = () => { triggerRef.current?.measureInWindow((x, y, width, height) => { setAnchor({x, y, width, height}) setIsMounted(true) progress.set(withSpring(1, SPRING_IN)) }) } const close = () => { progress.set( withTiming(0, TIMING_OUT, finished => { if (finished) { runOnJS(setIsMounted)(false) } }), ) } const runAction = (action: () => void) => { close() action() } return ( <> {anchor && ( runAction(onPressShare)} /> runAction(onPressSave)} /> )} ) } function MenuCard({ anchor, progress, children, }: { anchor: Anchor progress: ReturnType> children: React.ReactNode }) { const animatedStyle = useAnimatedStyle(() => ({ opacity: progress.get(), transform: [{scale: interpolate(progress.get(), [0, 1], [0.9, 1])}], })) return ( {children} ) } function MenuItem({ icon: Icon, label, onPress, }: { icon: React.ComponentType label: string onPress: () => void }) { return ( [styles.item, pressed && styles.itemPressed]}> {label} ) } const styles = StyleSheet.create({ card: { padding: 8, borderRadius: 16, borderWidth: 0.5, borderColor: CARD_BORDER, backgroundColor: CARD_BG, shadowColor: '#000', shadowOffset: {width: 0, height: 4}, shadowOpacity: 0.16, shadowRadius: 20, elevation: 8, }, item: { height: 44, paddingHorizontal: 12, borderRadius: 8, flexDirection: 'row', alignItems: 'center', gap: 6, }, itemPressed: { backgroundColor: 'rgba(255, 255, 255, 0.08)', }, itemText: { fontSize: 15, fontWeight: '500', lineHeight: 19.5, color: ITEM_TEXT, }, })