import React, { useRef, useState, useEffect } from "react"; import Carousel from "react-native-reanimated-carousel"; import { Platform, View, ScrollView, Linking, Text, TouchableOpacity, LayoutAnimation, Dimensions, } from "react-native"; import Constants from "expo-constants"; import * as Location from "expo-location"; import StatusbarDetect from "./StatusbarDetect"; import { widthPercentageToDP as wp } from "react-native-responsive-screen"; import { Ionicons } from "@expo/vector-icons"; import LottieView from "lottie-react-native"; import { parseAllTrainDiagram } from "./lib/parseAllTrainDiagram"; import trainList from "./assets/originData/trainList"; import LED_vision from "./components/発車時刻表/LED_vidion"; import Sign from "./components/駅名表/Sign"; import { TitleBar } from "./components/Menu/TitleBar"; import { FixedContentBottom } from "./components/Menu/FixedContentBottom"; import { UsefulBox } from "./components/atom/UsefulBox"; import { lineList } from "./lib/getStationList"; import useInterval from "./lib/useInterval"; import { HeaderConfig } from "./lib/HeaderConfig"; import { useFavoriteStation } from "./stateBox/useFavoriteStation"; import { SheetManager } from "react-native-actions-sheet"; import { useTrainDelayData } from "./stateBox/useTrainDelayData"; import { useNavigation } from "@react-navigation/native"; import { useStationList } from "./stateBox/useStationList"; import { StationNumber } from "./components/Menu/StationPagination"; import lineColorList from "./assets/originData/lineColorList"; import { AS } from "./storageControl"; import { SimpleDot } from "./components/Menu/SimpleDot"; export default function Menu({ getCurrentTrain }) { const { navigate } = useNavigation(); const { favoriteStation } = useFavoriteStation(); const { originalStationList } = useStationList(); //位置情報 const [locationStatus, setLocationStatus] = useState(null); useEffect(() => { if (Platform.OS == "web") return; Location.requestForegroundPermissionsAsync().then((data) => { setLocationStatus( Platform.OS == "ios" ? data.status == "granted" : data.android.accuracy == "fine" ); }); }, []); const getCurrentPosition = () => { if (!locationStatus) return () => {}; Location.getCurrentPositionAsync({}).then((location) => makeCurrentStation(location) ); }; const makeCurrentStation = (location) => { if (!originalStationList) return () => {}; const findStationEachLine = (selectLine) => { const searchArea = 0.002; 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 ); return NearStation; }; let returnDataBase = lineList .map((d) => findStationEachLine(originalStationList[d])) .filter((d) => d.length > 0) .reduce((pre, current) => { pre.push(...current); return pre; }, []); if (returnDataBase.length) { let currentStation = currentStation == undefined ? [] : currentStation; if (currentStation.toString() != returnDataBase.toString()) { setCurrentStation(returnDataBase); } } else { setCurrentStation(undefined); } }; useEffect(getCurrentPosition, [locationStatus]); useInterval(getCurrentPosition, 5000); const [currentStation, setCurrentStation] = useState(undefined); //第三要素 const carouselRef = useRef(); const [selectedCurrentStation, setSelectedCurrentStation] = useState(0); const [allStationData, setAllStationData] = useState([]); useEffect(() => { setAllStationData( [currentStation, ...favoriteStation].filter((d) => d != undefined) ); }, [currentStation, favoriteStation]); useEffect(() => { if (allStationData.length == 0) { setSelectedCurrentStation(0); return; } if (allStationData[selectedCurrentStation] == undefined) { const count = selectedCurrentStation - 1; setSelectedCurrentStation(count); } }, [selectedCurrentStation, currentStation, allStationData]); useEffect(() => { if (!carouselRef.current) return; carouselRef?.current.scrollTo({ count: selectedCurrentStation - carouselRef.current.getCurrentIndex(), animated: true, }); }, [selectedCurrentStation]); //全列車ダイヤリストを作成するuseEffect const [trainDiagram, setTrainDiagram] = useState(null); // 全列車のダイヤを列番ベースで整理 useEffect(() => { //全列車リストを生成する副作用[無条件初回実行] setTrainDiagram(trainList); }, []); const oPSign = () => { const payload = { currentStation: originalStationList && allStationData.length != 0 && allStationData[selectedCurrentStation], navigate: navigate, goTo: "menu", useShow: () => SheetManager.show("StationDetailView", { payload }), onExit: () => SheetManager.hide("StationDetailView"), }; SheetManager.show("StationDetailView", { payload }); }; const [dotButton, setDotButton] = useState(false); useEffect(() => { AS.getItem("CarouselSettings/activeDotSettings").then((data) => { setDotButton(data === "true"); }); }, []); const oLPSign = () => { LayoutAnimation.configureNext({ duration: 600, update: { type: "spring", springDamping: 0.5 }, }); AS.setItem( "CarouselSettings/activeDotSettings", !dotButton ? "true" : "false" ); setDotButton(!dotButton); }; const width = Dimensions.get("window").width; return ( {originalStationList.length != 0 && allStationData.length != 0 && ( { return ( ); }} /> {originalStationList && allStationData.map((d, index) => { const active = index == selectedCurrentStation; const numberIndex = d[0].StationNumber; if (dotButton) { return ( setSelectedCurrentStation(index)} currentStation={d} active={active} index={numberIndex} /> ); } else { return ( setSelectedCurrentStation(index)} active={active} index={numberIndex} /> ); } })} )} {allStationData.length != 0 && originalStationList.length != 0 && allStationData[selectedCurrentStation] && ( {}} /> )} ); } const TopMenuButton = () => { const buttonList = [ { backgroundColor: "#F89038", icon: "train-car", onPress: () => Linking.openURL("https://www.jr-shikoku.co.jp/01_trainbus/sp/"), title: "駅・鉄道情報", }, { backgroundColor: "#EA4752", icon: "google-spreadsheet", onPress: () => Linking.openURL( "https://www.jr-shikoku.co.jp/01_trainbus/jikoku/sp/#mainprice-box" ), title: "運賃表", }, { backgroundColor: "#91C31F", icon: "clipboard-list-outline", onPress: () => Linking.openURL("https://www.jr-shikoku.co.jp/e5489/"), title: "予約", }, ]; return ( {buttonList.map((d, index) => ( {d.title} ))} ); }; const JRSTraInfoBox = () => { const { getTime, delayData, loadingDelayData, setLoadingDelayData } = useTrainDelayData(); const styles = { touch: { backgroundColor: "#0099CC", borderRadius: 5, margin: 10, borderColor: "black", borderWidth: 2, overflow: "hidden", }, scroll: { backgroundColor: "#0099CC", borderRadius: 5, maxHeight: 300, }, bottom: { position: "absolute", top: 250, alignItems: "center", width: "100%", height: 50, backgroundColor: "#007FCC88", }, box: { padding: 10, backgroundColor: "white", borderBottomLeftRadius: 5, borderBottomRightRadius: 5, }, }; return ( SheetManager.show("JRSTraInfo")} style={styles.touch} > 列車遅延速報EX {getTime ? getTime.toLocaleTimeString("ja-JP").split(":")[0] + ":" + getTime.toLocaleTimeString("ja-JP").split(":")[1] : NaN} { setLoadingDelayData(true); }} /> {loadingDelayData ? ( ) : delayData ? ( delayData.map((d, index, array) => { let data = d.split(" "); return ( {data[0].replace("\n", "")} {data[1]} {data[3]} ); }) ) : ( 現在、5分以上の遅れはありません。 )} 詳細を見る ); };