import React, { useRef, useState, useEffect, useLayoutEffect, FC } from "react"; import { Platform, View, ScrollView, LayoutAnimation } from "react-native"; import Constants from "expo-constants"; import { configureReanimatedLogger, ReanimatedLogLevel, } from "react-native-reanimated"; import StatusbarDetect from "@/StatusbarDetect"; import { LED_vision } from "@/components/発車時刻表/LED_vidion"; import { TitleBar } from "@/components/Menu/TitleBar"; import { FixedContentBottom } from "@/components/Menu/FixedContentBottom"; import { lineList, stationIDPair } from "@/lib/getStationList"; import { useFavoriteStation } from "@/stateBox/useFavoriteStation"; import { useNavigation } from "@react-navigation/native"; import { useStationList } from "@/stateBox/useStationList"; import { TopMenuButton } from "@/components/Menu/TopMenuButton"; import { JRSTraInfoBox } from "@/components/Menu/JRSTraInfoBox"; import MapView, { Marker } from "react-native-maps"; import { CarouselBox } from "@/components/Menu/Carousel/CarouselBox"; import { CarouselTypeChanger } from "@/components/Menu/Carousel/CarouselTypeChanger"; import { useUserPosition } from "@/stateBox/useUserPosition"; import { AS } from "@/storageControl"; import { lineList_LineWebID } from "@/lib/getStationList"; import { StationProps } from "@/lib/CommonTypes"; import { LocationObject } from "expo-location"; configureReanimatedLogger({ level: ReanimatedLogLevel.error, // Set the log level to error strict: true, // Reanimated runs in strict mode by default }); type props = { scrollRef: React.RefObject; mapHeight: number; MapFullHeight: number; mapMode: boolean; setMapMode: React.Dispatch>; }; export const Menu: FC = (props) => { const { scrollRef, mapHeight, MapFullHeight, mapMode, setMapMode } = props; const { navigate } = useNavigation(); const { favoriteStation } = useFavoriteStation(); const { originalStationList, getStationDataFromNameBase } = useStationList(); const [stationListMode, setStationListMode] = useState< "position" | "favorite" >("position"); useEffect(() => { AS.getItem("stationListMode") .then((res) => setStationListMode(res)) .catch(() => { // AS.setItem("stationListMode", "position"); }); }, []); const mapsRef = useRef(null); const returnToTop = (bool = true) => { scrollRef?.current.scrollTo({ y: mapHeight > 80 ? mapHeight - 80 : 0, animated: bool, }); }; const goToMap = () => { scrollRef?.current.scrollTo({ y: 0, animated: true, }); }; useEffect(() => { setTimeout(() => { returnToTop(false); }, 10); }, [mapHeight]); const [scrollStartPosition, setScrollStartPosition] = useState(0); const onScrollBeginDrag = (e) => { LayoutAnimation.configureNext({ duration: 300, create: { type: LayoutAnimation.Types.easeInEaseOut, property: LayoutAnimation.Properties.opacity, }, update: { type: LayoutAnimation.Types.easeInEaseOut, property: LayoutAnimation.Properties.opacity, }, }); setScrollStartPosition(e.nativeEvent.contentOffset.y); setMapMode(false); }; //現在地基準の駅名標リストアップ機能 const { position, locationStatus } = useUserPosition(); const [nearPositionStation, setNearPositionStation] = useState< StationProps[][] >([]); //第三要素 useEffect(() => { if (!position) return () => {}; makeCurrentStation(position); }, [position, stationListMode]); const makeCurrentStation = (location: LocationObject) => { if (!originalStationList) return () => {}; const findStationEachLine = (selectLine) => { const searchArea = 0.055; //検索範囲 const _calcDistance = (from, to) => { let lat = Math.abs(from.lat - to.lat); let lng = Math.abs(from.lng - to.lng); return Math.sqrt(lat * lat + lng * lng); }; let NearStation = selectLine.filter( (d) => _calcDistance(d, { lat: location.coords.latitude, lng: location.coords.longitude, }) < searchArea ); //NearStationを距離の近い順にソート NearStation.sort((a, b) => { return ( _calcDistance(a, { lat: location.coords.latitude, lng: location.coords.longitude, }) - _calcDistance(b, { lat: location.coords.latitude, lng: location.coords.longitude, }) ); }); return NearStation; }; let _stList: StationProps[] = lineList .map((d) => findStationEachLine(originalStationList[d])) .filter((d) => d.length > 0) .reduce((pre, current) => { pre.push(...current); return pre; }, []); if (_stList.length == 0) setNearPositionStation([]); else { console.log("hoge"); console.log(_stList); let returnData: StationProps[][] = []; _stList.forEach((d, index, array) => { const stationName = d.Station_JP; if (returnData.findIndex((d) => d[0].Station_JP == stationName) != -1) return; returnData.push(array.filter((d2) => d2.Station_JP == stationName)); }); //returnDataを距離の近い順にソート returnData.sort((a, b) => { const _calcDistance = (from, to) => { let lat = Math.abs(from.lat - to.lat); let lng = Math.abs(from.lng - to.lng); return Math.sqrt(lat * lat + lng * lng); }; return ( _calcDistance(a[0], { lat: location.coords.latitude, lng: location.coords.longitude, }) - _calcDistance(b[0], { lat: location.coords.latitude, lng: location.coords.longitude, }) ); }); setNearPositionStation(returnData); } }; const [listIndex, setListIndex] = useState(0); const [listUpStation, setListUpStation] = useState([]); const [isSearchMode, setisSearchMode] = useState(false); const [input, setInput] = useState(""); useLayoutEffect(() => { if (!!isSearchMode) { const returnData = []; if (!input || input == "") { Object.keys(lineList_LineWebID).forEach((d) => { originalStationList[d].forEach((D) => { if ( isSearchMode && isSearchMode != stationIDPair[lineList_LineWebID[d]] ) return; const latlng = [D.lat, D.lng]; if (latlng.length == 0) return null; if (D.StationNumber == undefined) { return null; } returnData.push([D]); }); }); } else { const hoge = getStationDataFromNameBase(input); hoge.forEach((d, index, array) => { const stationName = d.Station_JP; if ( returnData.findIndex((d1) => d1[0].Station_JP == stationName) != -1 ) return; returnData.push(array.filter((d2) => d2.Station_JP == stationName)); }); } if (JSON.stringify(returnData) == JSON.stringify(listUpStation)) return; console.log("returnData"); console.log(returnData); setListUpStation(returnData); } else if (stationListMode == "position") { const returnData = nearPositionStation.filter((d) => d != undefined); if (JSON.stringify(returnData) == JSON.stringify(listUpStation)) return; setListUpStation(returnData); } else { const returnData = favoriteStation.filter((d) => d != undefined); if (JSON.stringify(returnData) == JSON.stringify(listUpStation)) return; setListUpStation(returnData); } }, [nearPositionStation, favoriteStation, stationListMode, isSearchMode]); useEffect(() => { if (listUpStation.length == 0) { setListIndex(0); return; } if (listUpStation.length == 1) { setListIndex(0); return; } if (listUpStation[listIndex] == undefined) { const count = listIndex - 1; setMapMode(false); setListIndex(count); } }, [listIndex, listUpStation, isSearchMode]); useEffect(() => { if (originalStationList == undefined) 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((d) => ({ latitude: d[0].lat, longitude: d[0].lng, })), { edgePadding: { top: 80, bottom: 120, left: 50, right: 50 } } // Add margin values here ); } else { mapsRef.current.animateToRegion(mapRegion, 1000); } }, [listIndex, listUpStation]); return ( {!mapMode ? : <>} { if (e.nativeEvent.contentOffset.y < mapHeight - 80) { if (scrollStartPosition > e.nativeEvent.contentOffset.y) { goToMap(); } else { returnToTop(); } } }} > { LayoutAnimation.configureNext({ duration: 300, create: { type: LayoutAnimation.Types.easeInEaseOut, property: LayoutAnimation.Properties.opacity, }, update: { type: LayoutAnimation.Types.easeInEaseOut, property: LayoutAnimation.Properties.opacity, }, }); setMapMode(true); goToMap(); }} > {listUpStation.map(([{ lat, lng, StationNumber }], index) => ( { setMapMode(false); setListIndex(index); if (mapsRef.current) { mapsRef.current.animateToRegion( { latitude: lat, longitude: lng, latitudeDelta: 0.05, longitudeDelta: 0.05, }, 1000 ); } LayoutAnimation.configureNext({ duration: 300, create: { type: LayoutAnimation.Types.easeInEaseOut, property: LayoutAnimation.Properties.opacity, }, update: { type: LayoutAnimation.Types.easeInEaseOut, property: LayoutAnimation.Properties.opacity, }, }); returnToTop(); }} /> ))} {!mapMode && ( )} {originalStationList.length != 0 && ( <> {listUpStation[listIndex] && ( )} )} {mapMode && ( )} ); };