Merge commit 'c8119e23731a23984f7aabfed0874a9a96303afd' into develop

This commit is contained in:
harukin-expo-dev-env
2025-09-19 04:34:37 +00:00
44 changed files with 1393 additions and 981 deletions

View File

@@ -1,5 +1,5 @@
import React, { useEffect } from "react";
import { Platform, UIManager } from "react-native";
import { Platform, UIManager, Text } from "react-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { AppContainer } from "./Apps";
import { UpdateAsync } from "./UpdateAsync";
@@ -35,7 +35,10 @@ export default function App() {
useEffect(() => {
UpdateAsync();
}, []);
if (Text.defaultProps == null) {
Text.defaultProps = {};
Text.defaultProps.allowFontScaling = false;
}
const ProviderTree = buildProvidersTree([
AllTrainDiagramProvider,
NotificationProvider,

View File

@@ -6,19 +6,19 @@ import Constants from "expo-constants";
import { Dimensions, StatusBar } from "react-native";
import { SheetManager } from "react-native-actions-sheet";
import { AS } from "./storageControl";
import TrainBase from "./components/trainbaseview";
import HowTo from "./howto";
import Menu from "./menu";
import News from "./components/news";
import Setting from "./components/Settings/settings";
import { useFavoriteStation } from "./stateBox/useFavoriteStation";
import { optionData } from "./lib/stackOption";
import AllTrainDiagramView from "./components/AllTrainDiagramView";
import { AS } from "@/storageControl";
import TrainBase from "@/components/trainbaseview";
import HowTo from "@/howto";
import { Menu } from "@/menu";
import News from "@/components/news";
import Setting from "@/components/Settings/settings";
import { useFavoriteStation } from "@/stateBox/useFavoriteStation";
import { optionData } from "@/lib/stackOption";
import AllTrainDiagramView from "@/components/AllTrainDiagramView";
import { useNavigation } from "@react-navigation/native";
import { news } from "./config/newsUpdate";
import { news } from "@/config/newsUpdate";
import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs";
import GeneralWebView from "./GeneralWebView";
import GeneralWebView from "@/GeneralWebView";
import { StationDiagramView } from "@/components/StationDiagram/StationDiagramView";
const Stack = createStackNavigator();
@@ -95,7 +95,7 @@ export function MenuPage() {
return unsubscribe;
}, [navigation, mapHeight, favoriteStation, setFavoriteStation]);
return (
<Stack.Navigator>
<Stack.Navigator id={null}>
<Stack.Screen
name="menu"
options={{

View File

@@ -50,7 +50,7 @@ export const Top = () => {
}, [addListener, mapSwitch]);
return (
<Stack.Navigator detachInactiveScreens={false}>
<Stack.Navigator id={null} detachInactiveScreens={false}>
<Stack.Screen
name="Apps"
options={{
@@ -68,7 +68,7 @@ export const Top = () => {
/>
<Stack.Screen
name="stDiagram"
options={{ ...optionData, gestureEnabled: false }}
options={{ ...optionData, gestureEnabled: false }}
component={StationDiagramView}
/>
<Stack.Screen name="howto" options={optionData} component={HowTo} />

View File

@@ -1,46 +0,0 @@
import React from "react";
import { View, Text, ScrollView, useWindowDimensions } from "react-native";
export const LandscapeTrainInfo = (props) => {
const { leftContent, topStickyContent, children, scrollHandlers } = props;
const { height, width } = useWindowDimensions();
return (
<View
style={{
flexDirection: "row",
backgroundColor: "blue",
width: width,
height: (height / 100) * 70,
marginBottom: 50,
}}
>
<View
style={{
flexDirection: "column",
height: (height / 100) * 70,
width: width / 2,
}}
>
{leftContent}
</View>
<ScrollView
{...scrollHandlers}
style={{
width: width / 2,
height: "auto",
}}
stickyHeaderIndices={[1]}
scrollEventThrottle={16}
onScroll={(d) => {
// Handle scroll events
}}
>
<View style={{ height: 0 }} />
<View style={{ flexDirection: "column" }} index={1}>
{topStickyContent}
</View>
{children}
</ScrollView>
</View>
);
};

View File

@@ -1,8 +1,15 @@
import React from "react";
import React, { FC } from "react";
import { ScrollView } from "react-native";
import { TrainDataView } from "./TrainDataView";
export const LongHeader = ({
import { trainDataType } from "@/lib/trainPositionTextArray";
type props = {
currentTrainData: trainDataType;
currentPosition: string[] | undefined;
nearTrainIDList: string[];
openTrainInfo: (f: string) => void;
navigate: (screen: string, data?: any) => void;
}
export const LongHeader:FC<props> = ({
currentTrainData,
currentPosition,
nearTrainIDList,

View File

@@ -1,8 +1,15 @@
import React from "react";
import React, { FC } from "react";
import { ScrollView } from "react-native";
import { TrainDataView } from "./TrainDataView";
export const ShortHeader = ({
import { trainDataType } from "@/lib/trainPositionTextArray";
type props = {
currentTrainData: trainDataType;
currentPosition: string[] | undefined;
nearTrainIDList: string[];
openTrainInfo: (f: string) => void;
navigate: (screen: string, data?: any) => void;
}
export const ShortHeader:FC<props> = ({
currentTrainData,
currentPosition,
nearTrainIDList,

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect } from "react";
import React, { useState, useEffect, FC } from "react";
import { View, TouchableOpacity, useWindowDimensions } from "react-native";
import { StateBox } from "./StateBox";
import { PositionBox } from "./PositionBox";
@@ -6,14 +6,23 @@ import { useDeviceOrientationChange } from "../../../stateBox/useDeviceOrientati
import { getStationList2 } from "../../../lib/getStationList";
import { useCurrentTrain } from "../../../stateBox/useCurrentTrain";
import { SheetManager } from "react-native-actions-sheet";
import { trainPosition } from "../../../lib/trainPositionTextArray";
import { trainDataType, trainPosition } from "@/lib/trainPositionTextArray";
import { StationPosPushDialog } from "../../発車時刻表/LED_inside_Component/TrainPositionDataPush";
import { getStationID } from "../../../lib/eachTrainInfoCoreLib/getStationData";
import { useStationList } from "../../../stateBox/useStationList";
import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
import { customTrainDataDetector } from "@/components/custom-train-data";
export const TrainDataView = ({
type props = {
currentTrainData: trainDataType;
currentPosition: string[] | undefined;
nearTrainIDList: string[];
openTrainInfo: (f: string) => void;
mode?: 0 | 1 | 2; //0:通常,1:コンパクト,2:横並び
navigate: (screen: string, data?: any) => void;
}
export const TrainDataView:FC<props> = ({
currentTrainData,
currentPosition,
nearTrainIDList,

View File

@@ -260,7 +260,10 @@ export const EachTrainInfoCore = ({
})
.catch(() => AS.setItem("trainPositionSwitch", "true"));
}, []);
const customTrainType = getTrainType({
type: customTrainDataDetector(data.trainNum, allCustomTrainData).type,
});
const openTrainInfo = (d) => {
const train = customTrainDataDetector(d, allCustomTrainData);
let TrainNumber = "";
@@ -269,12 +272,11 @@ export const EachTrainInfoCore = ({
parseInt(d.replace("M", "").replace("D", "")) - train.trainNumDistance;
TrainNumber = timeInfo + "号";
}
const limitedData = getTrainType({ type: train.type });
const payload = {
data: {
trainNum: d,
limited: `${getTrainType(train.type).data}:${
train.trainName
}${TrainNumber}`,
limited: `${limitedData.data}:${train.trainName}${TrainNumber}`,
},
navigate,
from: from == "LED" ? "LED2" : "NearTrainDiagramView",
@@ -332,9 +334,7 @@ export const EachTrainInfoCore = ({
style: {
maxHeight: isLandscape ? height - 94 : (height / 100) * 70,
backgroundColor:
getTrainType(
customTrainDataDetector(data.trainNum, allCustomTrainData).type
).data === "notService"
customTrainType.data === "notService"
? "#777777ff"
: "white",
},
@@ -367,9 +367,7 @@ export const EachTrainInfoCore = ({
/>
}
>
{getTrainType(
customTrainDataDetector(data.trainNum, allCustomTrainData).type
).data === "notService" && (
{customTrainType.data === "notService" && (
<Text style={{ backgroundColor: "#ffffffc2", fontWeight: "bold" }}>
この列車には乗車できません
</Text>
@@ -433,7 +431,7 @@ export const EachTrainInfoCore = ({
)}
{trainDataWidhThrough.map((i, index) =>
i.split(",")[1] == "提" ? (
<DataFromButton i={i} />
<DataFromButton i={i} key={i + "-data"} />
) : (
<EachStopList
{...{

View File

@@ -73,6 +73,7 @@ export const TrainMenuLineSelector = () => {
});
});
}}
key={d+"TrainMenuLineSelector"}
>
<View
style={{

View File

@@ -64,7 +64,7 @@ export default function AllTrainDiagramView() {
parseInt(d.replace("M", "").replace("D", "")) - train.trainNumDistance;
TrainNumber = timeInfo + "号";
}
const type = getTrainType(train.type).data;
const type = getTrainType({type:train.type}).data;
const limited = `${type}:${train.trainName}${TrainNumber}`;
const payload = {
data: { trainNum: d, limited },

View File

@@ -3,9 +3,11 @@ import { View, Platform } from "react-native";
import Constants from "expo-constants";
import { FixedTrain } from "./FixedPositionBox/FixedTrainBox";
import { FixedStation } from "./FixedPositionBox/FixedStationBox";
import { useState } from "react";
export const FixedPositionBox = () => {
const { fixedPosition, setFixedPosition } = useCurrentTrain();
const [displaySize, setDisplaySize] = useState(50);
return (
<View
@@ -15,17 +17,24 @@ export const FixedPositionBox = () => {
borderRadius: 5,
zIndex: 1500,
width: "100%",
height: 50,
height: displaySize,
flexDirection: "row",
}}
>
{fixedPosition.type === "station" && (
<FixedStation stationID={fixedPosition.value} />
<FixedStation
stationID={fixedPosition.value}
displaySize={displaySize}
setDisplaySize={setDisplaySize}
/>
)}
{fixedPosition.type === "train" && (
<FixedTrain trainID={fixedPosition.value} />
<FixedTrain
trainID={fixedPosition.value}
displaySize={displaySize}
setDisplaySize={setDisplaySize}
/>
)}
</View>
);
};

View File

@@ -1,23 +1,41 @@
import lineColorList from "@/assets/originData/lineColorList";
import { customTrainDataDetector } from "@/components/custom-train-data";
import { StationNumberMaker } from "@/components/駅名表/StationNumberMaker";
import { checkDuplicateTrainData } from "@/lib/checkDuplicateTrainData";
import { typeID } from "@/lib/getStringConfig";
import {
CustomTrainData,
eachTrainDiagramType,
StationProps,
} from "@/lib/CommonTypes";
import { getCurrentTrainData } from "@/lib/getCurrentTrainData";
import { getTrainDelayStatus } from "@/lib/getTrainDelayStatus";
import { getTrainType } from "@/lib/getTrainType";
import { objectIsEmpty } from "@/lib/objectIsEmpty";
import { trainPosition } from "@/lib/trainPositionTextArray";
import { getTime, trainTimeFiltering } from "@/lib/trainTimeFiltering";
import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
import { useAreaInfo } from "@/stateBox/useAreaInfo";
import { useCurrentTrain } from "@/stateBox/useCurrentTrain";
import { useStationList, StationProps } from "@/stateBox/useStationList";
import dayjs from "dayjs";
import { useEffect, useState } from "react";
import { Text, TouchableOpacity, View } from "react-native";
import { useStationList } from "@/stateBox/useStationList";
import { Ionicons } from "@expo/vector-icons";
import { useNavigation } from "@react-navigation/native";
export const FixedStation = ({ stationID }) => {
const { fixedPosition, setFixedPosition } = useCurrentTrain();
import { FC, useEffect, useState } from "react";
import { LayoutAnimation, Text, TouchableOpacity, View } from "react-native";
import { SheetManager } from "react-native-actions-sheet";
type props = {
stationID: string;
displaySize: number;
setDisplaySize: (size: number) => void;
};
export const FixedStation: FC<props> = ({
stationID,
displaySize,
setDisplaySize,
}) => {
const { currentTrain, setFixedPosition } = useCurrentTrain();
const { getStationDataFromId } = useStationList();
const { navigate } = useNavigation();
const [station, setStation] = useState<StationProps[]>([]);
useEffect(() => {
const data = getStationDataFromId(stationID);
@@ -29,117 +47,10 @@ export const FixedStation = ({ stationID }) => {
: "white";
////
const timeFiltering = (d) => {
const baseTime = 2;
if (currentTrain.filter((t) => t.num == d.train).length == 0) {
const date = dayjs();
const trainTime = date
.hour(parseInt(d.time.split(":")[0]))
.minute(parseInt(d.time.split(":")[1]));
if (date.isAfter(trainTime)) {
return false;
} else if (trainTime.diff(date) < baseTime * 60 * 60 * 1000) {
return true;
}
return false;
} else {
const Pos = trainPosition(
currentTrain.filter((t) => t.num == d.train)[0]
);
const nextPos = Pos.isBetween ? Pos.Pos.to : Pos.Pos.Pos;
const PrePos = Pos.isBetween ? Pos.Pos.from : "";
if (station[0].Station_JP == nextPos) {
if (d.lastStation != station[0].Station_JP) return true;
} else if (station[0].Station_JP == PrePos) {
return false;
}
let [h, m] = d.time.split(":");
let delay = isNaN(currentTrain.filter((t) => t.num == d.train)[0].delay)
? 0
: currentTrain.filter((t) => t.num == d.train)[0].delay;
const date = dayjs();
let targetHour = parseInt(h);
// 4時を日付変更線として処理
if (targetHour < 4) {
targetHour += 24;
}
let currentHour = date.hour();
if (currentHour < 4) {
currentHour += 24;
}
const db = dayjs()
.hour(targetHour)
.minute(parseInt(m) + parseInt(delay));
const currentTime = dayjs().hour(currentHour);
return !currentTime.isAfter(db);
}
};
type trainDataProps = {
train?: string;
lastStation?: string;
time?: string;
isThrough?: boolean;
};
const getTime = (stationDiagram, station) => {
const returnData = Object.keys(stationDiagram)
.map((trainNum) => {
let trainData: trainDataProps = {};
stationDiagram[trainNum].split("#").forEach((data) => {
if (data.match("着")) {
trainData.lastStation = data.split(",着,")[0];
}
if (data.match("着編")) {
trainData.lastStation = data.split(",着編,")[0];
}
if (data.split(",")[0] === station.Station_JP) {
if (data.match(",発,")) {
trainData.time = data.split(",発,")[1];
} else if (data.match(",発編,")) {
trainData.time = data.split(",発編,")[1];
} else if (data.match(",通編,")) {
trainData.time = data.split(",通編,")[1];
trainData.isThrough = true;
} else if (data.match(",着,")) {
trainData.time = data.split(",着,")[1];
} else if (data.match(",着編,")) {
trainData.time = data.split(",着編,")[1];
}
}
});
return {
train: trainNum,
time: trainData.time,
lastStation: trainData.lastStation,
isThrough: trainData.isThrough,
};
})
.filter((d) => d.time);
return returnData.sort((a, b) => {
switch (true) {
case parseInt(a.time.split(":")[0]) < parseInt(b.time.split(":")[0]):
return -1;
case parseInt(a.time.split(":")[0]) > parseInt(b.time.split(":")[0]):
return 1;
case parseInt(a.time.split(":")[1]) < parseInt(b.time.split(":")[1]):
return -1;
case parseInt(a.time.split(":")[1]) > parseInt(b.time.split(":")[1]):
return 1;
default:
return 0;
}
});
};
const { allTrainDiagram } = useAllTrainDiagram();
const { areaInfo, areaStationID } = useAreaInfo();
const [stationDiagram, setStationDiagram] = useState({}); //当該駅の全時刻表
const [isInfoArea, setIsInfoArea] = useState(false);
const { currentTrain } = useCurrentTrain();
useEffect(() => {
// 現在の駅に停車するダイヤを作成する副作用[列車ダイヤと現在駅情報]
@@ -161,7 +72,9 @@ export const FixedStation = ({ stationID }) => {
setIsInfoArea(station.some((s) => areaStationID.includes(s.StationNumber)));
}, [allTrainDiagram, station]);
const [trainTimeAndNumber, setTrainTimeAndNumber] = useState([]);
const [trainTimeAndNumber, setTrainTimeAndNumber] = useState<
eachTrainDiagramType[]
>([]);
useEffect(() => {
//現在の駅に停車する列車から時刻を切り出してLEDベースにフォーマット
@@ -169,29 +82,39 @@ export const FixedStation = ({ stationID }) => {
const getTimeData = getTime(stationDiagram, station[0]);
setTrainTimeAndNumber(getTimeData);
}, [stationDiagram]);
const [selectedTrain, setSelectedTrain] = useState<
{
isThrough?: boolean;
train?: string;
lastStation?: string;
time?: string;
}[]
>([]);
const [selectedTrain, setSelectedTrain] = useState<eachTrainDiagramType[]>(
[]
);
useEffect(() => {
if (!trainTimeAndNumber) return () => {};
if (!currentTrain) return () => {};
const data = trainTimeAndNumber
.filter((d) => currentTrain.map((m) => m.num).includes(d.train)) //現在の列車に絞る[ToDo]
.filter(timeFiltering).filter(d=>!d.isThrough)
.filter((d) => d.lastStation != station[0].Station_JP) //最終列車表示設定
.filter((d) => trainTimeFiltering({ d, currentTrain, station })) //時間フィルター
.filter((d) => !d.isThrough)
.filter((d) => d.lastStation != station[0].Station_JP); //最終列車表示設定
setSelectedTrain(data);
}, [trainTimeAndNumber, currentTrain /*finalSwitch*/]);
return (
<TouchableOpacity
style={{ flex: 1, flexDirection: "row" }}
style={{
flex: 1,
flexDirection: "row",
borderBottomColor: lineColor,
borderBottomWidth: 2,
position: "relative",
}}
activeOpacity={1}
onPress={() => {
setFixedPosition({ type: null, value: null });
const payload = {
currentStation: station,
navigate,
goTo: "menu",
onExit: () => SheetManager.hide("StationDetailView"),
};
//@ts-ignore
SheetManager.show("StationDetailView", { payload });
}}
>
<View
@@ -212,6 +135,9 @@ export const FixedStation = ({ stationID }) => {
width: "100%",
alignContent: "center",
alignItems: "center",
height: 22,
overflow: "hidden",
paddingLeft: 5,
}}
>
<StationNumberMaker
@@ -221,12 +147,13 @@ export const FixedStation = ({ stationID }) => {
/>
<Text
style={{
fontSize: 18,
fontSize: 14,
textAlignVertical: "center",
margin: 0,
padding: 0,
paddingLeft: 5,
flex: 1,
color:"white"
color: "white",
}}
>
{station[0]?.Station_JP}
@@ -234,15 +161,16 @@ export const FixedStation = ({ stationID }) => {
<View
style={{
backgroundColor: "white",
width: 10,
width: 6,
borderLeftColor: lineColor,
borderTopColor: lineColor,
borderBottomColor: "white",
borderBottomWidth: 16,
borderLeftWidth: 8,
borderRightColor: "white",
borderBottomWidth: 18,
borderLeftWidth: 10,
borderRightWidth: 0,
borderTopWidth: 5,
height: "100%",
height: 20,
}}
/>
</View>
@@ -253,7 +181,7 @@ export const FixedStation = ({ stationID }) => {
flex: 1,
}}
>
<Text style={{ fontSize: 20 }}></Text>
<Text style={{ fontSize: 18 }}></Text>
</View>
</View>
@@ -272,22 +200,135 @@ export const FixedStation = ({ stationID }) => {
<FixedStationBoxEachTrain
d={d}
station={station[0]}
displaySize={displaySize}
key={d.train + "-fixedStationBox"}
/>
))
) : (
<View style={{ backgroundColor: "white", flex: 1 }}>
<Text style={{ fontSize: 20 }}>
<Text style={{ fontSize: parseInt("11%") }}>
</Text>
</View>
)}
</View>
<TouchableOpacity
style={{
position: "absolute",
top: "100%",
left: 0,
flexDirection: "row",
alignItems: "center",
}}
onPress={() => {
setFixedPosition({ type: null, value: null });
}}
>
<View
style={{
flexDirection: "row",
alignItems: "center",
backgroundColor: lineColor,
paddingHorizontal: 5,
height: 26,
}}
>
<Ionicons name="lock-closed" size={15} color="white" />
<Text
style={{
color: "white",
fontSize: 15,
paddingRight: 5,
}}
>
</Text>
<Ionicons name="close" size={15} color="white" />
</View>
<View
style={{
backgroundColor: "#0000",
width: 6,
borderLeftColor: lineColor,
borderTopColor: lineColor,
borderBottomColor: "#0000",
borderRightColor: "#0000",
borderBottomWidth: 26,
borderLeftWidth: 10,
borderRightWidth: 0,
borderTopWidth: 0,
height: 26,
}}
/>
</TouchableOpacity>
<TouchableOpacity
style={{
position: "absolute",
top: "100%",
right: 0,
flexDirection: "row",
alignItems: "center",
}}
onPress={() => {
LayoutAnimation.configureNext({
duration: 500,
update: { type: "spring", springDamping: 0.7 },
});
if (displaySize === 50) {
setDisplaySize(200);
} else {
setDisplaySize(50);
}
}}
>
<View
style={{
backgroundColor: "#0000",
width: 6,
borderLeftColor: "#0000",
borderTopColor: lineColor,
borderBottomColor: "#0000",
borderRightColor: lineColor,
borderBottomWidth: 26,
borderLeftWidth: 0,
borderRightWidth: 10,
borderTopWidth: 0,
height: 26,
}}
/>
<View
style={{
flexDirection: "row",
alignItems: "center",
backgroundColor: lineColor,
paddingHorizontal: 5,
height: 26,
}}
pointerEvents="none"
>
<Ionicons
name={displaySize == 50 ? "chevron-down" : "chevron-up"}
size={15}
color="white"
/>
<Text
style={{
color: "white",
paddingRight: 5,
backgroundColor: lineColor,
fontSize: 15,
}}
>
{displaySize == 50 ? "時刻表を展開する" : "時刻表を縮小する"}
</Text>
</View>
</TouchableOpacity>
</TouchableOpacity>
);
};
const FixedStationBoxEachTrain = ({ d, station }) => {
const FixedStationBoxEachTrain = ({ d, station, displaySize }) => {
const { currentTrain } = useCurrentTrain();
const { stationList } = useStationList();
const { allCustomTrainData } = useAllTrainDiagram();
@@ -300,55 +341,30 @@ const FixedStationBoxEachTrain = ({ d, station }) => {
currentTrainData,
station.Station_JP
)}`;
const getTrainDataFromCurrentTrain = (trainNum: string) => {
const customTrainData = customTrainDataDetector(
d.train,
allCustomTrainData
);
switch (customTrainData.type) {
case "Normal":
case "OneMan":
const currentTrainData = currentTrain.filter((a) => a.num == trainNum);
if (currentTrainData.length == 0) return customTrainData;
else if (currentTrainData[0].Type.includes("rapid:")) {
const typeText = currentTrainData[0].Type.split(":");
const returnData = {
type: "Rapid",
trainName: typeText[1].replace("\r", ""),
trainIcon: null,
trainNumDistance: null,
info: "",
};
return returnData;
}
return customTrainData;
default:
return customTrainData;
}
};
const [train, setTrain] = useState<{
ToData: string;
TrainNumber: string;
id: string;
img: string;
isWanman: boolean;
trainName: string;
trainNumDistance: number;
type: typeID;
viaData: string;
info?: string;
uwasa?: string;
}>(getTrainDataFromCurrentTrain(d.train));
const [train, setTrain] = useState<CustomTrainData>(
getCurrentTrainData(d.train, currentTrain, allCustomTrainData)
);
useEffect(() => {
setTrain(getTrainDataFromCurrentTrain(d.train));
setTrain(getCurrentTrainData(d.train, currentTrain, allCustomTrainData));
}, [currentTrain, d.train]);
const { name, color } = getTrainType(train.type, true);
const { name, color } = getTrainType({ type: train.type, whiteMode: true });
return (
<View style={{ backgroundColor: "white", flexDirection: "row",height:"33%",overflow:"visible" }}>
<Text style={{ fontSize: 14, flex: 3 }}>{d.time}</Text>
<Text style={{ fontSize: 14, flex: 4, color }}>{name}</Text>
<Text style={{ fontSize: 14, flex: 4 }}>{d.lastStation}</Text>
<Text style={{ fontSize: 14, flex: 3 }}>{trainDelayStatus}</Text>
<View
style={{
backgroundColor: "white",
flexDirection: "row",
height: displaySize == 50 ? "33%" : "7.5%",
overflow: "visible",
}}
>
<Text style={{ fontSize: parseInt("11%"), flex: 3 }}>{d.time}</Text>
<Text style={{ fontSize: parseInt("11%"), flex: 4, color }}>{name}</Text>
<Text style={{ fontSize: parseInt("11%"), flex: 4 }}>
{d.lastStation}
</Text>
<Text style={{ fontSize: parseInt("11%"), flex: 3 }}>
{trainDelayStatus}
</Text>
</View>
);
};

View File

@@ -1,22 +1,38 @@
import lineColorList from "@/assets/originData/lineColorList";
import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
import { useCurrentTrain } from "@/stateBox/useCurrentTrain";
import { useStationList, StationProps } from "@/stateBox/useStationList";
import { useStationList } from "@/stateBox/useStationList";
import { StationProps } from "@/lib/CommonTypes";
import { FC, useEffect, useState } from "react";
import { Text, TouchableOpacity, View, Image } from "react-native";
import { customTrainDataDetector } from "../../custom-train-data";
import { getStringConfig, typeID } from "@/lib/getStringConfig";
import {
Text,
TouchableOpacity,
View,
Image,
LayoutAnimation,
ScrollView,
} from "react-native";
import { getTrainType } from "@/lib/getTrainType";
import { trainPosition } from "@/lib/trainPositionTextArray";
import { StationNumberMaker } from "../../駅名表/StationNumberMaker";
import { StationNumberMaker } from "@/components/駅名表/StationNumberMaker";
import { lineListPair, stationIDPair } from "@/lib/getStationList";
import { findReversalPoints } from "@/lib/eachTrainInfoCoreLib/findReversalPoints";
import { CustomTrainData, trainTypeID } from "@/lib/CommonTypes";
import { getCurrentTrainData } from "@/lib/getCurrentTrainData";
import { Ionicons } from "@expo/vector-icons";
import dayjs from "dayjs";
type props = {
trainID: string;
displaySize: number;
setDisplaySize: (e: number) => void;
};
export const FixedTrain: FC<props> = ({ trainID }) => {
export const FixedTrain: FC<props> = ({
trainID,
displaySize,
setDisplaySize,
}) => {
const {
fixedPosition,
setFixedPosition,
@@ -26,32 +42,6 @@ export const FixedTrain: FC<props> = ({ trainID }) => {
} = useCurrentTrain();
const { allCustomTrainData, allTrainDiagram } = useAllTrainDiagram();
const getTrainDataFromCurrentTrain = (trainNum: string) => {
const customTrainData = customTrainDataDetector(
trainNum,
allCustomTrainData
);
switch (customTrainData.type) {
case "Normal":
case "OneMan":
const currentTrainData = currentTrain.filter((a) => a.num == trainNum);
if (currentTrainData.length == 0) return customTrainData;
else if (currentTrainData[0].Type.includes("rapid:")) {
const typeText = currentTrainData[0].Type.split(":");
const returnData = {
type: "Rapid",
trainName: typeText[1].replace("\r", ""),
trainIcon: null,
trainNumDistance: null,
info: "",
};
return returnData;
}
return customTrainData;
default:
return customTrainData;
}
};
const [train, setTrain] = useState<{
Pos?: string;
Direction?: number;
@@ -62,21 +52,13 @@ export const FixedTrain: FC<props> = ({ trainID }) => {
delay?: string | number;
num?: string;
}>(null);
const [customData, setCustomData] = useState<{
ToData: string;
TrainNumber: string;
id: string;
img: string;
isWanman: boolean;
trainName: string;
trainNumDistance: number;
type: typeID;
viaData: string;
info?: string;
uwasa?: string;
}>(getTrainDataFromCurrentTrain(trainID));
const [customData, setCustomData] = useState<CustomTrainData>(
getCurrentTrainData(trainID, currentTrain, allCustomTrainData)
);
useEffect(() => {
setCustomData(getTrainDataFromCurrentTrain(trainID));
setCustomData(
getCurrentTrainData(trainID, currentTrain, allCustomTrainData)
);
}, [currentTrain, trainID]);
useEffect(() => {
const stationData = getCurrentStationData(trainID);
@@ -170,7 +152,7 @@ export const FixedTrain: FC<props> = ({ trainID }) => {
}, []).map((d) => d.StationNumber);
return StationNumbers;
});
const [currentPosition, setCurrentPosition] = useState([]);
const [currentPosition, setCurrentPosition] = useState<string[]>([]);
useEffect(() => {
const position = getPosition(train);
@@ -189,7 +171,6 @@ export const FixedTrain: FC<props> = ({ trainID }) => {
searchCount < points.length;
searchCount++
) {
console.log(trainDataWidhThrough[searchCount]);
const nextPos = trainDataWidhThrough[searchCount];
if (nextPos) {
const [station, se, time] = nextPos.split(",");
@@ -221,11 +202,6 @@ export const FixedTrain: FC<props> = ({ trainID }) => {
);
}
}, [customData, trainDataWidhThrough]);
const [stringConfig, setStringConfig] = useState([, ,]);
useEffect(() => {
const x = getStringConfig(customData.type, customData.TrainNumber);
setStringConfig(x);
}, [customData]);
const [station, setStation] = useState<StationProps[]>([]);
useEffect(() => {
@@ -236,76 +212,107 @@ export const FixedTrain: FC<props> = ({ trainID }) => {
station.length > 0
? lineColorList[station[0]?.StationNumber.slice(0, 1)]
: "black";
//const lineColor = "red";
const customTrainType = getTrainType({
type: customData.type,
whiteMode: true,
});
const trainNameText = `${customData.trainName}${
customData.trainNumDistance !== null
? ` ${parseInt(customData.TrainNumber) - customData.trainNumDistance}`
: ""
}`;
return (
<TouchableOpacity
style={{ flex: 1, flexDirection: "row", backgroundColor: "black" }}
onPress={() => {
setFixedPosition({ type: null, value: null });
<View
style={{
flex: 1,
flexDirection: displaySize === 50 ? "row" : "column",
backgroundColor: "black",
borderBottomColor: "black",
borderBottomWidth: 2,
position: "relative",
}}
>
<View
style={{ flexDirection: "column", flex: 1, backgroundColor: "white" }}
style={{
flexDirection: displaySize === 50 ? "column" : "row",
flex: 1,
backgroundColor: "white",
height: displaySize === 50 ? 50 : 200,
overflow: "hidden",
}}
>
<View style={{ flex: 1, flexDirection: "row" }}>
<View
style={{ flex: displaySize === 50 ? 1 : 5, flexDirection: "row" }}
>
<View
style={{
backgroundColor: getTrainType(customData.type, true).color,
backgroundColor: customTrainType.color,
flexDirection: "row",
alignContent: "center",
alignSelf: "center",
alignItems: "center",
height: "100%",
}}
>
<Image
source={{ uri: customData.img }}
width={14}
height={17}
width={displaySize === 50 ? 14 : 23}
height={displaySize === 50 ? 17 : 26}
style={{ margin: 5 }}
/>
<View
style={{
flexDirection: "row",
flexDirection: displaySize === 50 ? "row" : "column",
alignContent: "center",
alignSelf: "center",
alignItems: "center",
maxWidth: displaySize === 50 ? 100 : 60,
}}
>
<Text
style={{
fontSize: 14,
fontFamily: stringConfig[1] ? "JR-Nishi" : undefined,
fontWeight: !stringConfig[1] ? "bold" : undefined,
marginTop: stringConfig[1] ? 3 : 0,
fontFamily: customTrainType.fontAvailable
? "JR-Nishi"
: undefined,
fontWeight: !customTrainType.fontAvailable
? "bold"
: undefined,
marginTop: customTrainType.fontAvailable ? 3 : 0,
color: "white",
textAlignVertical: "center",
textAlign: "center",
textAlign: "left",
}}
>
{stringConfig[0]}
{customTrainType.shortName}
</Text>
{customData.trainName && (
<Text
style={{
fontSize: customData?.trainName?.length > 6 ? 9 : 14,
fontSize: trainNameText.length > 6 ? 8 : 14,
color: "white",
maxWidth: 65,
maxWidth: displaySize === 50 ? 60 : 200,
textAlignVertical: "center",
}}
>
{customData.trainName}
{trainNameText}
</Text>
)}
</View>
<View
style={{
backgroundColor: getTrainType(customData.type, true).color,
backgroundColor: customTrainType.color,
width: 10,
borderLeftColor: getTrainType(customData.type, true).color,
borderLeftColor: customTrainType.color,
borderTopColor: lineColor,
borderBottomColor: lineColor,
borderTopWidth: 14,
borderBottomWidth: 14,
borderLeftWidth: 10,
borderTopWidth: displaySize === 50 ? 14 : 50,
borderBottomWidth: displaySize === 50 ? 14 : 50,
borderLeftWidth: displaySize === 50 ? 10 : 30,
borderRightWidth: 0,
//height: displaySize === 50 ? 20 : 100,
height: "100%",
}}
></View>
</View>
@@ -329,12 +336,12 @@ export const FixedTrain: FC<props> = ({ trainID }) => {
>
<StationNumberMaker
currentStation={station}
singleSize={20}
singleSize={18}
useEach={true}
/>
<Text
style={{
fontSize: 14,
fontSize: customData?.ToData?.length > 4 ? 9 : 12,
color: "white",
fontWeight: "bold",
textAlignVertical: "center",
@@ -348,11 +355,26 @@ export const FixedTrain: FC<props> = ({ trainID }) => {
</View>
</View>
</View>
{displaySize === 200 && (
<View
style={{
backgroundColor: "white",
width: 10,
borderLeftColor: "black",
borderTopColor: lineColor,
borderBottomColor: "white",
borderRightColor: "black",
borderTopWidth: 50,
borderBottomWidth: 0,
borderLeftWidth: 0,
borderRightWidth: 20,
}}
></View>
)}
<View
style={{
backgroundColor: "black",
flex: 1,
flex: displaySize === 50 ? 1 : 4,
flexDirection: "row",
alignItems: "center",
}}
@@ -382,32 +404,152 @@ export const FixedTrain: FC<props> = ({ trainID }) => {
>
{nextStationData[0]?.Station_JP || "不明"}
</Text>
<View
style={{
backgroundColor: "white",
width: 10,
borderLeftColor: "black",
borderTopColor: "black",
borderBottomColor: "white",
borderRightColor: "white",
borderTopWidth: 25,
borderBottomWidth: 0,
borderLeftWidth: 0,
borderRightWidth: 10,
}}
></View>
{displaySize === 50 && (
<View
style={{
backgroundColor: "white",
width: 10,
borderLeftColor: "black",
borderTopColor: "black",
borderBottomColor: "white",
borderRightColor: "white",
borderTopWidth: 21,
borderBottomWidth: 0,
borderLeftWidth: 0,
borderRightWidth: 7,
}}
></View>
)}
</View>
</View>
<CurrentPositionBox
train={train}
lineColor={lineColor}
trainDataWithThrough={untilStationData}
isSmall={displaySize === 50}
/>
</TouchableOpacity>
<TouchableOpacity
style={{
position: "absolute",
top: "100%",
left: 0,
flexDirection: "row",
alignItems: "center",
}}
onPress={() => {
setFixedPosition({ type: null, value: null });
}}
>
<View
style={{
flexDirection: "row",
alignItems: "center",
backgroundColor: "black",
paddingHorizontal: 5,
height: 26,
}}
>
<Ionicons name="lock-closed" size={15} color="white" />
<Text
style={{
color: "white",
fontSize: 15,
paddingRight: 5,
}}
>
</Text>
<Ionicons name="close" size={15} color="white" />
</View>
<View
style={{
backgroundColor: "#0000",
width: 6,
borderLeftColor: "black",
borderTopColor: "black",
borderBottomColor: "#0000",
borderRightColor: "#0000",
borderBottomWidth: 26,
borderLeftWidth: 10,
borderRightWidth: 0,
borderTopWidth: 0,
height: 26,
}}
/>
</TouchableOpacity>
<TouchableOpacity
style={{
position: "absolute",
top: "100%",
right: 0,
flexDirection: "row",
alignItems: "center",
}}
onPress={() => {
LayoutAnimation.configureNext({
duration: 500,
update: { type: "spring", springDamping: 0.7 },
});
if (displaySize === 50) {
setDisplaySize(200);
} else {
setDisplaySize(50);
}
}}
>
<View
style={{
backgroundColor: "#0000",
width: 6,
borderLeftColor: "#0000",
borderTopColor: "black",
borderBottomColor: "#0000",
borderRightColor: "black",
borderBottomWidth: 26,
borderLeftWidth: 0,
borderRightWidth: 10,
borderTopWidth: 0,
height: 26,
}}
/>
<View
style={{
flexDirection: "row",
alignItems: "center",
backgroundColor: "black",
paddingHorizontal: 5,
height: 26,
}}
pointerEvents="none"
>
<Ionicons
name={displaySize == 50 ? "chevron-down" : "chevron-up"}
size={15}
color="white"
/>
<Text
style={{
color: "white",
paddingRight: 5,
backgroundColor: "black",
fontSize: 15,
}}
>
{displaySize == 50 ? "列車情報展開" : "列車情報縮小"}
</Text>
</View>
</TouchableOpacity>
</View>
);
};
const CurrentPositionBox = ({ train, lineColor, trainDataWithThrough }) => {
const CurrentPositionBox = ({
train,
lineColor,
trainDataWithThrough,
isSmall,
}) => {
let firstText = "";
let secondText = "";
let marginText = "";
@@ -424,66 +566,93 @@ const CurrentPositionBox = ({ train, lineColor, trainDataWithThrough }) => {
firstText = Pos;
}
}
const delayTime = train?.delay == "入線" ? 0 : parseInt(train?.delay);
return (
<View style={{ flex: 1, backgroundColor: "white", flexDirection: "row" }}>
<View style={{ flexDirection: "column", height: "100%" }}>
<View
style={{
backgroundColor: "white",
width: 10,
borderLeftColor: lineColor,
borderTopColor: lineColor,
borderBottomColor: "white",
borderRightColor: "white",
borderTopWidth: 25,
borderBottomWidth: 0,
borderLeftWidth: 0,
borderRightWidth: 10,
flex: 1,
}}
></View>
<View
style={{
backgroundColor: "white",
width: 10,
borderLeftColor: "white",
borderTopColor: "white",
borderBottomColor: "white",
borderRightColor: "white",
borderTopWidth: 25,
borderBottomWidth: 0,
borderLeftWidth: 0,
borderRightWidth: 10,
flex: 1,
}}
></View>
</View>
<View style={{ flex: 1, flexDirection: "row", overflow: "hidden" }}>
<View
style={{
flex: isSmall ? 1 : 3,
backgroundColor: "white",
flexDirection: "row",
}}
>
{isSmall && (
<View style={{ flexDirection: "column" }}>
<View
style={{
backgroundColor: "white",
width: 10,
borderLeftColor: lineColor,
borderTopColor: lineColor,
borderBottomColor: "white",
borderRightColor: "white",
borderTopWidth: 28,
borderBottomWidth: 0,
borderLeftWidth: 0,
borderRightWidth: 10,
}}
></View>
<View
style={{
backgroundColor: "white",
width: 10,
borderLeftColor: "white",
borderTopColor: "white",
borderBottomColor: "white",
borderRightColor: "white",
borderTopWidth: 18,
borderBottomWidth: 0,
borderLeftWidth: 0,
borderRightWidth: 10,
}}
></View>
</View>
)}
<ScrollView
style={{ flex: 1, flexDirection: "row" }}
horizontal
overScrollMode="always"
>
{trainDataWithThrough.length > 0 &&
trainDataWithThrough.map((d, index, array) => {
if (!d) return null;
if (d == "") return null;
const [station, se, time] = d.split(",");
let distanceMinute = 0;
if (time != "") {
const now = dayjs();
const hour = parseInt(time.split(":")[0]);
const distanceTime = now
.hour(hour < 4 ? hour + 24 : hour)
.minute(time.split(":")[1]);
distanceMinute = distanceTime.diff(now, "minute") + delayTime;
if (now.hour() < 4) {
if (hour < 4) {
distanceMinute = distanceMinute - 1440;
}
}
}
return (
<>
{(index == 0 && secondText == "") || <View
<View
style={{
flexDirection: "column",
backgroundColor: "#6e6e6eff",
borderRadius: 10,
marginHorizontal: 2,
padding: 2,
borderRadius: 30,
marginHorizontal: isSmall ? 2 : 4,
marginVertical: isSmall ? 0 : 2,
padding: isSmall ? 2 : 4,
justifyContent: "center",
alignItems: "center",
overflow: "hidden",
}}
key={d + "CurrentPositionBox"}
>
{station.split("").map((i, index) => {
return (
<Text
key={index}
key={i + index}
style={{
fontSize: 6,
fontSize: isSmall ? 5 : 12,
color: "white",
margin: 0,
padding: 0,
@@ -495,31 +664,65 @@ const CurrentPositionBox = ({ train, lineColor, trainDataWithThrough }) => {
);
})}
<View style={{ flex: 1 }} />
<Text style={{ fontSize: 8, color: "white" }}>
{se.includes("通") ? "" : "●"}
{isSmall ||
(time != "" && (
<Text
style={{
fontSize: isSmall ? 8 : 12,
color: "black",
backgroundColor: "white",
fontWeight: "bold",
}}
>
{distanceMinute}
</Text>
))}
<Text
style={{
fontSize: isSmall ? 8 : 14,
color: se.includes("通")
? "#020202ff"
: index == 1 && secondText == ""
? "#ffe852ff"
: "white",
marginTop: isSmall ? 0 : 3,
height: isSmall ? "auto" : 17,
fontWeight: "bold",
}}
>
{se.includes("通")
? null
: index == 1 && secondText == ""
? "→"
: "●"}
</Text>
</View>}
{(index == 0 && secondText != "") && (
</View>
{index == 0 && secondText != "" && (
<View
style={{
flexDirection: "column",
backgroundColor: "#6e6e6e0e",
borderRadius: 10,
marginHorizontal: 2,
padding: 2,
marginHorizontal: isSmall ? 2 : 4,
padding: isSmall ? 2 : 4,
justifyContent: "center",
alignItems: "center",
overflow: "hidden",
}}
>
<View style={{ flex: 1 }} />
<Text style={{ fontSize: 8, color: "black" }}></Text>
<Ionicons
name="arrow-forward"
size={isSmall ? 8 : 14}
color="black"
style={{ marginTop: isSmall ? 0 : 3 }}
/>
</View>
)}
</>
);
})}
</View>
</ScrollView>
</View>
);
};

View File

@@ -53,6 +53,7 @@ export const FavoriteList: FC = () => {
goBack();
if (canGoBack()) goBack();
}}
key={currentStation[0].StationNumber + "FavoriteList"}
>
<View
style={{

View File

@@ -1,9 +1,9 @@
import React, { FC, useState } from "react";
import { View, Text, TouchableOpacity } from "react-native";
import { useInterval } from "../../lib/useInterval";
import { useInterval } from "@/lib/useInterval";
import lineColorList from "../../assets/originData/lineColorList";
import { StationProps } from "@/stateBox/useStationList";
import lineColorList from "@/assets/originData/lineColorList";
import { StationProps } from "@/lib/CommonTypes";
type StationNumberProps = {
currentStation: StationProps[];
active: boolean;

View File

@@ -265,7 +265,7 @@ export const ExGridView: FC<{
if (num % 5 === 0) {
return (
<Text
key={num}
key={num + "ExGridViewTimeLabel"}
style={{
flex: 1,
textAlign: "left",

View File

@@ -1,5 +1,5 @@
import { migrateTrainName } from "@/lib/eachTrainInfoCoreLib/migrateTrainName";
import { getStringConfig, typeID } from "@/lib/getStringConfig";
import { getStringConfig } from "@/lib/getStringConfig";
import { getTrainType } from "@/lib/getTrainType";
import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
import { FC, useEffect, useLayoutEffect, useMemo, useState } from "react";
@@ -18,6 +18,7 @@ import { useStationList } from "@/stateBox/useStationList";
import { SharedValue, useAnimatedStyle } from "react-native-reanimated";
import Animated from "react-native-reanimated";
import lineColorList from "@/assets/originData/lineColorList";
import { CustomTrainData, trainTypeID } from "@/lib/CommonTypes";
export const ExGridViewItem: FC<{
d: {
@@ -40,22 +41,7 @@ export const ExGridViewItem: FC<{
const { allCustomTrainData } = useAllTrainDiagram();
const { originalStationList, stationList } = useStationList();
const { navigate, goBack } = useNavigation();
const [trainData, setTrainData] = useState<{
ToData: string;
TrainNumber: string;
id: string;
img: string;
info?: string;
infoUrl: string;
infogram: string;
isEdit: boolean;
isSeason: boolean;
trainName: string;
trainNumDistance?: number;
type: typeID;
viaData?: string;
uwasa?: string;
}>();
const [trainData, setTrainData] = useState<CustomTrainData>();
useEffect(() => {
if (allCustomTrainData) {
allCustomTrainData.forEach((x) => {
@@ -65,7 +51,7 @@ export const ExGridViewItem: FC<{
});
}
}, []);
const { color, name, data } = getTrainType(trainData?.type, true);
const { color, name, data } = getTrainType({ type: trainData?.type, whiteMode: true });
// 列車名、種別、フォントの取得
const [
typeString,

View File

@@ -1,5 +1,5 @@
import { migrateTrainName } from "@/lib/eachTrainInfoCoreLib/migrateTrainName";
import { getStringConfig, typeID } from "@/lib/getStringConfig";
import { getStringConfig } from "@/lib/getStringConfig";
import { getTrainType } from "@/lib/getTrainType";
import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
import { FC, useEffect, useMemo, useState } from "react";
@@ -10,6 +10,7 @@ import { SheetManager } from "react-native-actions-sheet";
import { useNavigation } from "@react-navigation/native";
import { lineList } from "@/lib/getStationList";
import { useStationList } from "@/stateBox/useStationList";
import { CustomTrainData, trainTypeID } from "@/lib/CommonTypes";
export const ListViewItem: FC<{
d: {
@@ -22,22 +23,7 @@ export const ListViewItem: FC<{
}> = ({ d }) => {
const { allCustomTrainData } = useAllTrainDiagram();
const { navigate, goBack } = useNavigation();
const [trainData, setTrainData] = useState<{
ToData: string;
TrainNumber: string;
id: string;
img: string;
info?: string;
infoUrl: string;
infogram: string;
isEdit: boolean;
isSeason: boolean;
trainName: string;
trainNumDistance?: number;
type: typeID;
viaData?: string;
uwasa?: string;
}>();
const [trainData, setTrainData] = useState<CustomTrainData>();
useEffect(() => {
if (allCustomTrainData) {
allCustomTrainData.forEach((x) => {
@@ -47,8 +33,8 @@ export const ListViewItem: FC<{
});
}
}, []);
const { color, name, data } = getTrainType(trainData?.type, true);
const { originalStationList } = useStationList();
const { color, name, data } = getTrainType({ type: trainData?.type, whiteMode: true });
const { originalStationList } = useStationList();
// 列車名、種別、フォントの取得
const [
typeString,

View File

@@ -18,8 +18,8 @@ import dayjs from "dayjs";
import { ExGridView } from "./ExGridView";
import { Switch } from "react-native-elements";
import { customTrainDataDetector } from "../custom-train-data";
import { typeID } from "@/lib/getStringConfig";
import { colorString } from "@/lib/getTrainType";
import { getTrainType } from "@/lib/getTrainType";
import { trainTypeID } from "@/lib/CommonTypes";
type props = {
route: {
@@ -55,7 +55,7 @@ export const StationDiagramView: FC<props> = ({ route }) => {
const { navigate, addListener, goBack, canGoBack } = useNavigation();
const [keyBoardVisible, setKeyBoardVisible] = useState(false);
const [input, setInput] = useState("");
const [selectedTypeList, setSelectedTypeList] = useState<typeID[]>([
const [selectedTypeList, setSelectedTypeList] = useState<trainTypeID[]>([
"Normal",
"OneMan",
"Rapid",
@@ -262,48 +262,36 @@ export const StationDiagramView: FC<props> = ({ route }) => {
<TypeSelectorBox
selectedTypeList={selectedTypeList}
setSelectedTypeList={setSelectedTypeList}
typeName="普通"
typeID="Normal"
color="black"
relativeID={["OneMan"]}
/>
<TypeSelectorBox
selectedTypeList={selectedTypeList}
setSelectedTypeList={setSelectedTypeList}
typeName="快速"
typeID="Rapid"
color="#00b8d8cc"
relativeID={["OneManRapid"]}
/>
<TypeSelectorBox
selectedTypeList={selectedTypeList}
setSelectedTypeList={setSelectedTypeList}
typeName="特急"
typeID="LTDEXP"
color="red"
relativeID={["NightLTDEXP"]}
/>
<TypeSelectorBox
selectedTypeList={selectedTypeList}
setSelectedTypeList={setSelectedTypeList}
typeName="臨時"
typeID="SPCL"
color="#297bff"
relativeID={["SPCL_Normal", "SPCL_Rapid", "SPCL_EXP", "Party"]}
/>
<TypeSelectorBox
selectedTypeList={selectedTypeList}
setSelectedTypeList={setSelectedTypeList}
typeName="貨物"
typeID="Freight"
color="#00869ecc"
/>
<TypeSelectorBox
selectedTypeList={selectedTypeList}
setSelectedTypeList={setSelectedTypeList}
typeName="回送"
typeID="Forwarding"
color="#727272cc"
relativeID={["FreightForwarding"]}
/>
<TouchableOpacity
@@ -395,23 +383,15 @@ export const StationDiagramView: FC<props> = ({ route }) => {
};
export const TypeSelectorBox: FC<{
selectedTypeList: typeID[];
setSelectedTypeList: (list: typeID[]) => void;
typeName: string;
typeID: typeID;
color: colorString;
relativeID?: typeID[];
selectedTypeList: trainTypeID[];
setSelectedTypeList: (list: trainTypeID[]) => void;
typeID: trainTypeID;
relativeID?: trainTypeID[];
}> = (props) => {
const {
selectedTypeList,
setSelectedTypeList,
typeName,
typeID,
relativeID,
color,
} = props;
const { selectedTypeList, setSelectedTypeList, typeID, relativeID } = props;
const isSelected =
selectedTypeList.findIndex((item) => item === typeID) !== -1;
const { color, shortName } = getTrainType({ type: typeID, whiteMode: true });
return (
<TouchableOpacity
style={{
@@ -447,7 +427,7 @@ export const TypeSelectorBox: FC<{
margin: 5,
}}
>
{typeName}
{shortName}
</Text>
</TouchableOpacity>
);

View File

@@ -1,7 +1,12 @@
import { CustomTrainData } from "@/lib/CommonTypes";
import dayjs from "dayjs";
export const customTrainDataDetector = (
type CustomTrainDataDetector = (
TrainNumber: string,
allCustomTrainData?: any[]
) => CustomTrainData;
export const customTrainDataDetector: CustomTrainDataDetector = (
TrainNumber,
allCustomTrainData
) => {
if (allCustomTrainData && allCustomTrainData.length > 0) {
const customTrain = allCustomTrainData.find(

View File

@@ -1,23 +1,24 @@
import React, { FC, useEffect, useState } from "react";
import { TouchableOpacity } from "react-native";
import { checkDuplicateTrainData } from "../../lib/checkDuplicateTrainData";
import { getTrainDelayStatus } from "../../lib/getTrainDelayStatus";
import { getTrainType } from "../../lib/getTrainType";
import { useCurrentTrain } from "../../stateBox/useCurrentTrain";
import { checkDuplicateTrainData } from "@/lib/checkDuplicateTrainData";
import { getTrainDelayStatus } from "@/lib/getTrainDelayStatus";
import { getTrainType } from "@/lib/getTrainType";
import { useCurrentTrain } from "@/stateBox/useCurrentTrain";
import { SheetManager } from "react-native-actions-sheet";
import { Description } from "./LED_inside_Component/Description";
import { DependTime } from "./LED_inside_Component/DependTime";
import { LastStation } from "./LED_inside_Component/LastStation";
import { StatusAndDelay } from "./LED_inside_Component/StatusAndDelay";
import { TrainName } from "./LED_inside_Component/TrainName";
import { customTrainDataDetector } from "../custom-train-data";
import { TrainPosition } from "./LED_inside_Component/TrainPosition";
import { StationPosPushDialog } from "./LED_inside_Component/TrainPositionDataPush";
import { StationPosDeleteDialog } from "./LED_inside_Component/TrainPositionDataDelete";
import { useStationList } from "../../stateBox/useStationList";
import { Description } from "@/components/発車時刻表/LED_inside_Component/Description";
import { DependTime } from "@/components/発車時刻表/LED_inside_Component/DependTime";
import { LastStation } from "@/components/発車時刻表/LED_inside_Component/LastStation";
import { StatusAndDelay } from "@/components/発車時刻表/LED_inside_Component/StatusAndDelay";
import { TrainName } from "@/components/発車時刻表/LED_inside_Component/TrainName";
import { TrainPosition } from "@/components/発車時刻表/LED_inside_Component/TrainPosition";
import { StationPosPushDialog } from "@/components/発車時刻表/LED_inside_Component/TrainPositionDataPush";
import { StationPosDeleteDialog } from "@/components/発車時刻表/LED_inside_Component/TrainPositionDataDelete";
import { useStationList } from "@/stateBox/useStationList";
import useInterval from "@/lib/useInterval";
import dayjs from "dayjs";
import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
import { CustomTrainData, StationProps, trainTypeID } from "@/lib/CommonTypes";
import { getCurrentTrainData } from "@/lib/getCurrentTrainData";
type Props = {
d: {
@@ -28,10 +29,7 @@ type Props = {
};
trainIDSwitch: boolean;
trainDescriptionSwitch: boolean;
station: {
Station_JP: string;
StationNumber: string;
};
station: StationProps;
navigate: (screen: string, data?: any) => void;
openStationACFromEachTrainInfo: (station: string) => void;
};
@@ -62,7 +60,7 @@ export const EachData: FC<Props> = (props) => {
const payload = {
data: {
trainNum: d.train,
limited: `${getTrainType(train.type).data}:${
limited: `${getTrainType({type:train.type}).data}:${
train.trainName
}${TrainNumber}`,
},
@@ -75,47 +73,9 @@ export const EachData: FC<Props> = (props) => {
});
};
const getTrainDataFromCurrentTrain = (trainNum: string) => {
const customTrainData = customTrainDataDetector(
d.train,
allCustomTrainData
);
switch (customTrainData.type) {
case "Normal":
case "OneMan":
const currentTrainData = currentTrain.filter((a) => a.num == trainNum);
if (currentTrainData.length == 0) return customTrainData;
else if (currentTrainData[0].Type.includes("rapid:")) {
const typeText = currentTrainData[0].Type.split(":");
const returnData = {
type: "Rapid",
trainName: typeText[1].replace("\r", ""),
trainIcon: null,
trainNumDistance: null,
info: "",
};
return returnData;
}
return customTrainData;
default:
return customTrainData;
}
};
const [train, setTrain] = useState<{
ToData: string;
TrainNumber: string;
id: string;
img: string;
isWanman: boolean;
trainName: string;
trainNumDistance: number;
type:string;
viaData:string;
info?:string;
uwasa?:string;
}>(getTrainDataFromCurrentTrain(d.train));
const [train, setTrain] = useState<CustomTrainData>(getCurrentTrainData(d.train,currentTrain,allCustomTrainData));
useEffect(() => {
setTrain(getTrainDataFromCurrentTrain(d.train));
setTrain(getCurrentTrainData(d.train,currentTrain,allCustomTrainData));
}, [currentTrain, d.train, trainDescriptionSwitch]);
// 土讃線複数存在対策
const currentTrainData = checkDuplicateTrainData(
@@ -145,10 +105,13 @@ export const EachData: FC<Props> = (props) => {
const [isShow, setIsShow] = useState(true);
const [isDepartureNow, setIsDepartureNow] = useState(false);
useEffect(() => {
const [h, m] = d.time.split(":");
const IntH = parseInt(h);
const IntM = parseInt(m);
const currentTime = dayjs();
const trainTime = currentTime
.set("hour", parseInt(d.time.split(":")[0]))
.set("minute", parseInt(d.time.split(":")[1]));
.set("hour", IntH < 4 ? IntH + 24 : IntH)
.set("minute", IntM);
const diff = trainTime.diff(currentTime, "minute");
if (diff < 2) setIsDepartureNow(true);
else setIsDepartureNow(false);

View File

@@ -1,17 +1,18 @@
import React, { FC } from "react";
import { Text, View } from "react-native";
import { getTrainType } from "../../../lib/getTrainType";
import { trainTypeID } from "@/lib/CommonTypes";
type Props = {
trainName: string;
trainNumDistance?: number;
trainIDSwitch: boolean;
trainID: string;
type: string;
type: trainTypeID;
isThrew: boolean;
};
export const TrainName: FC<Props> = (props) => {
const { trainName, trainNumDistance, trainIDSwitch, trainID, type, isThrew } = props;
const { name, color } = getTrainType(type);
const { name, color } = getTrainType({ type });
const TrainNumber =
trainNumDistance != undefined
? `${

View File

@@ -1,18 +1,17 @@
import React, { useState, useEffect } from "react";
import React, { useState, useEffect, FC } from "react";
import { View, useWindowDimensions } from "react-native";
import dayjs from "dayjs";
import { useInterval } from "../../lib/useInterval";
import { objectIsEmpty } from "../../lib/objectIsEmpty";
import { useCurrentTrain } from "../../stateBox/useCurrentTrain";
import { useAreaInfo } from "../../stateBox/useAreaInfo";
import { AS } from "../../storageControl";
import { Footer } from "./LED_Vision_Component/Footer";
import { Header } from "./LED_Vision_Component/Header";
import { Description } from "./LED_inside_Component/Description";
import { EachData } from "./EachData";
import { objectIsEmpty } from "@/lib/objectIsEmpty";
import { useCurrentTrain } from "@/stateBox/useCurrentTrain";
import { useAreaInfo } from "@/stateBox/useAreaInfo";
import { AS } from "@/storageControl";
import { Footer } from "@/components/発車時刻表/LED_Vision_Component/Footer";
import { Header } from "@/components/発車時刻表/LED_Vision_Component/Header";
import { EachData } from "@/components/発車時刻表/EachData";
import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
import { trainPosition } from "@/lib/trainPositionTextArray";
import { AreaDescription } from "./LED_inside_Component/AreaDescription";
import { AreaDescription } from "@/components/発車時刻表/LED_inside_Component/AreaDescription";
import { getTime, trainTimeFiltering } from "@/lib/trainTimeFiltering";
import { eachTrainDiagramType, StationProps } from "@/lib/CommonTypes";
import { useNavigation } from "@react-navigation/native";
/**
*
@@ -43,10 +42,17 @@ import { AreaDescription } from "./LED_inside_Component/AreaDescription";
* 9031M ()()
* 9062D ()
*/
export default function LED_vision(props) {
const { station, navigate, openStationACFromEachTrainInfo } = props;
type props = {
station: StationProps[];
};
export const LED_vision: FC<props> = (props) => {
const { station } = props;
const { navigate, addListener, isFocused } = useNavigation();
const { currentTrain } = useCurrentTrain();
const [stationDiagram, setStationDiagram] = useState({}); //当該駅の全時刻表
const [stationDiagram, setStationDiagram] = useState<{
[key: string]: string;
}>({}); //当該駅の全時刻表
const [finalSwitch, setFinalSwitch] = useState(false);
const [trainIDSwitch, setTrainIDSwitch] = useState(false);
const [trainDescriptionSwitch, setTrainDescriptionSwitch] = useState(false);
@@ -85,7 +91,9 @@ export default function LED_vision(props) {
/*
{lastStation: "当駅止", time: "12:34", train: "1234M"}
*/
const [trainTimeAndNumber, setTrainTimeAndNumber] = useState([]);
const [trainTimeAndNumber, setTrainTimeAndNumber] = useState<
eachTrainDiagramType[]
>([]);
useEffect(() => {
//現在の駅に停車する列車から時刻を切り出してLEDベースにフォーマット
@@ -94,102 +102,19 @@ export default function LED_vision(props) {
setTrainTimeAndNumber(getTimeData);
}, [stationDiagram]);
const [selectedTrain, setSelectedTrain] = useState([]);
const [selectedTrain, setSelectedTrain] = useState<eachTrainDiagramType[]>(
[]
);
useEffect(() => {
if (!trainTimeAndNumber) return () => {};
if (!currentTrain) return () => {};
const data = trainTimeAndNumber
.filter((d) => currentTrain.map((m) => m.num).includes(d.train)) //現在の列車に絞る[ToDo]
.filter(timeFiltering)
.filter((d) => !!finalSwitch || d.lastStation != station[0].Station_JP) //最終列車表示設定
.filter((d) => trainTimeFiltering({ d, currentTrain, station })) //時間フィルター
.filter((d) => !!finalSwitch || d.lastStation != station[0].Station_JP); //最終列車表示設定
setSelectedTrain(data);
}, [trainTimeAndNumber, currentTrain, finalSwitch]);
const getTime = (stationDiagram, station) => {
const returnData = Object.keys(stationDiagram)
.map((trainNum) => {
let trainData = {};
stationDiagram[trainNum].split("#").forEach((data) => {
if (data.match("着")) {
trainData.lastStation = data.split(",着,")[0];
}
if (data.match("着編")) {
trainData.lastStation = data.split(",着編,")[0];
}
if (data.split(",")[0] === station.Station_JP) {
if (data.match(",発,")) {
trainData.time = data.split(",発,")[1];
}else if (data.match(",発編,")) {
trainData.time = data.split(",発編,")[1];
} else if (data.match(",通編,")) {
trainData.time = data.split(",通編,")[1];
trainData.isThrough = true;
} else if (data.match(",着,")) {
trainData.time = data.split(",着,")[1];
}else if (data.match(",着編,")) {
trainData.time = data.split(",着編,")[1];
}
}
});
return {
train: trainNum,
time: trainData.time,
lastStation: trainData.lastStation,
isThrough: trainData.isThrough,
};
})
.filter((d) => d.time);
return returnData.sort((a, b) => {
switch (true) {
case parseInt(a.time.split(":")[0]) < parseInt(b.time.split(":")[0]):
return -1;
case parseInt(a.time.split(":")[0]) > parseInt(b.time.split(":")[0]):
return 1;
case parseInt(a.time.split(":")[1]) < parseInt(b.time.split(":")[1]):
return -1;
case parseInt(a.time.split(":")[1]) > parseInt(b.time.split(":")[1]):
return 1;
default:
return 0;
}
});
};
const timeFiltering = (d) => {
const baseTime = 2;
if (currentTrain.filter((t) => t.num == d.train).length == 0) {
const date = dayjs();
const trainTime = date
.hour(parseInt(d.time.split(":")[0]))
.minute(parseInt(d.time.split(":")[1]));
if (date.isAfter(trainTime)) {
return false;
} else if (trainTime.diff(date) < baseTime * 60 * 60 * 1000) {
return true;
}
return false;
} else {
const Pos = trainPosition(
currentTrain.filter((t) => t.num == d.train)[0]
);
const nextPos = Pos.isBetween ? Pos.Pos.to : Pos.Pos.Pos;
const PrePos = Pos.isBetween ? Pos.Pos.from : "";
if (station[0].Station_JP == nextPos) {
if(d.lastStation != station[0].Station_JP) return true;
} else if (station[0].Station_JP == PrePos) {
return false;
}
const date = dayjs();
let [h, m] = d.time.split(":");
let delay = isNaN(currentTrain.filter((t) => t.num == d.train)[0].delay)
? 0
: currentTrain.filter((t) => t.num == d.train)[0].delay;
const db = date.hour(parseInt(h)).minute(parseInt(m) + parseInt(delay));
return !date.isAfter(db);
}
};
const { width } = useWindowDimensions();
const adjustedWidth = width * 0.98;
return (
@@ -210,7 +135,7 @@ export default function LED_vision(props) {
trainIDSwitch,
trainDescriptionSwitch,
navigate,
openStationACFromEachTrainInfo,
openStationACFromEachTrainInfo: () => {},
}}
station={station[0]}
key={d.train}
@@ -236,4 +161,4 @@ export default function LED_vision(props) {
/>
</View>
);
}
};

View File

@@ -1,8 +1,8 @@
import React, { FC } from "react";
import { Text, View } from "react-native";
import { useWindowDimensions } from "react-native";
import lineColorList from "../../assets/originData/lineColorList";
import { StationProps } from "@/stateBox/useStationList";
import lineColorList from "@/assets/originData/lineColorList";
import { StationProps } from "@/lib/CommonTypes";
type props = {
currentStation: StationProps[];

58
lib/CommonTypes.ts Normal file
View File

@@ -0,0 +1,58 @@
export type trainTypeID =
| "Normal"
| "OneMan"
| "Rapid"
| "OneManRapid"
| "LTDEXP"
| "NightLTDEXP"
| "SPCL"
| "SPCL_Normal"
| "SPCL_Rapid"
| "SPCL_EXP"
| "Party"
| "Freight"
| "Forwarding"
| "FreightForwarding"
| "Other";
export type CustomTrainData = {
ToData?: string;
TrainNumber?: string;
TrainNumberOverride?: string;
id?: string;
img?: string;
isWanman?: boolean;
trainName?: string;
trainNumDistance?: number;
type?: trainTypeID;
viaData?: string;
info?: string;
infoUrl?: string;
infogram?: string;
uwasa?: string;
isEdit?: boolean;
isSeason?: boolean;
vehicleFormation?: string;
trainInfoUrl?: string;
};
export type eachTrainDiagramType = {
train: string;
time: string;
lastStation: string;
isThrough: boolean;
};
export type StationProps = {
DispNum: string;
JrHpUrl?: string;
MyStation: string;
StationMap: string;
StationNumber: string | null;
StationTimeTable: string;
Station_EN: string;
Station_JP: string;
jslodApi: string;
lat: number;
lng: number;
};

View File

@@ -0,0 +1,31 @@
import { customTrainDataDetector } from "@/components/custom-train-data";
import { CustomTrainData, trainTypeID } from "./CommonTypes";
import { trainDataType } from "./trainPositionTextArray";
export const getCurrentTrainData = (
trainNum: string,
currentTrain: trainDataType[],
allCustomTrainData: CustomTrainData[] | undefined
) => {
const customTrainData = customTrainDataDetector(trainNum, allCustomTrainData);
switch (customTrainData.type) {
case "Normal":
case "OneMan":
const currentTrainData = currentTrain.filter((a) => a.num == trainNum);
if (currentTrainData.length == 0) return customTrainData;
else if (currentTrainData[0].Type?.includes("rapid:")) {
const typeText = currentTrainData[0].Type?.split(":");
const returnData = {
type: "Rapid" as trainTypeID,
trainName: typeText[1].replace("\r", ""),
trainIcon: null,
trainNumDistance: null,
info: "",
};
return returnData;
}
return customTrainData;
default:
return customTrainData;
}
};

View File

@@ -1,20 +1,6 @@
export type typeID =
| "Normal"
| "OneMan"
| "Rapid"
| "OneManRapid"
| "LTDEXP"
| "NightLTDEXP"
| "SPCL"
| "SPCL_Normal"
| "SPCL_Rapid"
| "SPCL_EXP"
| "Party"
| "Freight"
| "Forwarding"
| "FreightForwarding"
| "Other";
type types = (types: typeID, id: string) => [string, boolean, boolean];
import { trainTypeID } from "@/lib/CommonTypes";
type types = (types: trainTypeID, id: string) => [string, boolean, boolean];
export const getStringConfig: types = (type, id) => {
switch (type) {
case "Normal":

View File

@@ -1,17 +1,18 @@
import { typeID } from "./getStringConfig";
import { trainTypeID } from "./CommonTypes";
export type colorString =
| "aqua"
| "#00a0bdff"
| "#007488ff"
| "red"
| "#297bff"
| "#ff7300ff"
| "#00869ecc"
| "#727272cc"
| "#00b8d8cc"
| "#5f5f5fff"
| "#e000b0ff"
| "white"
| "black"
| "pink";
type trainTypeString =
| "快速"
| "特急"
@@ -25,56 +26,184 @@ type trainTypeString =
| "貨物"
| "回送"
| "単機回送"
| "試運転"
| "その他";
type trainTypeDataString = "rapid" | "express" | "normal" | "notService";
type getTrainType = (
d: typeID,
isWhiteMode?: boolean
) => {
type getTrainType = (e: {
type: trainTypeID;
id?: string;
whiteMode?: boolean;
}) => {
color: colorString;
name: trainTypeString;
shortName: string;
fontAvailable: boolean;
isOneMan: boolean;
data: trainTypeDataString;
};
export const getTrainType: getTrainType = (nameString, whiteMode) => {
switch (nameString) {
export const getTrainType: getTrainType = ({ type, id, whiteMode }) => {
switch (type) {
case "Normal":
return {
color: whiteMode ? "black" : "white",
name: "普通列車",
shortName: "普通",
fontAvailable: true,
isOneMan: false,
data: "normal",
};
case "OneMan":
return {
color: whiteMode ? "black" : "white",
name: "普通列車(ワンマン)",
shortName: "普通",
fontAvailable: true,
isOneMan: true,
data: "normal",
};
case "Rapid":
return {
color: whiteMode ? "#00a0bdff" : "aqua",
name: "快速",
shortName: "快速",
fontAvailable: true,
isOneMan: false,
data: "rapid",
};
case "OneManRapid":
return { color: whiteMode ? "#00a0bdff" : "aqua", name: "快速", data: "rapid" };
return {
color: whiteMode ? "#00a0bdff" : "aqua",
name: "快速",
shortName: "快速",
fontAvailable: true,
isOneMan: true,
data: "rapid",
};
case "LTDEXP":
return { color: "red", name: "特急", data: "express" };
return {
color: "red",
name: "特急",
shortName: "特急",
fontAvailable: true,
isOneMan: false,
data: "express",
};
case "NightLTDEXP":
return { color: whiteMode ? "#e000b0ff":"pink", name: "寝台特急", data: "express" };
return {
color: whiteMode ? "#e000b0ff" : "pink",
name: "寝台特急",
shortName: "特急",
fontAvailable: true,
isOneMan: false,
data: "express",
};
case "SPCL":
case "SPCL_Normal":
return { color: "#297bff", name: "臨時", data: "normal" };
return {
color: "#297bff",
name: "臨時",
shortName: "臨時",
fontAvailable: true,
isOneMan: false,
data: "normal",
};
case "SPCL_Rapid":
return { color: "#297bff", name: "臨時快速", data: "normal" };
return {
color: "#297bff",
name: "臨時快速",
shortName: "臨時快速",
fontAvailable: true,
isOneMan: false,
data: "normal",
};
case "SPCL_EXP":
return { color: "#297bff", name: "臨時特急", data: "normal" };
return {
color: "#297bff",
name: "臨時特急",
shortName: "臨時特急",
fontAvailable: true,
isOneMan: false,
data: "normal",
};
case "Party":
return { color: "#ff7300ff", name: "団体臨時", data: "normal" };
return {
color: "#ff7300ff",
name: "団体臨時",
shortName: "団体臨時",
fontAvailable: true,
isOneMan: false,
data: "normal",
};
case "Freight":
return { color: "#007488ff", name: "貨物", data: "notService" };
return {
color: "#007488ff",
name: "貨物",
shortName: "貨物",
fontAvailable: false,
isOneMan: false,
data: "notService",
};
case "Forwarding":
return { color: "#727272cc", name: "回送", data: "notService" };
return {
color: "#5f5f5fff",
name: "回送",
shortName: "回送",
fontAvailable: false,
isOneMan: false,
data: "notService",
};
case "FreightForwarding":
return { color: "#727272cc", name: "単機回送", data: "notService" };
return {
color: "#5f5f5fff",
name: "単機回送",
shortName: "単機回送",
fontAvailable: false,
isOneMan: false,
data: "notService",
};
case "Other":
default:
if (id) {
switch (true) {
case !!id.includes("T"):
return {
color: "#5f5f5fff",
name: "単機回送",
shortName: "単機回送",
fontAvailable: false,
isOneMan: false,
data: "notService",
};
case !!id.includes("R"):
case !!id.includes("E"):
case !!id.includes("L"):
case !!id.includes("A"):
case !!id.includes("B"):
return {
color: "#5f5f5fff",
name: "回送",
shortName: "回送",
fontAvailable: false,
isOneMan: false,
data: "notService",
};
case !!id.includes("H"):
return {
color: "#5f5f5fff",
name: "試運転",
shortName: "試運転",
fontAvailable: false,
isOneMan: false,
data: "notService",
};
}
}
return {
color: whiteMode ? "black" : "white",
name: "その他",
shortName: "その他",
fontAvailable: false,
isOneMan: false,
data: "normal",
};
}

View File

@@ -9,30 +9,13 @@ export const initIcon = (
tabBarBadge: string,
isInfo: boolean
) => {
switch (type) {
case "Ionicons":
return ({ focused, color, size }) => (
<>
{!!tabBarBadge && <Badge tabBarBadge={tabBarBadge} isInfo={isInfo} />}
<Ionicons
name={name}
size={30}
color={focused ? "#0099CC" : "black"}
/>
</>
);
case "AntDesign":
return ({ focused, color, size }) => (
<>
{!!tabBarBadge && <Badge tabBarBadge={tabBarBadge} isInfo={isInfo} />}
<AntDesign
name={name}
size={30}
color={focused ? "#0099CC" : "black"}
/>
</>
);
}
const IconComponent = type == "Ionicons" ? Ionicons : AntDesign;
return ({ focused, color, size }) => (
<>
{!!tabBarBadge && <Badge tabBarBadge={tabBarBadge} isInfo={isInfo} />}
<IconComponent name={name} size={30} color={focused ? "#0099CC" : "black"} />
</>
);
};
type BadgeProps = { tabBarBadge: string; isInfo: boolean };
@@ -60,7 +43,7 @@ export const Badge: FC<BadgeProps> = ({ tabBarBadge, isInfo }) => {
shadowOffset: { width: 0, height: 0 },
shadowOpacity: 0.5,
shadowRadius: 4,
elevation: 2
elevation: 2,
}}
>
<Text style={{ color: "white", paddingHorizontal: 4 }}>

View File

@@ -18,7 +18,7 @@ export type trainDataType = {
Line?: string;
PosNum?: number;
Type?: string;
delay?: string | number;
delay?: "入線" | number;
num?: string;
};
type trainData = (

107
lib/trainTimeFiltering.ts Normal file
View File

@@ -0,0 +1,107 @@
import dayjs from "dayjs";
import { trainDataType, trainPosition } from "@/lib/trainPositionTextArray";
import { eachTrainDiagramType, StationProps } from "@/lib/CommonTypes";
type trainDataProps = {
d: eachTrainDiagramType;
currentTrain: trainDataType[];
station: StationProps[];
};
export const trainTimeFiltering: (x: trainDataProps) => boolean = (props) => {
const { d, currentTrain, station } = props;
const baseTime = 2; // 何時間以内の列車を表示するか
if (currentTrain.filter((t) => t.num == d.train).length == 0) {
const date = dayjs();
const trainTime = date
.hour(parseInt(d.time.split(":")[0]))
.minute(parseInt(d.time.split(":")[1]));
if (date.isAfter(trainTime)) {
return false;
} else if (trainTime.diff(date) < baseTime * 60 * 60 * 1000) {
return true;
}
return false;
} else {
const Pos = trainPosition(currentTrain.filter((t) => t.num == d.train)[0]);
let nextPos = "";
let PrePos = "";
//
if (Pos.isBetween == true) {
nextPos = Pos.Pos.to;
PrePos = Pos.Pos.from;
} else {
nextPos = Pos.Pos.Pos;
}
const stationData = station[0].Station_JP;
switch (stationData) {
case nextPos:
if (d.lastStation != stationData) return true;
break;
case PrePos:
return false;
default:
break;
}
const [h, m] = d.time.split(":");
const delayData = currentTrain.filter((t) => t.num == d.train)[0].delay;
let delay = delayData === "入線" ? 0 : delayData;
const date = dayjs();
const IntH = parseInt(h) < 4 ? parseInt(h) + 24 : parseInt(h);
const IntM = parseInt(m);
const targetDate = date.hour(IntH).minute(IntM + delay);
if (date.isAfter(targetDate)) return false;
if (targetDate.diff(date) < baseTime * 60 * 60 * 1000) return true;
return false;
}
};
type getTimeProps = (
stationDiagram: { [key: string]: string },
station: StationProps
) => eachTrainDiagramType[];
export const getTime: getTimeProps = (stationDiagram, station) => {
const returnData = Object.keys(stationDiagram)
.map((trainNum) => {
let trainData: eachTrainDiagramType = {
time: "",
lastStation: "",
isThrough: false,
train: trainNum,
};
stationDiagram[trainNum].split("#").forEach((data) => {
const [stationName, type, time] = data.split(",");
if (!type) return;
if (type.match("着")) {
trainData.lastStation = stationName;
}
if (stationName === station.Station_JP) {
if (type.match("発")) {
trainData.time = time;
} else if (type.match("通")) {
trainData.time = time;
trainData.isThrough = true;
} else if (type.match("着")) {
trainData.time = time;
}
}
});
return {
train: trainNum,
time: trainData.time,
lastStation: trainData.lastStation,
isThrough: trainData.isThrough,
};
})
.filter((d) => d.time);
return returnData.sort((a, b) => {
let [aH, aM] = a.time.split(":");
let [bH, bM] = b.time.split(":");
if (parseInt(aH) < 4) aH = (parseInt(aH) + 24).toString();
if (parseInt(bH) < 4) bH = (parseInt(bH) + 24).toString();
const baseTime = dayjs();
const aTime = baseTime.hour(parseInt(aH)).minute(parseInt(aM));
const bTime = baseTime.hour(parseInt(bH)).minute(parseInt(bM));
if (aTime.isBefore(bTime)) return -1;
if (aTime.isAfter(bTime)) return 1;
return 0;
});
};

View File

@@ -110,13 +110,6 @@ export const injectJavascriptData: InjectJavascriptData = (
setStrings();
}catch(error){}
};
const useAutoReload = () =>{
try{
setReload();
}catch(error){}
setTimeout(useAutoReload, 10000);
}
useAutoReload();
`;
// 左か右かを判定してアイコンを設置する
const trainIcon = `

View File

@@ -1,58 +1,54 @@
import React, { useRef, useState, useEffect, useLayoutEffect } from "react";
import {
Platform,
View,
ScrollView,
useWindowDimensions,
LayoutAnimation,
Text,
TouchableOpacity,
} from "react-native";
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 StatusbarDetect from "@/StatusbarDetect";
import LED_vision from "./components/発車時刻表/LED_vidion";
import { TitleBar } from "./components/Menu/TitleBar";
import { FixedContentBottom } from "./components/Menu/FixedContentBottom";
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 { lineList, stationIDPair } from "@/lib/getStationList";
import { useFavoriteStation } from "@/stateBox/useFavoriteStation";
import { useNavigation } from "@react-navigation/native";
import { useStationList } from "./stateBox/useStationList";
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 { 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";
import { AS } from "./storageControl";
import { lineList_LineWebID } from "./lib/getStationList";
import { Ionicons } from "@expo/vector-icons";
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
});
export default function Menu(props) {
type props = {
scrollRef: React.RefObject<ScrollView>;
mapHeight: number;
MapFullHeight: number;
mapMode: boolean;
setMapMode: React.Dispatch<React.SetStateAction<boolean>>;
};
export const Menu: FC<props> = (props) => {
const { scrollRef, mapHeight, MapFullHeight, mapMode, setMapMode } = props;
const { navigate, addListener, isFocused } = useNavigation();
const { navigate } = useNavigation();
const { favoriteStation } = useFavoriteStation();
const { originalStationList, getStationDataFromNameBase } = useStationList();
const { height, width } = useWindowDimensions();
const { bottom, left, right, top } = useSafeAreaInsets();
const tabBarHeight = useBottomTabBarHeight();
const [stationListMode, setStationListMode] = useState(
/*<"position"|"favorite">*/ "position"
);
const [stationListMode, setStationListMode] = useState<
"position" | "favorite"
>("position");
useEffect(() => {
AS.getItem("stationListMode")
.then((res) => setStationListMode(res))
.catch((e) => {
.catch(() => {
// AS.setItem("stationListMode", "position");
});
}, []);
@@ -92,11 +88,17 @@ export default function Menu(props) {
};
//現在地基準の駅名標リストアップ機能
const { position, locationStatus } = useUserPosition();
const [nearPositionStation, setNearPositionStation] = useState<
StationProps[][]
>([]); //第三要素
useEffect(() => {
if (!position) return () => {};
makeCurrentStation(position);
}, [position, stationListMode]);
const makeCurrentStation = (location) => {
const makeCurrentStation = (location: LocationObject) => {
if (!originalStationList) return () => {};
const findStationEachLine = (selectLine) => {
const searchArea = 0.055; //検索範囲
@@ -128,7 +130,7 @@ export default function Menu(props) {
return NearStation;
};
let _stList = lineList
let _stList: StationProps[] = lineList
.map((d) => findStationEachLine(originalStationList[d]))
.filter((d) => d.length > 0)
.reduce((pre, current) => {
@@ -137,7 +139,7 @@ export default function Menu(props) {
}, []);
if (_stList.length == 0) setNearPositionStation([]);
else {
let returnData = [];
let returnData: StationProps[][] = [];
_stList.forEach((d, index, array) => {
const stationName = d.Station_JP;
if (returnData.findIndex((d) => d[0].Station_JP == stationName) != -1)
@@ -166,19 +168,17 @@ export default function Menu(props) {
}
};
const [nearPositionStation, setNearPositionStation] = useState([]); //第三要素
const [listIndex, setListIndex] = useState(0);
const [listUpStation, setListUpStation] = useState([]);
const [listUpStation, setListUpStation] = useState<StationProps[][]>([]);
const [isSearchMode, setisSearchMode] = useState(false);
const [input, setInput] = React.useState("");
const [input, setInput] = useState("");
useLayoutEffect(() => {
if (!!isSearchMode) {
const returnData = [];
if (!input || input == "") {
Object.keys(lineList_LineWebID).forEach((d, indexBase) => {
originalStationList[d].forEach((D, index) => {
Object.keys(lineList_LineWebID).forEach((d) => {
originalStationList[d].forEach((D) => {
if (
isSearchMode &&
isSearchMode != stationIDPair[lineList_LineWebID[d]]
@@ -196,7 +196,9 @@ export default function Menu(props) {
const hoge = getStationDataFromNameBase(input);
hoge.forEach((d, index, array) => {
const stationName = d.Station_JP;
if (returnData.findIndex((d1) => d1[0].Station_JP == stationName) != -1)
if (
returnData.findIndex((d1) => d1[0].Station_JP == stationName) != -1
)
return;
returnData.push(array.filter((d2) => d2.Station_JP == stationName));
});
@@ -242,8 +244,8 @@ export default function Menu(props) {
if (mapMode) {
mapsRef?.current.fitToCoordinates(
listUpStation.map((d) => ({
latitude: parseFloat(d[0].lat),
longitude: parseFloat(d[0].lng),
latitude: d[0].lat,
longitude: d[0].lng,
})),
{ edgePadding: { top: 80, bottom: 120, left: 50, right: 50 } } // Add margin values here
);
@@ -261,24 +263,7 @@ export default function Menu(props) {
}}
>
<StatusbarDetect />
{!mapMode ? (
<TitleBar />
) : (
<></>
// <Text
// style={{
// fontSize: 30,
// color: "#0099CC",
// fontWeight: "bold",
// position: "absolute",
// top: 0,
// zIndex: 1000,
// fontStyle: "italic",
// }}
// >
// JRShikoku RailScope
// </Text>
)}
{!mapMode ? <TitleBar /> : <></>}
<ScrollView
ref={scrollRef}
snapToStart={false}
@@ -334,8 +319,8 @@ export default function Menu(props) {
<Marker
key={index + StationNumber}
coordinate={{
latitude: parseFloat(lat),
longitude: parseFloat(lng),
latitude: lat,
longitude: lng,
}}
image={require("@/assets/reccha-small.png")}
onPress={() => {
@@ -344,8 +329,8 @@ export default function Menu(props) {
if (mapsRef.current) {
mapsRef.current.animateToRegion(
{
latitude: parseFloat(lat),
longitude: parseFloat(lng),
latitude: lat,
longitude: lng,
latitudeDelta: 0.05,
longitudeDelta: 0.05,
},
@@ -401,11 +386,7 @@ export default function Menu(props) {
}}
/>
{listUpStation[listIndex] && (
<LED_vision
station={listUpStation[listIndex]}
navigate={navigate}
openStationACFromEachTrainInfo={() => {}}
/>
<LED_vision station={listUpStation[listIndex]} />
)}
</>
)}
@@ -433,4 +414,4 @@ export default function Menu(props) {
)}
</View>
);
}
};

View File

@@ -1,12 +1,19 @@
import React, { Ref, useRef, useState,useEffect } from "react";
import { View, Platform, TouchableOpacity, StyleProp, ViewStyle,Linking } from "react-native";
import React, { Ref, useRef, useState, useEffect } from "react";
import {
View,
Platform,
TouchableOpacity,
StyleProp,
ViewStyle,
Linking,
} from "react-native";
import { WebView } from "react-native-webview";
import Constants from "expo-constants";
import { Ionicons } from "@expo/vector-icons";
import { useNavigation } from "@react-navigation/native";
export default function tndView() {
const webview = useRef<WebView>(null);
const { navigate, addListener, isFocused } = useNavigation();
const { navigate, addListener, isFocused } = useNavigation();
const jsa = `
document.querySelector('.sitettl').style.display = 'none';
document.querySelector('.attention').style.display = 'none';
@@ -100,23 +107,23 @@ setInterval(() => {
});
}, 1000);
`;
const goToTrainMenu = () =>{
if (Platform.OS === "web") {
Linking.openURL("https://www.jr-shikoku.co.jp/info/");
setTimeout(() => {
// @ts-ignore
navigate("topMenu", { screen: "menu" });
}, 100);
return;
}
}
useEffect(() => {
// @ts-ignore
const unsubscribe = addListener("tabPress", goToTrainMenu);
return unsubscribe;
}, [addListener]);
const goToTrainMenu = () => {
if (Platform.OS === "web") {
Linking.openURL("https://www.jr-shikoku.co.jp/info/");
setTimeout(() => {
// @ts-ignore
navigate("topMenu", { screen: "menu" });
}, 100);
return;
}
};
useEffect(() => {
// @ts-ignore
const unsubscribe = addListener("tabPress", goToTrainMenu);
return unsubscribe;
}, [addListener]);
return (
<View
style={{
@@ -147,7 +154,7 @@ setInterval(() => {
}
const ReloadButton = ({ onPress, top, LoadError = false }) => {
const styles:StyleProp<ViewStyle> = {
const styles: StyleProp<ViewStyle> = {
position: "absolute",
top,
right: 10,

View File

@@ -1,22 +1,30 @@
import trainList from "@/assets/originData/trainList";
import useInterval from "@/lib/useInterval";
import { AS } from "@/storageControl";
import React, { createContext, useContext, useEffect, useState } from "react";
import React, { createContext, FC, useContext, useEffect, useState } from "react";
const initialState = {
allTrainDiagram: undefined,
setAllTrainDiagram: () => {},
allTrainDiagram: {},
setAllTrainDiagram: (e) => {},
allCustomTrainData: [],
keyList: [],
};
type initialStateType = {
allTrainDiagram: { [key: string]: string };
setAllTrainDiagram: (e) => void;
allCustomTrainData: any[];
keyList: string[];
};
const AllTrainDiagramContext = createContext(initialState);
const AllTrainDiagramContext = createContext<initialStateType>(initialState);
export const useAllTrainDiagram = () => useContext(AllTrainDiagramContext);
export const AllTrainDiagramProvider = ({ children }) => {
type Props = {
children: React.ReactNode;
};
export const AllTrainDiagramProvider:FC<Props> = ({ children }) => {
const [allTrainDiagram, setAllTrainDiagram] = useState(trainList);
const [allCustomTrainData, setAllCustomTrainData] = useState([]); // カスタム列車データ
const [keyList, setKeyList] = useState(); // 第二要素
const [keyList, setKeyList] = useState<string[]>([]); // 第二要素
useEffect(() => {
if (allTrainDiagram && Object.keys(allTrainDiagram).length > 0)
setKeyList(Object.keys(allTrainDiagram));
@@ -29,19 +37,19 @@ export const AllTrainDiagramProvider = ({ children }) => {
.then((res) => {
const data = {};
res.forEach((d) => {
const keys = Object.keys(d);
const keys = Object.keys(d)[0];
data[keys] = d[keys];
});
//dataのkeyで並び替え
const sortedData = Object.keys(data)
.sort((a, b) => a.replace(/[D,M]/, "") - b.replace(/[D,M]/, ""))
.sort((a, b) => parseInt(a.replace(/[D,M]/, "")) - parseInt(b.replace(/[D,M]/, "")))
.reduce((acc, key) => {
acc[key] = data[key];
return acc;
}, {});
return sortedData;
})
.then((res) => {
.then((res:any) => {
setAllTrainDiagram(res);
AS.setItem("allTrainDiagram", JSON.stringify(res));
})

View File

@@ -1,19 +1,12 @@
import React, { createContext, useContext, useState, useEffect } from "react";
import React, {
createContext,
useContext,
useState,
useEffect,
FC,
} from "react";
import useInterval from "../lib/useInterval";
const initialState = {
areaInfo: "",
setAreainfo: () => {},
areaIconBadgeText: "",
areaStationID: [],
};
const AreaInfoContext = createContext(initialState);
export const useAreaInfo = () => {
return useContext(AreaInfoContext);
};
const setoStationID = [
"Y00",
"Y01",
@@ -340,7 +333,30 @@ const areaStationPair = {
yodo: { id: "G", stationID: yodoStationID },
};
export const AreaInfoProvider = ({ children }) => {
const initialState = {
areaInfo: "",
setAreaInfo: () => {},
areaIconBadgeText: "",
areaStationID: [],
isInfo: false,
setIsInfo: () => {},
};
type initialStateType = {
areaInfo: string;
setAreaInfo: (e: string) => void;
areaIconBadgeText: string;
areaStationID: string[];
isInfo: boolean;
setIsInfo: (e: boolean) => void;
};
const AreaInfoContext = createContext<initialStateType>(initialState);
export const useAreaInfo = () => {
return useContext(AreaInfoContext);
};
type props = { children: React.ReactNode };
export const AreaInfoProvider: FC<props> = ({ children }) => {
const [areaInfo, setAreaInfo] = useState("");
const [areaIconBadgeText, setAreaIconBadgeText] = useState("");
const [areaStationID, setAreaStationID] = useState([]);

View File

@@ -1,13 +1,19 @@
import React, { createContext, useContext, useState, useEffect } from "react";
import React, {
createContext,
useContext,
useState,
useEffect,
FC,
} from "react";
import { AS } from "../storageControl";
import { useAllTrainDiagram } from "./useAllTrainDiagram";
const initialState = {
busAndTrainData: [],
setBusAndTrainData: () => {},
setBusAndTrainData: (e) => {},
trainPairData: [],
setTrainPairData: () => {},
initializeTrainPairList: () => {},
getInfluencedTrainData: () => {},
setTrainPairData: (e) => {},
initializeTrainPairList: (e) => {},
getInfluencedTrainData: (e) => {},
};
const BusAndTrainDataContext = createContext(initialState);
@@ -15,11 +21,17 @@ const BusAndTrainDataContext = createContext(initialState);
export const useBusAndTrainData = () => {
return useContext(BusAndTrainDataContext);
};
export const BusAndTrainDataProvider = ({ children }) => {
type props = { children: React.ReactNode };
export const BusAndTrainDataProvider: FC<props> = ({ children }) => {
const { allTrainDiagram } = useAllTrainDiagram();
const [busAndTrainData, setBusAndTrainData] = useState([]);
const [trainPairData, setTrainPairData] = useState([]);
const [busAndTrainData, setBusAndTrainData] = useState<
{
address: string;
name: string;
type: "station-data" | "bus-stop" | "train-info";
}[]
>([]);
const [trainPairData, setTrainPairData] = useState<any[]>([]);
useEffect(() => {
AS.getItem("busAndTrain202403")
.then((d) => {
@@ -53,7 +65,7 @@ export const BusAndTrainDataProvider = ({ children }) => {
});
return trainPairList;
};
const getInfluencedTrainData = (trainNum) => {
const getInfluencedTrainData = (trainNum: string) => {
const trainPairList = initializeTrainPairList();
// 9253M ラマル

View File

@@ -4,78 +4,114 @@ import React, {
useState,
useEffect,
useRef,
FC,
} from "react";
import { HeaderConfig } from "../lib/HeaderConfig";
import { HeaderConfig } from "@/lib/HeaderConfig";
import useInterval from "../lib/useInterval";
import { useStationList } from "./useStationList";
import useInterval from "@/lib/useInterval";
import { useStationList } from "@/stateBox/useStationList";
import { checkDuplicateTrainData } from "@/lib/checkDuplicateTrainData";
import { getStationID } from "@/lib/eachTrainInfoCoreLib/getStationData";
import { trainDataType } from "@/lib/trainPositionTextArray";
import WebView from "react-native-webview";
import { StationProps } from "@/lib/CommonTypes";
type loading = "loading" | "success" | "error";
const initialState = {
webview: {},
webview: undefined,
currentTrain: [],
setCurrentTrain: () => {},
currentTrainLoading: "loading",
setCurrentTrainLoading: () => {},
setCurrentTrain: (e) => {},
currentTrainLoading: "loading" as loading,
setCurrentTrainLoading: (e) => {},
getCurrentTrain: () => {},
inject: (i) => {},
fixedPosition: null,
setFixedPosition: (e) => {},
setInjectData: (e) => {},
getCurrentStationData: (e) => {},
getPosition: (e) => {},
getCurrentStationData: ((e) => {}) as (
e: string
) => trainDataType | undefined,
getPosition: ((e) => {}) as (e: trainDataType) => string[] | undefined,
};
const CurrentTrainContext = createContext(initialState);
type initialStateType = {
webview: React.MutableRefObject<WebView<{}>> | null;
currentTrain: trainDataType[];
setCurrentTrain: (e: trainDataType[]) => void;
currentTrainLoading: loading;
setCurrentTrainLoading: (e: loading) => void;
getCurrentTrain: () => void;
inject: (i: string) => void;
fixedPosition: { type: "station" | "train"; value: string } | null;
setFixedPosition: (
e: { type: "station" | "train"; value: string } | null
) => void;
setInjectData: (e: {
type: "station" | "train";
value: string;
fixed: boolean;
}) => void;
getCurrentStationData: (e: string) => trainDataType | undefined;
getPosition: (e: trainDataType) => string[] | undefined;
};
const CurrentTrainContext = createContext<initialStateType>(initialState);
export const useCurrentTrain = () => {
return useContext(CurrentTrainContext);
};
export const CurrentTrainProvider = ({ children }) => {
const [currentTrain, setCurrentTrain] = useState([]); //現在在線中の全列車 { num: 列車番号, delay: 遅延時分(状態), Pos: 位置情報 }
const [currentTrainLoading, setCurrentTrainLoading] = useState("loading"); // success, error, loading
type props = {
children: React.ReactNode;
};
export const CurrentTrainProvider: FC<props> = ({ children }) => {
const webview = useRef<WebView>(null);
const [currentTrain, setCurrentTrain] = useState<trainDataType[]>([]); //現在在線中の全列車 { num: 列車番号, delay: 遅延時分(状態), Pos: 位置情報 }
const [currentTrainLoading, setCurrentTrainLoading] =
useState<loading>("loading");
const { getInjectJavascriptAddress, stationList, originalStationList } =
useStationList();
const [fixedPosition, setFixedPosition] = useState({
const [fixedPosition, setFixedPosition] = useState<{
type: "station" | "train";
value: string;
}>({
type: null,
value: null,
});
const [_, setIntervalState] = useInterval(
() => {
if (!webview.current) return;
if (fixedPosition.type == "station") {
const script = getInjectJavascriptAddress(fixedPosition.value);
inject(script);
} else if (fixedPosition.type == "train") {
const currentTrain = getCurrentStationData(fixedPosition.value);
const values = getPosition(currentTrain);
if (!values) return;
if (values[0] == "M12" || values[1] == "M12") {
const script = getInjectJavascriptAddress("M12");
inject(script);
return;
}
const script = getInjectJavascriptAddress(
values[values.length == 2 ? currentTrain.Direction : 0]
);
const [_, setIntervalState] = useInterval(() => {
if (!webview.current) return;
if (fixedPosition.type == "station") {
const script = getInjectJavascriptAddress(fixedPosition.value);
inject(script);
} else if (fixedPosition.type == "train") {
const currentTrain = getCurrentStationData(fixedPosition.value);
const values = getPosition(currentTrain);
if (!values) return;
if (values[0] == "M12" || values[1] == "M12") {
const script = getInjectJavascriptAddress("M12");
inject(script);
return;
}
},
5000, //60000,
false
);
useEffect(() => {
if (fixedPosition) {
setIntervalState.start();
const script = getInjectJavascriptAddress(
values[values.length == 2 ? currentTrain.Direction : 0]
);
inject(script);
} else {
setIntervalState.stop();
inject(`setReload()`);
}
}, [fixedPosition]);
const getPosition = (currentTrainData) => {
}, 10000);
// useEffect(() => {
// if (fixedPosition) {
// setIntervalState.start();
// } else {
// setIntervalState.stop();
// }
// }, [fixedPosition]);
type getPositionFuncType = (
currentTrainData: trainDataType
) => string[] | undefined;
const getPosition: getPositionFuncType = (currentTrainData) => {
//currentTrainData.Pos = "鴨川~端岡"; //test
if (!currentTrainData) return;
if (!currentTrainData?.Pos) return;
@@ -85,7 +121,7 @@ export const CurrentTrainProvider = ({ children }) => {
.replace("(徳島線)", "")
.replace("(高徳線)", "")
.split("");
const direction = parseInt(currentTrainData?.Direction) || 0;
const direction = currentTrainData?.Direction || 0;
if (pos[0] == "児島" && pos[1] == "宇多津") {
return ["M12", "Y09"];
} else if (pos[1] == "児島" && pos[0] == "宇多津") {
@@ -104,7 +140,7 @@ export const CurrentTrainProvider = ({ children }) => {
let firstStationID = "";
let secondStation = false;
let secondStationID = "";
originalStationList[key].forEach((station) => {
originalStationList[key].forEach((station: StationProps) => {
if (station.Station_JP === pos[0]) {
firstStation = true;
firstStationID = station.StationNumber;
@@ -136,7 +172,8 @@ export const CurrentTrainProvider = ({ children }) => {
return [getStationID(currentTrainData?.Pos, stationList)];
}
};
const getCurrentStationData = (e) => {
type getCurrentStationDataFunc = (e: string) => trainDataType | undefined;
const getCurrentStationData: getCurrentStationDataFunc = (e) => {
//e:trainNumber
if (!currentTrain.length) return;
return checkDuplicateTrainData(
@@ -144,23 +181,32 @@ export const CurrentTrainProvider = ({ children }) => {
stationList
);
};
const setInjectData = ({ type, value, fixed }) => {
if (type === "station") {
const script = getInjectJavascriptAddress(value);
inject(script);
} else if (type === "train") {
const currentTrain = getCurrentStationData(value);
const values = getPosition(currentTrain);
if (!values) return;
let script;
if (values[0] == "M12" || values[1] == "M12") {
script = getInjectJavascriptAddress("M12");
} else {
const valuesIndex = values.length == 2 ? currentTrain.Direction : 0;
script = getInjectJavascriptAddress(values[valuesIndex]);
}
inject(script);
type injectDataType = {
type: "station" | "train";
value: string;
fixed: boolean;
};
type injectDataFuncType = (data: injectDataType) => void;
const setInjectData: injectDataFuncType = ({ type, value, fixed }) => {
let script;
switch (type) {
case "station":
script = getInjectJavascriptAddress(value);
break;
case "train":
const currentTrain = getCurrentStationData(value);
const values = getPosition(currentTrain);
if (!values) return;
if (values[0] == "M12" || values[1] == "M12") {
script = getInjectJavascriptAddress("M12");
} else {
const valuesIndex = values.length == 2 ? currentTrain.Direction : 0;
script = getInjectJavascriptAddress(values[valuesIndex]);
}
break;
}
inject(script);
if (fixed) {
setFixedPosition({ type, value });
}
@@ -213,9 +259,10 @@ export const CurrentTrainProvider = ({ children }) => {
getCurrentTrain();
}, []); //初回だけ現在の全在線列車取得
useInterval(getCurrentTrain, 15000); //15秒毎に全在線列車取得
const [_0, _1] = useInterval(() => {
getCurrentTrain();
}, 10000); //10秒毎に全在線列車取得
const webview = useRef();
return (
<CurrentTrainContext.Provider
value={{

View File

@@ -1,7 +1,7 @@
import React, { createContext, useContext, useState, useEffect } from "react";
import { useWindowDimensions } from "react-native";
import * as ScreenOrientation from "expo-screen-orientation";
const initialState = { isLandscape: false, setIsLandscape: () => {} };
const initialState = { isLandscape: false, setIsLandscape: (e) => {} };
const DeviceOrientationChange = createContext(initialState);

View File

@@ -6,8 +6,9 @@ import React, {
useLayoutEffect,
FC,
} from "react";
import { AS } from "../storageControl";
import { useStationList } from "./useStationList";
import { AS } from "@/storageControl";
import { useStationList } from "@/stateBox/useStationList";
import { StationProps } from "@/lib/CommonTypes";
const initialState = {
favoriteStation: [],
setFavoriteStation: () => {},
@@ -16,8 +17,8 @@ const initialState = {
type initialStateType = {
favoriteStation: any[];
setFavoriteStation: (d:any)=>void;
lodAddMigration: ()=>void;
setFavoriteStation: (d: any) => void;
lodAddMigration: () => void;
};
const FavoriteStationContext = createContext<initialStateType>(initialState);
@@ -27,8 +28,8 @@ export const useFavoriteStation = () => {
type Props = {
children: React.ReactNode;
};
export const FavoriteStationProvider:FC<Props> = ({ children }) => {
const [favoriteStation, setFavoriteStation] = useState([]);
export const FavoriteStationProvider: FC<Props> = ({ children }) => {
const [favoriteStation, setFavoriteStation] = useState<StationProps[][]>([]);
const { getStationDataFromName } = useStationList();
const lodAddMigration = () => {
const migration = favoriteStation.map((d) => {
@@ -39,13 +40,13 @@ export const FavoriteStationProvider:FC<Props> = ({ children }) => {
useEffect(() => {
AS.getItem("favoriteStation")
.then((d) => {
const returnData = JSON.parse(d);
const returnData: StationProps[][] = JSON.parse(d);
setFavoriteStation(returnData);
})
.catch((error) => {
// エラーログを記録(開発時のみ)
if (__DEV__) {
console.warn('お気に入り駅の読み込みに失敗しました:', error);
console.warn("お気に入り駅の読み込みに失敗しました:", error);
}
});
}, []);

View File

@@ -9,20 +9,8 @@ import {
lineList,
getStationList,
lineList_LineWebID,
} from "../lib/getStationList";
export type StationProps = {
DispNum: string;
JrHpUrl: string;
MyStation: string;
StationMap: string;
StationNumber: string | null;
StationTimeTable: string;
Station_EN: string;
Station_JP: string;
jslodApi: string;
lat: number;
lng: number;
};
} from "@/lib/getStationList";
import { StationProps } from "@/lib/CommonTypes";
type initialStateType = {
originalStationList: StationProps[][];
setOriginalStationList: React.Dispatch<React.SetStateAction<StationProps[]>>;
@@ -134,7 +122,7 @@ export const StationListProvider: FC<Props> = ({ children }) => {
});
}
});
return `MoveDisplayStation('${bootStationList[0].line}_${bootStationList[0].station.MyStation}_${bootStationList[0].station.Station_JP}');document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");`;
return `MoveDisplayStation('${bootStationList[0].line}_${bootStationList[0].station.MyStation}_${bootStationList[0].station.Station_JP}');document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");setReload();`;
};
return (

View File

@@ -1,11 +1,11 @@
import React, { createContext, useContext, useEffect, useState } from "react";
import React, { createContext, FC, useContext, useEffect, useState } from "react";
const initialState = {
getTime: new Date(),
setGetTime: () => {},
setGetTime: (e) => {},
loadingDelayData: true,
setLoadingDelayData: (loading) => {},
delayData: undefined,
setDelayData: () => {},
setDelayData: (e) => {},
};
const TrainDelayDataContext = createContext(initialState);
@@ -13,8 +13,10 @@ const TrainDelayDataContext = createContext(initialState);
export const useTrainDelayData = () => {
return useContext(TrainDelayDataContext);
};
export const TrainDelayDataProvider = ({ children }) => {
type props = {
children: React.ReactNode;
};
export const TrainDelayDataProvider:FC<props> = ({ children }) => {
const [delayData, setDelayData] = useState(undefined);
const [getTime, setGetTime] = useState(new Date());
const [loadingDelayData, setLoadingDelayData] = useState(true);

View File

@@ -1,4 +1,10 @@
import React, { createContext, useContext, useState, useEffect } from "react";
import React, {
createContext,
useContext,
useState,
useEffect,
FC,
} from "react";
import { ASCore } from "../storageControl";
@@ -9,29 +15,29 @@ import { useNotification } from "../stateBox/useNotifications";
const initialState = {
selectedLine: undefined,
setSelectedLine: () => {},
setSelectedLine: (e) => {},
mapsStationData: undefined,
setMapsStationData: () => {},
setMapsStationData: (e) => {},
iconSetting: undefined,
setIconSetting: () => {},
setIconSetting: (e) => {},
mapSwitch: undefined,
setMapSwitch: () => {},
setMapSwitch: (e) => {},
stationMenu: undefined,
setStationMenu: () => {},
setStationMenu: (e) => {},
uiSetting: undefined,
setUiSetting: () => {},
setUiSetting: (e) => {},
LoadError: false,
setLoadError: () => {},
setLoadError: (e) => {},
trainInfo: {
trainNum: undefined,
limited: undefined,
trainData: undefined,
},
setTrainInfo: () => {},
setTrainInfo: (e) => {},
trainMenu: "true",
setTrainMenu: () => {},
updatePermission : false,
setUpdatePermission : () => {},
setTrainMenu: (e) => {},
updatePermission: false,
setUpdatePermission: (e) => {},
injectJavascript: "",
};
@@ -40,33 +46,36 @@ const TrainMenuContext = createContext(initialState);
export const useTrainMenu = () => {
return useContext(TrainMenuContext);
};
export const TrainMenuProvider = ({ children }) => {
type props = { children: React.ReactNode };
export const TrainMenuProvider: FC<props> = ({ children }) => {
const { expoPushToken } = useNotification();
const [selectedLine, setSelectedLine] = useState(undefined);
const [mapsStationData, setMapsStationData] = useState(undefined);
useEffect(() => {
getStationList2().then(setMapsStationData);
}, []);
type boolType = "true" | "false" | undefined;
//画面表示関連
const [iconSetting, setIconSetting] = useState(undefined);
const [mapSwitch, setMapSwitch] = useState(undefined);
const [stationMenu, setStationMenu] = useState(undefined);
const [iconSetting, setIconSetting] = useState<boolType>(undefined);
const [mapSwitch, setMapSwitch] = useState<boolType>(undefined);
const [stationMenu, setStationMenu] = useState<boolType>(undefined);
const [LoadError, setLoadError] = useState(false);
//更新権限所有確認
const [updatePermission, setUpdatePermission] = useState(false);
useEffect(()=>{
fetch("https://n8n.haruk.in/webhook/data-edit-permission?token=" + expoPushToken).then((res)=>res.json())
.then((res)=>{
if(res.data == true){
setUpdatePermission(true);
}else{
setUpdatePermission(false);
}
})
}, [expoPushToken])
useEffect(() => {
fetch(
"https://n8n.haruk.in/webhook/data-edit-permission?token=" + expoPushToken
)
.then((res) => res.json())
.then((res) => {
if (res.data == true) {
setUpdatePermission(true);
} else {
setUpdatePermission(false);
}
});
}, [expoPushToken]);
//列車情報表示関連
const [trainInfo, setTrainInfo] = useState({