import React, { useEffect, useRef } from "react"; import { Image, LayoutAnimation, Platform, View } from "react-native"; import type { LocationObject } from "expo-location"; import MapView, { Marker } from "react-native-maps"; import type { StationProps } from "@/lib/CommonTypes"; type MenuMapProps = { mapHeight: number; mapFullHeight: number; mapMode: boolean; backgroundColor: string; isDark: boolean; isHeavyContentReady: boolean; listIndex: number; listUpStation: StationProps[][]; position: LocationObject | undefined; mapPaddingTop: number; mapPaddingBottom: number; setMapMode: React.Dispatch>; setListIndex: (index: number) => void; onGoToMap: () => void; onReturnToTop: () => void; }; const MAP_PIN_SIZE = Platform.OS === "android" ? 32 : 36; const ANDROID_USER_LOCATION_MARKER_SIZE = 18; const ANDROID_USER_LOCATION_INNER_SIZE = 8; const configureMapLayoutAnimation = () => { LayoutAnimation.configureNext({ duration: 300, create: { type: LayoutAnimation.Types.easeInEaseOut, property: LayoutAnimation.Properties.opacity, }, update: { type: LayoutAnimation.Types.easeInEaseOut, property: LayoutAnimation.Properties.opacity, }, }); }; const MenuMapComponent = ({ mapHeight, mapFullHeight, mapMode, backgroundColor, isDark, isHeavyContentReady, listIndex, listUpStation, position, mapPaddingTop, mapPaddingBottom, setMapMode, setListIndex, onGoToMap, onReturnToTop, }: MenuMapProps) => { const mapsRef = useRef(null); useEffect(() => { if (!isHeavyContentReady) return; if (!mapsRef.current) return; if (listUpStation.length === 0) return; if (listUpStation[listIndex] == undefined) return; const { lat, lng } = listUpStation[listIndex][0]; const mapRegion = { latitude: lat, longitude: lng, latitudeDelta: 0.05, longitudeDelta: 0.05, }; if (mapMode) { mapsRef.current.fitToCoordinates( listUpStation.map((stationGroup) => ({ latitude: stationGroup[0].lat, longitude: stationGroup[0].lng, })), { edgePadding: { top: mapPaddingTop, bottom: mapPaddingBottom, left: 50, right: 50, }, }, ); } else { mapsRef.current.animateToRegion(mapRegion, 1000); } // mapMode と padding の変更時には、既存挙動どおり個別追従しない // eslint-disable-next-line react-hooks/exhaustive-deps }, [isHeavyContentReady, listIndex, listUpStation]); const handleMapTouch = () => { configureMapLayoutAnimation(); setMapMode(true); onGoToMap(); }; const handleMarkerPress = ( station: { lat: number; lng: number }, index: number, ) => { setMapMode(false); setListIndex(index); if (mapsRef.current) { mapsRef.current.animateToRegion( { latitude: station.lat, longitude: station.lng, latitudeDelta: 0.05, longitudeDelta: 0.05, }, 1000, ); } configureMapLayoutAnimation(); onReturnToTop(); }; if (!isHeavyContentReady) { return ( ); } return ( {Platform.OS === "android" && position ? ( ) : null} {listUpStation.map(([{ lat, lng, StationNumber }], index) => ( handleMarkerPress({ lat, lng }, index)} > ))} ); }; export const MenuMap = React.memo(MenuMapComponent); MenuMap.displayName = "MenuMap";