Merge commit '59d7d425e5f52f547ac569aa7874fbd5adbefca1' into develop

This commit is contained in:
harukin-expo-dev-env 2025-07-08 16:27:33 +00:00
commit 54fba616b5
19 changed files with 497 additions and 90 deletions

View File

@ -1,6 +1,29 @@
{ {
"type": "FeatureCollection", "type": "FeatureCollection",
"features": [ "features": [
{
"properties": {
"name": "阿波池田",
"uri": "https://uedayou.net/jrslod/四国旅客鉄道/土讃線/阿波池田",
"color": "E25885"
},
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[133.80429, 34.02714],
[133.80515, 34.02656]
]
}
},
{
"properties": {
"name": "阿波池田",
"uri": "https://uedayou.net/jrslod/四国旅客鉄道/土讃線/阿波池田"
},
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [133.80429, 34.02714] }
},
{ {
"properties": { "properties": {
"name": "佃", "name": "佃",
@ -561,6 +584,29 @@
"type": "Feature", "type": "Feature",
"geometry": { "type": "Point", "coordinates": [134.53819, 34.08082] } "geometry": { "type": "Point", "coordinates": [134.53819, 34.08082] }
}, },
{
"properties": {
"name": "徳島",
"uri": "https://uedayou.net/jrslod/四国旅客鉄道/高徳線/徳島",
"color": "9ACD32"
},
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[134.55251, 34.07404],
[134.55049, 34.07498]
]
}
},
{
"properties": {
"name": "徳島",
"uri": "https://uedayou.net/jrslod/四国旅客鉄道/高徳線/徳島"
},
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [134.55251, 34.07404] }
},
{ {
"properties": { "properties": {
"name": "徳島線", "name": "徳島線",

View File

@ -33,7 +33,7 @@ export const LandscapeTrainInfo = (props) => {
stickyHeaderIndices={[1]} stickyHeaderIndices={[1]}
scrollEventThrottle={16} scrollEventThrottle={16}
onScroll={(d) => { onScroll={(d) => {
console.log(d.nativeEvent.contentOffset.y); // Handle scroll events
}} }}
> >
<View style={{ height: 0 }} /> <View style={{ height: 0 }} />

View File

@ -51,7 +51,6 @@ export const TrainIconStatus: FC<Props> = ({ data, navigate, from }) => {
) )
.then((d) => d.json()) .then((d) => d.json())
.then((d) => { .then((d) => {
console.log(d);
if (d.trainStatus == "") { if (d.trainStatus == "") {
//setAnpanmanStatus({name:"checkmark-circle-outline",color:"blue"}); //setAnpanmanStatus({name:"checkmark-circle-outline",color:"blue"});
} else if (d.trainStatus == "▲") { } else if (d.trainStatus == "▲") {
@ -76,7 +75,6 @@ export const TrainIconStatus: FC<Props> = ({ data, navigate, from }) => {
) )
.then((d) => d.json()) .then((d) => d.json())
.then((d) => { .then((d) => {
console.log(d);
if (d.trainStatus == "") { if (d.trainStatus == "") {
//setAnpanmanStatus({name:"checkmark-circle-outline",color:"blue"}); //setAnpanmanStatus({name:"checkmark-circle-outline",color:"blue"});
} else if (d.trainStatus == "▲") { } else if (d.trainStatus == "▲") {

View File

@ -18,6 +18,7 @@ import { TrainBusButton } from "./StationDeteilView/TrainBusButton";
import { 駅構内図 } from "./StationDeteilView/StationInsideMapButton"; import { 駅構内図 } from "./StationDeteilView/StationInsideMapButton";
import { WebSiteButton } from "./StationDeteilView/WebSiteButton"; import { WebSiteButton } from "./StationDeteilView/WebSiteButton";
import { StationTimeTableButton } from "./StationDeteilView/StationTimeTableButton"; import { StationTimeTableButton } from "./StationDeteilView/StationTimeTableButton";
import { StationTrainPositionButton } from "./StationDeteilView/StationTrainPositionButton";
export const StationDeteilView = (props) => { export const StationDeteilView = (props) => {
if (!props.payload) return <></>; if (!props.payload) return <></>;
@ -104,16 +105,23 @@ export const StationDeteilView = (props) => {
} }
/> />
</View> </View>
{currentStation[0].JrHpUrl && <View style={{ flexDirection: "row" }}>
currentStation[0].StationNumber != "M12" && ( <StationTrainPositionButton
<駅構内図 //児島例外/ stationNumber={currentStation[0].StationNumber}
navigate={navigate} onExit={onExit}
goTo={goTo} navigate={navigate}
useShow={useShow} />
address={currentStation[0].JrHpUrl} {currentStation[0].JrHpUrl &&
onExit={onExit} currentStation[0].StationNumber != "M12" && (
/> <駅構内図 //児島例外/
)} navigate={navigate}
goTo={goTo}
useShow={useShow}
address={currentStation[0].JrHpUrl}
onExit={onExit}
/>
)}
</View>
<View style={{ flexDirection: "row" }}> <View style={{ flexDirection: "row" }}>
{!currentStation[0].JrHpUrl || ( {!currentStation[0].JrHpUrl || (
<WebSiteButton <WebSiteButton
@ -135,7 +143,12 @@ export const StationDeteilView = (props) => {
useShow={useShow} useShow={useShow}
/> />
)} )}
<StationMapButton stationMap={currentStation[0].StationMap || `https://www.google.co.jp/maps/place/${currentStation[0].lat},${currentStation[0].lng}`} /> <StationMapButton
stationMap={
currentStation[0].StationMap ||
`https://www.google.co.jp/maps/place/${currentStation[0].lat},${currentStation[0].lng}`
}
/>
{!trainBus || ( {!trainBus || (
<TrainBusButton <TrainBusButton
address={trainBus.address} address={trainBus.address}

View File

@ -19,6 +19,7 @@ export const 駅構内図:FC<Props> = (props) => {
alignContent: "center", alignContent: "center",
alignItems: "center", alignItems: "center",
margin: 2, margin: 2,
flex: 1,
}} }}
onPress={() => { onPress={() => {
navigate("howto", { info, goTo, useShow }); navigate("howto", { info, goTo, useShow });

View File

@ -0,0 +1,54 @@
import { FC } from "react";
import { TouchableOpacity, View, Text, Linking } from "react-native";
import { useStationList } from "@/stateBox/useStationList";
import { useCurrentTrain } from "@/stateBox/useCurrentTrain";
import AntDesign from "react-native-vector-icons/AntDesign";
type Props = {
stationNumber: string;
onExit: () => void;
navigate?: (screen: string, params: { screen: string }) => void;
};
export const StationTrainPositionButton: FC<Props> = (props) => {
const { stationNumber, onExit, navigate } = props;
const {
inject,
} = useCurrentTrain();
const { getInjectJavascriptAddress } = useStationList();
return (
<TouchableOpacity
style={{
height: 50,
backgroundColor: "#0099CC",
flexDirection: "row",
alignContent: "center",
alignItems: "center",
margin: 2,
flex: 1
}}
onPress={() => {
navigate("positions", { screen: "Apps" });
const script = getInjectJavascriptAddress(stationNumber);
inject(script);
onExit();
}}
>
<View style={{ flex: 1 }} />
<AntDesign
name={"barchart"}
size={20}
color={"white"}
style={{ marginHorizontal: 5, marginVertical: 5 }}
/>
<Text
style={{
color: "white",
textAlign: "center",
textAlignVertical: "center",
}}
>
</Text>
<View style={{ flex: 1 }} />
</TouchableOpacity>
);
};

View File

@ -139,7 +139,7 @@ export const AppsWebView = ({ openStationACFromEachTrainInfo }) => {
if (favoriteStation.length < 1) return () => {}; if (favoriteStation.length < 1) return () => {};
const string = getInjectJavascriptAddress(favoriteStation[0][0].StationNumber); const string = getInjectJavascriptAddress(favoriteStation[0][0].StationNumber);
if (!string) return () => {}; if (!string) return () => {};
webview.current?.injectJavaScript(string); webview?.current.injectJavaScript(string);
once = true; once = true;
}; };

View File

@ -1,7 +1,14 @@
import Sign from "@/components/駅名表/Sign"; import Sign from "@/components/駅名表/Sign";
import React, { useEffect, useRef, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
import { AS } from "@/storageControl"; import { AS } from "@/storageControl";
import { useWindowDimensions, View, LayoutAnimation } from "react-native"; import {
useWindowDimensions,
View,
LayoutAnimation,
TouchableOpacity,
Text,
ScrollView,
} from "react-native";
import Carousel, { ICarouselInstance } from "react-native-reanimated-carousel"; import Carousel, { ICarouselInstance } from "react-native-reanimated-carousel";
import { SheetManager } from "react-native-actions-sheet"; import { SheetManager } from "react-native-actions-sheet";
import { StationNumber } from "../StationPagination"; import { StationNumber } from "../StationPagination";
@ -13,10 +20,22 @@ export const CarouselBox = ({
setListIndex, setListIndex,
listIndex, listIndex,
navigate, navigate,
stationListMode,
}) => { }) => {
const carouselRef = useRef<ICarouselInstance>(null); const carouselRef = useRef<ICarouselInstance>(null);
const { height, width } = useWindowDimensions(); const { height, width } = useWindowDimensions();
const [dotButton, setDotButton] = useState(false); const [dotButton, setDotButton] = useState(false);
const carouselBadgeScrollViewRef = useRef<ScrollView>(null);
useEffect(() => {
if (!carouselBadgeScrollViewRef.current) return;
const dotSize = dotButton ? 28 : 24;
const scrollToIndex = dotSize * listIndex - width / 2 + dotSize - 5;
carouselBadgeScrollViewRef.current.scrollTo({
x: scrollToIndex,
animated: true,
});
}, [listIndex, dotButton, width, carouselBadgeScrollViewRef]);
const oPSign = () => { const oPSign = () => {
const payload = { const payload = {
currentStation: listUpStation[listIndex], currentStation: listUpStation[listIndex],
@ -46,13 +65,6 @@ export const CarouselBox = ({
setDotButton(data === "true"); setDotButton(data === "true");
}); });
}, []); }, []);
useEffect(() => {
if (!carouselRef.current) return;
carouselRef?.current.scrollTo({
count: listIndex - carouselRef.current.getCurrentIndex(),
animated: true,
});
}, [listIndex]);
const RenderItem = ({ item, index }) => { const RenderItem = ({ item, index }) => {
return ( return (
<View <View
@ -66,12 +78,38 @@ export const CarouselBox = ({
key={item[0].StationNumber} key={item[0].StationNumber}
> >
<View style={{ flex: 1 }} /> <View style={{ flex: 1 }} />
<Sign {item[0].StationNumber != "null" ? (
stationID={item[0].StationNumber} <Sign
isCurrentStation={item == nearPositionStation} stationID={item[0].StationNumber}
oP={oPSign} isCurrentStation={item == nearPositionStation}
oLP={oLPSign} oP={oPSign}
/> oLP={oLPSign}
/>
) : (
<TouchableOpacity
style={{
width: width * 0.8,
height: ((width * 0.8) / 20) * 9,
borderColor: "#0099CC",
borderWidth: 1,
backgroundColor: "white",
}}
>
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
}}
>
<Text style={{ color: "#0099CC", fontSize: 20 }}>
{stationListMode == "position"
? "現在地の近くに駅がありません。"
: "お気に入りリストがありません。お気に入りの駅を追加しよう!"}
</Text>
</View>
</TouchableOpacity>
)}
<View style={{ flex: 1 }} /> <View style={{ flex: 1 }} />
</View> </View>
); );
@ -80,7 +118,11 @@ export const CarouselBox = ({
<View style={{ flex: 1, paddingTop: 10 }}> <View style={{ flex: 1, paddingTop: 10 }}>
<Carousel <Carousel
ref={carouselRef} ref={carouselRef}
data={listUpStation} data={
listUpStation.length > 0
? listUpStation
: [[{ StationNumber: "null" }]]
}
height={(((width / 100) * 80) / 20) * 9 + 10} height={(((width / 100) * 80) / 20) * 9 + 10}
pagingEnabled={true} pagingEnabled={true}
snapEnabled={true} snapEnabled={true}
@ -93,15 +135,29 @@ export const CarouselBox = ({
parallaxScrollingOffset: 100, parallaxScrollingOffset: 100,
parallaxAdjacentItemScale: 0.8, parallaxAdjacentItemScale: 0.8,
}} }}
scrollAnimationDuration={600}
onSnapToItem={setListIndex} onSnapToItem={setListIndex}
renderItem={RenderItem} renderItem={RenderItem}
overscrollEnabled={false}
defaultIndex={listIndex >= listUpStation.length ? 0 : listIndex}
/> />
<View <ScrollView
style={{ horizontal
showsHorizontalScrollIndicator={false}
contentContainerStyle={{
flexDirection: "row", flexDirection: "row",
justifyContent: "center", justifyContent: "center",
alignContent: "center", alignContent: "center",
alignItems: "center", alignItems: "center",
paddingVertical: 2,
paddingHorizontal: 10,
minWidth: width,
}}
ref={(scrollViewRef) => {
// ScrollViewのrefを保存
if (scrollViewRef) {
carouselBadgeScrollViewRef.current = scrollViewRef;
}
}} }}
> >
{originalStationList && {originalStationList &&
@ -123,7 +179,7 @@ export const CarouselBox = ({
/> />
); );
})} })}
</View> </ScrollView>
</View> </View>
); );
}; };

View File

@ -1,21 +1,34 @@
import { AS } from "@/storageControl"; import { AS } from "@/storageControl";
import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs"; import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs";
import React, { useEffect, useRef } from "react"; import React, { useEffect, useRef } from "react";
import { View, TouchableOpacity, Text, LayoutAnimation } from "react-native"; import { useWindowDimensions } from "react-native";
import {
View,
TouchableOpacity,
Text,
LayoutAnimation,
KeyboardAvoidingView,
Platform,
} from "react-native";
import Ionicons from "react-native-vector-icons/Ionicons"; import Ionicons from "react-native-vector-icons/Ionicons";
import { SearchUnitBox } from "@/components/Menu/RailScope/SearchUnitBox";
export const CarouselTypeChanger = ({ export const CarouselTypeChanger = ({
locationStatus, locationStatus,
position, position,
mapsRef, mapsRef,
scrollRef,
stationListMode, stationListMode,
setStationListMode, setStationListMode,
setSelectedCurrentStation, setSelectedCurrentStation,
mapMode, mapMode,
setMapMode, setMapMode,
isSearchMode,
setisSearchMode,
}) => { }) => {
const tabBarHeight = useBottomTabBarHeight(); const tabBarHeight = useBottomTabBarHeight();
const returnToDefaultMode = ()=>{ const { height, width } = useWindowDimensions();
const returnToDefaultMode = () => {
LayoutAnimation.configureNext({ LayoutAnimation.configureNext({
duration: 300, duration: 300,
create: { create: {
@ -28,13 +41,32 @@ export const CarouselTypeChanger = ({
}, },
}); });
setMapMode(false); setMapMode(false);
} };
return ( return (
<View style={{ width: "100%", height: 40, flexDirection: "row", position: mapMode ? "absolute" : "relative", bottom: mapMode ? 0 : undefined}} key={"carouselTypeChanger"} > <KeyboardAvoidingView
behavior="padding"
keyboardVerticalOffset={80}
enabled={Platform.OS === "ios"}
style={{
width: "100%",
height: 40,
flexDirection: "row",
position: mapMode ? "absolute" : "relative",
bottom: mapMode ? 0 : undefined,
zIndex: 1000,
backgroundColor: "white",
}}
key={"carouselTypeChanger"}
>
<SearchUnitBox
isSearchMode={isSearchMode}
setisSearchMode={setisSearchMode}
/>
<TouchableOpacity <TouchableOpacity
style={{ style={{
flex: 1, flex: 1,
backgroundColor: stationListMode == "position" ? "#0099CC" : "#0099CC80", backgroundColor:
stationListMode == "position" ? "#0099CC" : "#0099CC80",
padding: 5, padding: 5,
alignItems: "center", alignItems: "center",
flexDirection: "row", flexDirection: "row",
@ -45,8 +77,7 @@ export const CarouselTypeChanger = ({
borderBottomRightRadius: mapMode ? 0 : 20, borderBottomRightRadius: mapMode ? 0 : 20,
}} }}
disabled={!locationStatus} disabled={!locationStatus}
onPressIn={() => {
onPressIn={() =>{
if (!position) return; if (!position) return;
returnToDefaultMode(); returnToDefaultMode();
setStationListMode("position"); setStationListMode("position");
@ -99,7 +130,8 @@ export const CarouselTypeChanger = ({
<TouchableOpacity <TouchableOpacity
style={{ style={{
flex: 1, flex: 1,
backgroundColor: stationListMode == "favorite" ? "#0099CC" : "#0099CC80", backgroundColor:
stationListMode == "favorite" ? "#0099CC" : "#0099CC80",
padding: 5, padding: 5,
alignItems: "center", alignItems: "center",
flexDirection: "row", flexDirection: "row",
@ -137,6 +169,6 @@ export const CarouselTypeChanger = ({
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
</View> </KeyboardAvoidingView>
); );
}; };

View File

@ -0,0 +1,114 @@
import React from "react";
import {
TouchableOpacity,
Text,
View,
LayoutAnimation,
TextInput,
KeyboardAvoidingView,
Platform,
} from "react-native";
import Ionicons from "react-native-vector-icons/Ionicons";
import { useWindowDimensions } from "react-native";
import lineColorList from "@/assets/originData/lineColorList";
import { lineList_LineWebID, stationIDPair } from "@/lib/getStationList";
export const SearchUnitBox = ({ isSearchMode, setisSearchMode }) => {
const { height, width } = useWindowDimensions();
return (
<>
<TouchableOpacity
style={{
position: "absolute",
bottom: !!isSearchMode ? 0 : 60,
right: 0,
padding: !!isSearchMode ? 5 : 10,
margin: !!isSearchMode ? 0 : 10,
backgroundColor: "#0099CC",
borderRadius: !!isSearchMode ? 5 : 50,
width: !!isSearchMode ? width : 50,
zIndex: 1000,
}}
disabled={!!isSearchMode}
onPress={() => {
LayoutAnimation.configureNext({
duration: 100,
update: { type: "easeInEaseOut", springDamping: 0.6 },
});
setisSearchMode(true);
}}
>
{!isSearchMode && <Ionicons name="search" size={30} color="white" />}
{!!isSearchMode && (
<View style={{ backgroundColor: "#0099CC" }}>
<View style={{ flexDirection: "row", alignItems: "center" }}>
<TouchableOpacity onPress={() => {
LayoutAnimation.configureNext({
duration: 100,
update: { type: "easeInEaseOut", springDamping: 0.6 },
});
setisSearchMode(false);
}}>
<Ionicons
name="arrow-back"
size={20}
color="white"
style={{ marginRight: 10 }}
/>
</TouchableOpacity>
{Object.keys(lineList_LineWebID).map((d) => (
<TouchableOpacity
style={{
flex: 1,
backgroundColor: lineColorList[stationIDPair[lineList_LineWebID[d]]],
padding: 5,
marginHorizontal: 2,
borderRadius: 10,
borderColor: "white",
borderWidth: 1,
borderStyle: "solid",
alignItems: "center",
opacity: isSearchMode == stationIDPair[lineList_LineWebID[d]] ? 1 : !isSearchMode ? 1 : 0.5,
zIndex: 10,
}}
onPress={() => {
const id = stationIDPair[lineList_LineWebID[d]];
const s = isSearchMode == id ? undefined : id;
if (!s) return;
setisSearchMode(s);
}}
key={stationIDPair[lineList_LineWebID[d]]}
>
<Text
style={{ color: "white", fontWeight: "bold", fontSize: 20 }}
>
{stationIDPair[lineList_LineWebID[d]]}
</Text>
</TouchableOpacity>
))}
{/* <View
style={{
backgroundColor: "white",
borderRadius: 25,
height: 30,
paddingRight: 10,
paddingLeft: 10,
flex: 1,
}}
>
<TextInput
placeholder="駅名を入力してフィルタリングします。"
//onFocus={() => setKeyBoardVisible(true)}
onEndEditing={() => {}}
//onChange={(ret) => setInput(ret.nativeEvent.text)}
//value={input}
style={{ flex: 1 }}
/>
</View> */}
</View>
</View>
)}
</TouchableOpacity>
</>
);
};

View File

@ -8,7 +8,6 @@ import { AS } from "../../../storageControl";
export const FavoriteSettingsItem = ({ currentStation }) => { export const FavoriteSettingsItem = ({ currentStation }) => {
const lineIDs = []; const lineIDs = [];
const EachIDs = []; const EachIDs = [];
console.log(currentStation);
currentStation.forEach((d) => { currentStation.forEach((d) => {
if (!d.StationNumber) return; if (!d.StationNumber) return;
const textArray = d.StationNumber.split(""); const textArray = d.StationNumber.split("");

View File

@ -24,7 +24,7 @@ export default function TrainMenu({ style }) {
const { originalStationList } = useStationList(); const { originalStationList } = useStationList();
useEffect(() => { useEffect(() => {
const stationPinData = []; const stationPinData = [];
Object.keys(originalStationList).forEach((d, indexBase) => { Object.keys(lineList_LineWebID).forEach((d, indexBase) => {
originalStationList[d].forEach((D, index) => { originalStationList[d].forEach((D, index) => {
if (selectedLine && selectedLine != lineList_LineWebID[d]) return; if (selectedLine && selectedLine != lineList_LineWebID[d]) return;
const latlng = [D.lat,D.lng]; const latlng = [D.lat,D.lng];
@ -35,14 +35,14 @@ export default function TrainMenu({ style }) {
setStationPin(stationPinData); setStationPin(stationPinData);
}, [originalStationList, selectedLine]); }, [originalStationList, selectedLine]);
useLayoutEffect(() => { useLayoutEffect(() => {
mapRef.current.fitToCoordinates( mapRef?.current.fitToCoordinates(
stationPin.map(({ latlng }) => ({ stationPin.map(({ latlng }) => ({
latitude: parseFloat(latlng[0]), latitude: parseFloat(latlng[0]),
longitude: parseFloat(latlng[1]), longitude: parseFloat(latlng[1]),
})), })),
{ edgePadding: { top: 80, bottom: 120, left: 50, right: 50 } } // Add margin values here { edgePadding: { top: 80, bottom: 120, left: 50, right: 50 } } // Add margin values here
); );
}, [stationPin]); }, [stationPin,mapRef]);
return ( return (
<View style={{ height: "100%", backgroundColor: "#0099CC", ...style }}> <View style={{ height: "100%", backgroundColor: "#0099CC", ...style }}>
<MapView <MapView
@ -70,7 +70,7 @@ export default function TrainMenu({ style }) {
d={d} d={d}
navigate={navigate} navigate={navigate}
webview={webview} webview={webview}
key={D.StationNumber + d} key={D.Station_JP + D.StationNumber + d}
/> />
))} ))}
</MapView> </MapView>
@ -161,6 +161,7 @@ export default function TrainMenu({ style }) {
}); });
}); });
}} }}
key={stationIDPair[d]}
> >
<Text <Text
style={{ color: "white", fontWeight: "bold", fontSize: 20 }} style={{ color: "white", fontWeight: "bold", fontSize: 20 }}

View File

@ -25,22 +25,6 @@ export const Header = ({ station }) => {
}} }}
> >
<View style={{ flex: 1, flexDirection: "column", alignItems: "center" }}> <View style={{ flex: 1, flexDirection: "column", alignItems: "center" }}>
<AntDesign
name={"barchart"}
size={20}
color={"white"}
style={{
borderWidth: 1,
borderColor: "white",
padding: 10,
borderRadius: 10,
}}
onPress={() => {
navigate("positions", { screen: "Apps" });
const script = getInjectJavascriptAddress(station.StationNumber);
inject(script);
}}
/>
</View> </View>
<View style={{}}> <View style={{}}>
<Text style={{ fontSize: 25, color: "white", fontWeight: "bold" }}> <Text style={{ fontSize: 25, color: "white", fontWeight: "bold" }}>

View File

@ -211,15 +211,11 @@ export const getStationList = async () => {
, ,
stationList["日英対応表"] stationList["日英対応表"]
); );
const tokushimaCurrent = addStationPosition( stationList["徳島線(徳島-阿波池田間)[B]"] = addStationPosition(
concatBetweenStations(stationList["徳島線(徳島-阿波池田間)[B]"]), concatBetweenStations(stationList["徳島線(徳島-阿波池田間)[B]"]),
, ,
stationList["日英対応表"] stationList["日英対応表"]
); );
stationList["徳島線(徳島-阿波池田間)[B]"] = [
tokushimaCurrent[tokushimaCurrent.length - 1],
...tokushimaCurrent,
];
stationList["徳島線(徳島-阿波池田間)[B]"].pop(); stationList["徳島線(徳島-阿波池田間)[B]"].pop();
stationList["瀬戸大橋線(児島-宇多津間)[M]"] = [ stationList["瀬戸大橋線(児島-宇多津間)[M]"] = [
{ {

View File

@ -5,7 +5,7 @@ type nameString =
| "SPCL" | "SPCL"
| "Normal" | "Normal"
| string; | string;
type colorString = "aqua" | "red" | "#297bff" | "white"; type colorString = "aqua" | "red" | "#297bff" | "white" | "pink";
type trainTypeString = type trainTypeString =
| "快速" | "快速"
| "特急" | "特急"
@ -28,7 +28,7 @@ export const getTrainType: getTrainType = (nameString) => {
case "LTDEXP": case "LTDEXP":
return { color: "red", name: "特急", data: "express" }; return { color: "red", name: "特急", data: "express" };
case "NightLTDEXP": case "NightLTDEXP":
return { color: "red", name: "寝台特急", data: "express" }; return { color: "pink", name: "寝台特急", data: "express" };
case "SPCL": case "SPCL":
case "SPCL_Rapid": case "SPCL_Rapid":
case "SPCL_EXP": case "SPCL_EXP":

View File

@ -1055,6 +1055,8 @@ export const injectJavascriptData: InjectJavascriptData = (
const nameReplace = (,,,hasProblem) =>{ const nameReplace = (,,,hasProblem) =>{
let isWanman = false; let isWanman = false;
let trainName = ""; let trainName = "";
let trainType = "";
let trainTypeColor = "black";
let viaData = ""; let viaData = "";
let ToData = ""; let ToData = "";
let TrainNumber = ; let TrainNumber = ;
@ -1262,7 +1264,43 @@ export const injectJavascriptData: InjectJavascriptData = (
getThrew(); getThrew();
if(trainDataList.find(e => e.id === ) !== undefined){ if(trainDataList.find(e => e.id === ) !== undefined){
const data = trainDataList.find(e => e.id === ); const data = trainDataList.find(e => e.id === );
//{id,isWanman,trainName,viaData,ToData} //{id,isWanman,trainName,viaData,ToData,TrainNumber,JRF,type,infoUrl,trainNumDistance,info,infogram}
trainType = (()=>{
switch(data.type){
case "Normal":
trainTypeColor = "black";
return "普通";
case "OneMan":
trainTypeColor = "black";
return "普通";
case "Freight":
trainTypeColor = "black";
return "貨物";
case "SPCL_Normal":
trainTypeColor = "#297bff";
return "臨時";
case "SPCL_Rapid":
trainTypeColor = "#297bff";
return "臨時快速";
case "SPCL_LTDEXP":
trainTypeColor = "#297bff";
return "臨時特急";
case "LTDEXP":
trainTypeColor = "red";
return "特急";
case "NightLTDEXP":
trainTypeColor = "rgb(211, 0, 176)";
return "寝台特急";
case "OneManRapid":
trainTypeColor = "rgba(0, 140, 255, 1)";
return "快速";
case "Rapid":
trainTypeColor = "rgba(0, 140, 255, 1)";
return "快速";
default:
return "";
}
})();
isWanman = data.isWanman; isWanman = data.isWanman;
if(data.trainName != ""){ if(data.trainName != ""){
trainName = data.trainName; trainName = data.trainName;
@ -1293,16 +1331,25 @@ export const injectJavascriptData: InjectJavascriptData = (
}); });
let getColors = []; let getColors = [];
if(stationLines.length === 0){ if(stationLines.length === 0){
getColors = ["#000"]; getColors = ["rgba(97, 96, 96, 0.81)"];
}else{ }else{
getColors = stationLines.map(e => GetLineBarColor(e)); getColors = stationLines.map(e => GetLineBarColor(e));
} }
let yosan2Color = undefined;
if(viaData == "(内子経由)"){
yosan2Color ="#F5AC13";
}
else if(viaData == "(海経由)"){
yosan2Color = "#9AA7D7";
}
const gradient = getColors.length > 1 ? "linear-gradient(130deg, " + getColors[0] + " 0%, "+ getColors[0]+"50%, "+ getColors[1]+"50%, " + getColors[1] + " 100%)" : getColors[0]; const gradient = getColors.length > 1 ? "linear-gradient(130deg, " + getColors[0] + " 0%, "+ getColors[0]+"50%, "+ getColors[1]+"50%, " + getColors[1] + " 100%)" : getColors[0];
.insertAdjacentHTML('beforebegin', "<p style='font-size:6px;padding:0;color:black;text-align:center;'>" + TrainNumber + (JRF ? "":"レ") + "</p>"); .insertAdjacentHTML('beforebegin', "<p style='font-size:6px;padding:0;color:black;text-align:center;'>" + TrainNumber + (JRF ? "":"レ") + "</p>");
.insertAdjacentHTML('beforebegin', "<p style='font-size:8px;font-weight:bold;padding:0;color: black;text-align:center;'>" + (isWanman ? "ワンマン " : "") + "</p>"); .insertAdjacentHTML('beforebegin', "<p style='font-size:8px;font-weight:bold;padding:0;color: black;text-align:center;'>" + (isWanman ? "ワンマン " : "") + "</p>");
.insertAdjacentHTML('beforebegin', "<p style='font-size:6px;font-weight:bold;padding:0;color: black;text-align:center;'>" + viaData + "</p>"); .insertAdjacentHTML('beforebegin', "<p style='font-size:6px;font-weight:bold;padding:0;color: black;text-align:center;border-bottom-style:solid;border-bottom-width: "+(!!yosan2Color ? "2px" : "0px")+";border-color:" + yosan2Color + "'>" + viaData + "</p>");
.insertAdjacentHTML('beforebegin', "<p style='font-size:8px;font-weight:bold;padding:0;color: black;text-align:center;'>" + trainName + "</p>"); .insertAdjacentHTML('beforebegin', "<p style='font-size:8px;font-weight:bold;padding:0;color: black;text-align:center;'>" + trainName + "</p>");
.insertAdjacentHTML('beforebegin', "<div style='width:100%;background:" + gradient + ";'><p style='font-size:10px;font-weight:bold;padding:0;margin:0;color:white;align-items:center;align-content:center;text-align:center;text-shadow:1px 1px 0px #00000030, -1px -1px 0px #00000030,-1px 1px 0px #00000030, 1px -1px 0px #00000030,1px 0px 0px #00000030, -1px 0px 0px #00000030,0px 1px 0px #00000030, 0px -1px 0px #00000030;'>" + (ToData ? ToData + "行" : ToData) + "</p></div>"); .insertAdjacentHTML('beforebegin', "<div style='width:100%;background:" + gradient + ";'><p style='font-size:10px;font-weight:bold;padding:0;margin:0;color:white;align-items:center;align-content:center;text-align:center;text-shadow:1px 1px 0px #00000030, -1px -1px 0px #00000030,-1px 1px 0px #00000030, 1px -1px 0px #00000030,1px 0px 0px #00000030, -1px 0px 0px #00000030,0px 1px 0px #00000030, 0px -1px 0px #00000030;'>" + (ToData ? ToData + "行" : ToData) + "</p></div>");
.insertAdjacentHTML('beforebegin', "<div style='width:100%;background:" + trainTypeColor + ";'><p style='font-size:10px;font-weight:bold;font-style:italic;padding:0;color: white;text-align:center;'>" + trainType + "</p></div>");
.insertAdjacentHTML('beforebegin', "<p style='font-size:8px;font-weight:bold;padding:0;text-align:center;color: "+(hasProblem ? "red":"black")+";'>" + (hasProblem ? "‼️停止中‼️" : "") + "</p>"); .insertAdjacentHTML('beforebegin', "<p style='font-size:8px;font-weight:bold;padding:0;text-align:center;color: "+(hasProblem ? "red":"black")+";'>" + (hasProblem ? "‼️停止中‼️" : "") + "</p>");
`: ` `: `
.insertAdjacentHTML('beforebegin', "<p style='font-size:10px;font-weight:bold;padding:0;color: black;'>" + returnText1 + "</p>"); .insertAdjacentHTML('beforebegin', "<p style='font-size:10px;font-weight:bold;padding:0;color: black;'>" + returnText1 + "</p>");
@ -1440,7 +1487,7 @@ const setStrings = () =>{
var = element.getElementsByTagName("p")[0]; var = element.getElementsByTagName("p")[0];
var = element.getAttribute('offclick').split('"')[1]; var = element.getAttribute('offclick').split('"')[1];
var = element.getAttribute('offclick').split('"')[3]; var = element.getAttribute('offclick').split('"')[3];
const trainData = trainPositionDatas.find(e => e.TrainNum == ); const trainData = trainPositionDatas.filter(e=>!(e.Pos && e.Pos.includes("予告窓"))).find(e => e.TrainNum == );
const hasProblem = probremsData.find((e)=>{ const hasProblem = probremsData.find((e)=>{
return e.TrainNum == trainData.TrainNum && e.Pos == trainData.Pos; return e.TrainNum == trainData.TrainNum && e.Pos == trainData.Pos;
}); });

95
menu.js
View File

@ -1,10 +1,12 @@
import React, { useRef, useState, useEffect } from "react"; import React, { useRef, useState, useEffect, useLayoutEffect } from "react";
import { import {
Platform, Platform,
View, View,
ScrollView, ScrollView,
useWindowDimensions, useWindowDimensions,
LayoutAnimation, LayoutAnimation,
Text,
TouchableOpacity,
} from "react-native"; } from "react-native";
import Constants from "expo-constants"; import Constants from "expo-constants";
import { import {
@ -17,7 +19,7 @@ import LED_vision from "./components/発車時刻表/LED_vidion";
import { TitleBar } from "./components/Menu/TitleBar"; import { TitleBar } from "./components/Menu/TitleBar";
import { FixedContentBottom } from "./components/Menu/FixedContentBottom"; import { FixedContentBottom } from "./components/Menu/FixedContentBottom";
import { lineList } from "./lib/getStationList"; import { lineList, stationIDPair } from "./lib/getStationList";
import { useFavoriteStation } from "./stateBox/useFavoriteStation"; import { useFavoriteStation } from "./stateBox/useFavoriteStation";
import { useNavigation } from "@react-navigation/native"; import { useNavigation } from "@react-navigation/native";
import { useStationList } from "./stateBox/useStationList"; import { useStationList } from "./stateBox/useStationList";
@ -30,6 +32,9 @@ import { CarouselBox } from "./components/Menu/Carousel/CarouselBox";
import { CarouselTypeChanger } from "./components/Menu/Carousel/CarouselTypeChanger"; import { CarouselTypeChanger } from "./components/Menu/Carousel/CarouselTypeChanger";
import { useUserPosition } from "./stateBox/useUserPosition"; import { useUserPosition } from "./stateBox/useUserPosition";
import { AS } from "./storageControl"; import { AS } from "./storageControl";
import { lineList_LineWebID } from "./lib/getStationList";
import { Ionicons } from "@expo/vector-icons";
import { SearchUnitBox } from "./components/Menu/RailScope/SearchUnitBox";
configureReanimatedLogger({ configureReanimatedLogger({
level: ReanimatedLogLevel.error, // Set the log level to error level: ReanimatedLogLevel.error, // Set the log level to error
strict: true, // Reanimated runs in strict mode by default strict: true, // Reanimated runs in strict mode by default
@ -167,24 +172,52 @@ export default function Menu(props) {
const [listIndex, setListIndex] = useState(0); const [listIndex, setListIndex] = useState(0);
const [listUpStation, setListUpStation] = useState([]); const [listUpStation, setListUpStation] = useState([]);
useEffect(() => { const [isSearchMode, setisSearchMode] = useState(false);
if (stationListMode == "position") { useLayoutEffect(() => {
setListUpStation(nearPositionStation.filter((d) => d != undefined)); if (!!isSearchMode) {
const returnData = [];
Object.keys(lineList_LineWebID).forEach((d, indexBase) => {
originalStationList[d].forEach((D, index) => {
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]);
});
});
if (JSON.stringify(returnData) == JSON.stringify(listUpStation)) return;
setListUpStation(returnData);
} else if (stationListMode == "position") {
const returnData = nearPositionStation.filter((d) => d != undefined);
if (JSON.stringify(returnData) == JSON.stringify(listUpStation)) return;
setListUpStation(returnData);
} else { } else {
setListUpStation(favoriteStation.filter((d) => d != undefined)); const returnData = favoriteStation.filter((d) => d != undefined);
if (JSON.stringify(returnData) == JSON.stringify(listUpStation)) return;
setListUpStation(returnData);
} }
}, [nearPositionStation, favoriteStation, stationListMode]); }, [nearPositionStation, favoriteStation, stationListMode, isSearchMode]);
useEffect(() => { useEffect(() => {
if (listUpStation.length == 0) { if (listUpStation.length == 0) {
setListIndex(0); setListIndex(0);
return; return;
} }
if (listUpStation.length == 1) {
setListIndex(0);
return;
}
if (listUpStation[listIndex] == undefined) { if (listUpStation[listIndex] == undefined) {
const count = listIndex - 1; const count = listIndex - 1;
setMapMode(false); setMapMode(false);
setListIndex(count); setListIndex(count);
} }
}, [listIndex, nearPositionStation, listUpStation]); }, [listIndex, listUpStation, isSearchMode]);
useEffect(() => { useEffect(() => {
if (originalStationList == undefined) return; if (originalStationList == undefined) return;
if (listUpStation.length == 0) return; if (listUpStation.length == 0) return;
@ -196,9 +229,18 @@ export default function Menu(props) {
latitudeDelta: 0.05, latitudeDelta: 0.05,
longitudeDelta: 0.05, longitudeDelta: 0.05,
}; };
if (mapMode) return; if (mapMode) {
mapsRef.current.animateToRegion(mapRegion, 1000); mapsRef?.current.fitToCoordinates(
}, [listIndex, nearPositionStation, listUpStation, mapsRef]); listUpStation.map((d) => ({
latitude: parseFloat(d[0].lat),
longitude: parseFloat(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 ( return (
<View <View
@ -209,16 +251,35 @@ export default function Menu(props) {
}} }}
> >
<StatusbarDetect /> <StatusbarDetect />
<TitleBar /> {!mapMode ? (
<TitleBar />
) : (
<></>
// <Text
// style={{
// fontSize: 30,
// color: "#0099CC",
// fontWeight: "bold",
// position: "absolute",
// top: 0,
// zIndex: 1000,
// fontStyle: "italic",
// }}
// >
// JRShikoku RailScope
// </Text>
)}
<ScrollView <ScrollView
ref={scrollRef} ref={scrollRef}
snapToStart={false} snapToStart={false}
snapToEnd={false} snapToEnd={false}
decelerationRate={"normal"} decelerationRate={"normal"}
snapToOffsets={[mapHeight - 80]} snapToOffsets={[mapHeight - 80]}
contentContainerStyle={{
position: "relative",
}}
onScrollBeginDrag={onScrollBeginDrag} onScrollBeginDrag={onScrollBeginDrag}
onScrollEndDrag={(e) => { onScrollEndDrag={(e) => {
console.log(e.nativeEvent.velocity);
if (e.nativeEvent.contentOffset.y < mapHeight - 80) { if (e.nativeEvent.contentOffset.y < mapHeight - 80) {
if (scrollStartPosition > e.nativeEvent.contentOffset.y) { if (scrollStartPosition > e.nativeEvent.contentOffset.y) {
goToMap(); goToMap();
@ -303,16 +364,19 @@ export default function Menu(props) {
locationStatus, locationStatus,
position, position,
mapsRef, mapsRef,
scrollRef,
stationListMode, stationListMode,
setStationListMode, setStationListMode,
setSelectedCurrentStation: setListIndex, setSelectedCurrentStation: setListIndex,
mapMode, mapMode,
setMapMode, setMapMode,
isSearchMode,
setisSearchMode,
}} }}
/> />
)} )}
{listUpStation.length != 0 && originalStationList.length != 0 && ( {originalStationList.length != 0 && (
<> <>
<CarouselBox <CarouselBox
{...{ {...{
@ -322,6 +386,7 @@ export default function Menu(props) {
setListIndex, setListIndex,
listIndex, listIndex,
navigate, navigate,
stationListMode,
}} }}
/> />
{listUpStation[listIndex] && ( {listUpStation[listIndex] && (
@ -349,6 +414,8 @@ export default function Menu(props) {
setSelectedCurrentStation: setListIndex, setSelectedCurrentStation: setListIndex,
mapMode, mapMode,
setMapMode, setMapMode,
isSearchMode,
setisSearchMode,
}} }}
/> />
)} )}

View File

@ -15,7 +15,7 @@ const initialState = {
currentTrainLoading: "loading", currentTrainLoading: "loading",
setCurrentTrainLoading: () => {}, setCurrentTrainLoading: () => {},
getCurrentTrain: () => {}, getCurrentTrain: () => {},
inject: () => {}, inject: (i) => {},
}; };
const CurrentTrainContext = createContext(initialState); const CurrentTrainContext = createContext(initialState);

View File

@ -92,7 +92,6 @@ export const StationListProvider: FC<Props> = ({ children }) => {
return; return;
} }
if (x.StationNumber == StationNumber) { if (x.StationNumber == StationNumber) {
console.log(originalStationList[d]);
if (!x.MyStation) findNearStations = true; if (!x.MyStation) findNearStations = true;
else bootStationList.push({ line: lineName, station: x }); else bootStationList.push({ line: lineName, station: x });
} }