Files
jrshikoku/components/trainMenu.tsx

265 lines
9.1 KiB
TypeScript
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useRef, useState, useEffect, useLayoutEffect } from "react";
import { View, Text, TouchableOpacity, Linking, Platform } from "react-native";
import MapView, { Marker } from "react-native-maps";
import { useCurrentTrain } from "../stateBox/useCurrentTrain";
import { useNavigation } from "@react-navigation/native";
import lineColorList from "../assets/originData/lineColorList";
import { lineList_LineWebID, lineListPair, stationIDPair } from "../lib/getStationList";
import { SheetManager } from "react-native-actions-sheet";
import { useTrainMenu } from "../stateBox/useTrainMenu";
import { MapPin } from "./TrainMenu/MapPin";
import { UsefulBox } from "./TrainMenu/UsefulBox";
import { MapsButton } from "./TrainMenu/MapsButton";
import { useStationList } from "@/stateBox/useStationList";
import { useThemeColors } from "@/lib/theme";
import { useUserPosition } from "@/stateBox/useUserPosition";
const ANDROID_USER_LOCATION_MARKER_SIZE = 18;
const ANDROID_USER_LOCATION_INNER_SIZE = 8;
export default function TrainMenu({ style }) {
const { fixed, isDark } = useThemeColors();
const { webview } = useCurrentTrain();
const mapRef = useRef<any>(null);
const { navigate, goBack } = useNavigation<any>();
const [stationPin, setStationPin] = useState([]);
const {
selectedLine,
setSelectedLine,
mapsStationData: stationData,
} = useTrainMenu();
const { originalStationList } = useStationList();
const { position } = useUserPosition();
useEffect(() => {
const stationPinData = [];
Object.keys(lineList_LineWebID).forEach((d, indexBase) => {
originalStationList[d].forEach((D, index) => {
if (selectedLine && selectedLine != lineList_LineWebID[d]) return;
const latlng = [D.lat,D.lng];
if (latlng.length == 0) return null;
stationPinData.push({ D, d, latlng, indexBase: 0, index });
});
});
setStationPin(stationPinData);
}, [originalStationList, selectedLine]);
useLayoutEffect(() => {
mapRef?.current.fitToCoordinates(
stationPin.map(({ latlng }) => ({
latitude: parseFloat(latlng[0]),
longitude: parseFloat(latlng[1]),
})),
{ edgePadding: { top: 80, bottom: 120, left: 50, right: 50 } } // Add margin values here
);
}, [stationPin,mapRef]);
return (
<View style={{ height: "100%", backgroundColor: fixed.primary, ...style }}>
<MapView
style={{ flex: 1, width: "100%", height: "100%" }}
showsUserLocation={Platform.OS !== "android"}
loadingEnabled={true}
showsMyLocationButton={false}
moveOnMarkerPress={false}
showsCompass={false}
ref={mapRef}
userInterfaceStyle={isDark ? "dark" : "light"}
//provider={PROVIDER_GOOGLE}
initialRegion={{
latitude: 33.774519,
longitude: 133.533306,
latitudeDelta: 1.8, //小さくなるほどズーム
longitudeDelta: 1.8,
}}
>
{Platform.OS === "android" && position ? (
<Marker
key="android-user-location"
coordinate={{
latitude: position.coords.latitude,
longitude: position.coords.longitude,
}}
anchor={{ x: 0.5, y: 0.5 }}
tracksViewChanges={false}
zIndex={999}
>
<View
style={{
width: ANDROID_USER_LOCATION_MARKER_SIZE,
height: ANDROID_USER_LOCATION_MARKER_SIZE,
borderRadius: ANDROID_USER_LOCATION_MARKER_SIZE / 2,
backgroundColor: "rgba(10, 132, 255, 0.24)",
borderWidth: 1,
borderColor: "rgba(10, 132, 255, 0.42)",
alignItems: "center",
justifyContent: "center",
}}
>
<View
style={{
width: ANDROID_USER_LOCATION_INNER_SIZE,
height: ANDROID_USER_LOCATION_INNER_SIZE,
borderRadius: ANDROID_USER_LOCATION_INNER_SIZE / 2,
backgroundColor: "#0A84FF",
borderWidth: 1,
borderColor: "#ffffff",
}}
/>
</View>
</Marker>
) : null}
{stationPin.map(({ D, d, latlng, indexBase, index }) => (
<MapPin
index={index}
indexBase={indexBase}
latlng={latlng}
D={D}
d={d}
navigate={navigate}
webview={webview}
key={D.Station_JP + D.StationNumber + d}
/>
))}
</MapView>
<View style={{ position: "relative" }}>
<View
style={{
flexDirection: "row",
position: "absolute",
width: "100%" as any,
bottom: 0,
flex: 1,
}}
>
<TouchableOpacity
style={{
backgroundColor: selectedLine
? lineColorList[stationIDPair[selectedLine]]
: fixed.primary,
padding: 10,
zIndex: 1,
alignItems: "center",
position: "absolute",
bottom: 0,
width: "100%",
paddingBottom: 50,
}}
onPress={() => SheetManager.show("TrainMenuLineSelector")}
>
<Text
style={{
color: "white",
fontWeight: "bold",
fontSize: 10,
textAlign: "center",
}}
>
  ここを押して路線をフィルタリングできます  
</Text>
<Text
style={{
color: "white",
fontWeight: "bold",
fontSize: 20,
textAlign: "center",
}}
>
{selectedLine
? lineListPair[stationIDPair[selectedLine]]
: "JR四国 対象全駅"}
</Text>
</TouchableOpacity>
<Text style={{ position: "absolute", bottom: 40 }}>
路線記号からフィルタリング
</Text>
{Object.keys(stationData).map((d) => (
<TouchableOpacity
style={{
flex: 1,
backgroundColor: lineColorList[stationIDPair[d]],
padding: 5,
margin: 2,
borderRadius: 10,
borderColor: "white",
borderWidth: 1,
borderStyle: "solid",
alignItems: "center",
opacity: selectedLine == d ? 1 : !selectedLine ? 1 : 0.5,
zIndex: 10,
}}
onPress={() => {
const s = selectedLine == d ? undefined : d;
if(!s) return;
setSelectedLine(s);
Object.keys(stationData).forEach((data, indexBase) => {
stationData[data].forEach((D, index) => {
if (!D.StationMap) return null;
if (s && s != data) return;
const latlng = D.StationMap.replace(
"https://www.google.co.jp/maps/place/",
""
).split(",");
if (latlng.length == 0) return null;
if (index == 0 && stationPin.length > 0) {
webview.current
?.injectJavaScript(`MoveDisplayStation('${data}_${D.MyStation}_${D.Station_JP}');
document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");`);
}
});
});
}}
key={stationIDPair[d]}
>
<Text
style={{ color: "white", fontWeight: "bold", fontSize: 20 }}
>
{stationIDPair[d]}
</Text>
</TouchableOpacity>
))}
</View>
</View>
{navigate && (
<View style={{ flexDirection: "row" }}>
<UsefulBox
backgroundColor={"#F89038"}
icon="train-car"
flex={1}
onPressButton={() =>
navigate("howto", {
info: "https://xprocess.haruk.in/JR-shikoku-Apps-Common/info/train-position",
})
}
>
走行位置の見方
</UsefulBox>
<UsefulBox
backgroundColor={"#EA4752"}
icon="star"
flex={1}
onPressButton={() => navigate("favoriteList")}
>
お気に入り
</UsefulBox>
<UsefulBox
backgroundColor={"#91C31F"}
icon="clipboard-list-outline"
flex={1}
onPressButton={() =>
Linking.openURL(
"https://nexcloud.haruk.in/apps/forms/ZRHjWFF7znr5Xjr2"
)
}
>
フィードバック
</UsefulBox>
</View>
)}
<MapsButton
onPress={() => {
goBack();
}}
top={0}
mapSwitch={"flex"}
/>
</View>
);
}