Files
jrshikoku/menu.js
harukin-expo-dev-env 7232c40af1 menuの変数名を変更
2025-04-13 16:56:47 +00:00

227 lines
7.5 KiB
JavaScript

import React, { useRef, useState, useEffect } from "react";
import { Platform, View, ScrollView, useWindowDimensions } 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 } 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 from "react-native-maps";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs";
import { CarouselBox } from "./components/Menu/Carousel/CarouselBox";
import { CarouselTypeChanger } from "./components/Menu/Carousel/CarouselTypeChanger";
import { useUserPosition } from "./stateBox/useUserPosition";
configureReanimatedLogger({
level: ReanimatedLogLevel.error, // Set the log level to error
strict: true, // Reanimated runs in strict mode by default
});
export default function Menu({ getCurrentTrain, scrollRef }) {
const { navigate, addListener, isFocused } = useNavigation();
const { favoriteStation } = useFavoriteStation();
const { originalStationList } = useStationList();
const { height, width } = useWindowDimensions();
const { bottom, left, right, top } = useSafeAreaInsets();
const tabBarHeight = useBottomTabBarHeight();
const [mapsOpacity, setMapsOpacity] = useState(false);
const [stationListMode, setStationListMode] = useState(
/*<"position"|"favorite">*/ "position"
);
const mapsRef = useRef(null);
const MapHeight =
height -
tabBarHeight +
(Platform.OS == "android" ? Constants.statusBarHeight : 0) -
100 -
((((width / 100) * 80) / 20) * 9 + 10 + 30);
useEffect(() => {
setTimeout(() => {
if (scrollRef.current) {
scrollRef.current.scrollTo({
y: MapHeight - 80,
animated: false,
});
}
}, 10);
}, []);
//位置情報
const { position, locationStatus } = useUserPosition();
useEffect(() => {
if (!position) return () => {};
makeCurrentStation(position);
}, [position, stationListMode]);
const makeCurrentStation = (location) => {
if (!originalStationList) return () => {};
const findStationEachLine = (selectLine) => {
const searchArea = stationListMode == "position" ? 0.07 : 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) => {
return d.length > 0;
})
.reduce((pre, current) => {
pre.push(...current);
return pre;
}, []);
if (returnDataBase.length) {
let currentStation = currentStation == undefined ? [] : currentStation;
if (currentStation.toString() != returnDataBase.toString()) {
setNearPositionStation(returnDataBase);
}
} else {
setNearPositionStation(undefined);
}
};
const [nearPositionStation, setNearPositionStation] = useState(undefined); //第三要素
const carouselRef = useRef();
const [listIndex, setListIndex] = useState(0);
const [listUpStation, setListUpStation] = useState([]);
useEffect(() => {
if (stationListMode == "position") {
console.log(nearPositionStation);
setListUpStation([nearPositionStation].filter((d) => d != undefined));
} else {
setListUpStation(favoriteStation.filter((d) => d != undefined));
}
}, [nearPositionStation, favoriteStation, stationListMode]);
useEffect(() => {
if (listUpStation.length == 0) {
setListIndex(0);
return;
}
if (listUpStation[listIndex] == undefined) {
const count = listIndex - 1;
setListIndex(count);
}
}, [listIndex, nearPositionStation, listUpStation]);
useEffect(() => {
if (!carouselRef.current) return;
carouselRef?.current.scrollTo({
count: listIndex - carouselRef.current.getCurrentIndex(),
animated: true,
});
}, [listIndex]);
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,
};
mapsRef.current.animateToRegion(mapRegion, 1000);
}, [listIndex, nearPositionStation, listUpStation, mapsRef]);
return (
<View
style={{
height: "100%",
backgroundColor: "white",
paddingTop: Platform.OS == "ios" ? Constants.statusBarHeight : 0,
}}
>
<StatusbarDetect />
<TitleBar />
<ScrollView
ref={scrollRef}
snapToStart={false}
snapToEnd={false}
decelerationRate={"normal"}
onScroll={(d) => {
const scrollY = d.nativeEvent.contentOffset.y + 100;
setMapsOpacity(scrollY < MapHeight);
}}
snapToOffsets={[MapHeight - 80]}
>
<MapView
ref={mapsRef}
style={{ flex: 1, width: "100%", height: MapHeight }}
showsUserLocation={true}
loadingEnabled={true}
showsMyLocationButton={false}
moveOnMarkerPress={false}
showsCompass={false}
//provider={PROVIDER_GOOGLE}
initialRegion={{
latitude: 33.774519,
longitude: 133.533306,
latitudeDelta: 1.8, //小さくなるほどズーム
longitudeDelta: 1.8,
}}
onPress={() => alert("地図をタップ")}
/>
<CarouselTypeChanger
{...{
locationStatus,
position,
mapsRef,
stationListMode,
setStationListMode,
setSelectedCurrentStation: setListIndex,
}}
/>
{listUpStation.length != 0 && originalStationList.length != 0 && (
<>
<CarouselBox
{...{
originalStationList,
allStationData: listUpStation,
currentStation: nearPositionStation,
setSelectedCurrentStation: setListIndex,
carouselRef,
selectedCurrentStation: listIndex,
navigate,
}}
/>
{listUpStation[listIndex] && (
<LED_vision
station={listUpStation[listIndex]}
getCurrentTrain={getCurrentTrain}
navigate={navigate}
openStationACFromEachTrainInfo={() => {}}
/>
)}
</>
)}
<TopMenuButton />
<JRSTraInfoBox />
<FixedContentBottom navigate={navigate} />
</ScrollView>
</View>
);
}