97 Commits

Author SHA1 Message Date
harukin-expo-dev-env
7716cb516c Merge commit 'dc7cc555c990fd4a2cd5cf47089339c887eecc75' 2025-07-18 15:42:20 +00:00
harukin-expo-dev-env
70976c0554 Merge commit '8a7285bb20c76d6e99cafd96193957829906f9ac' 2025-07-08 16:44:25 +00:00
harukin-expo-dev-env
5616c7ed96 Merge commit '8212148fb298dc678b811aadf0344731b43e8cf7' 2025-05-04 12:56:37 +00:00
harukin-expo-dev-env
13580a57d4 Merge commit 'bd2248e1a943e574ccc44892122cd9da4df14b68' 2025-04-20 17:22:59 +00:00
harukin-expo-dev-env
c9481fb0c2 Merge commit 'b64138178c4ca99bfcbb4f115403a18674ce8136' 2025-04-14 19:10:10 +00:00
harukin-expo-dev-env
5cda45740c Merge commit '67f40b55c19ff2e94b1168865486bcde7d457cab' 2025-04-10 16:38:21 +00:00
harukin-expo-dev-env
84d1305796 Merge commit 'fdefbc82bd39c8cba29911273db2f96fa39c0e3f' 2025-04-10 15:55:13 +00:00
harukin-expo-dev-env
336e3510fa Merge commit 'af8f3333cd68ea507675ad02ec59ccf2f7959e00' 2025-03-30 02:52:30 +00:00
harukin-expo-dev-env
25780e1664 Merge commit '0a364021ce2fed98257e80cc780ac4020cecb9c1' 2025-03-25 07:27:06 +00:00
harukin-expo-dev-env
e6fab84393 Merge commit 'de2b94292dc97df6e290e91976d01cea24c98ced' 2025-03-22 12:33:34 +00:00
harukin-expo-dev-env
390acdeab7 Merge commit '8c75e06ac18e33588b5bf200d7fccf05d3c34c22' 2025-03-22 11:34:25 +00:00
harukin-expo-dev-env
ff7a5624e6 Merge commit '45500e7a4ae614debd93404339958465db88f71d' 2025-03-19 15:49:36 +00:00
harukin-expo-dev-env
9b79f224d3 Merge commit '2c5023568a0442679b476bd84651eca3fcc90ee1' 2025-03-16 05:56:14 +00:00
harukin-expo-dev-env
2f76e3776f Merge commit '8a48bc48e6eb82921fcda3a84e07db2eca51e614' 2025-03-15 04:23:16 +00:00
harukin-expo-dev-env
026da47d82 Merge commit '23fb2d715a461cb0ebfca1e1944757febd315fec' 2025-03-14 18:29:20 +00:00
harukin-expo-dev-env
29be052bf6 Merge commit 'ab883827e13b5c99556857395ac950ee00c53b83' 2025-03-11 05:26:18 +00:00
harukin-expo-dev-env
2fb7d97d33 Merge commit '31618aab496a7979a39e534d023cb69103b06721' 2025-03-10 15:51:25 +00:00
harukin-expo-dev-env
76ebf8055b Merge commit '26cf84705abd4c9a69ac56fcade483a373089bf8' 2025-03-06 03:52:42 +00:00
harukin-expo-dev-env
7b572cd657 Merge commit 'fa882223d49fec390177131371b99a3101976759' 2025-03-05 11:51:51 +00:00
harukin-expo-dev-env
61fa0f8484 Merge commit 'ede2884c4a7b8a508cfd9f4f7cc87da4efe3db08' 2025-03-04 16:17:50 +00:00
harukin-expo-dev-env
935aaf2610 Merge commit '098cae50533368eec9cfdb933900c503ae46e850' 2025-03-04 15:01:08 +00:00
harukin-expo-dev-env
8ec53d6e06 Merge commit '0aaf171477659e632a23aeb6af39e83d5acf70c2' 2025-02-09 03:21:16 +00:00
harukin-expo-dev-env
e8b1a21a3b Merge commit '4a01c529b47cd85420a4c1feeac87164730dee94' 2025-01-15 12:38:58 +00:00
harukin-expo-dev-env
e6b89842a3 Merge commit '2776f17681ac2bf76a70c268c4db8921c5888a4f' 2025-01-14 07:42:06 +00:00
harukin-expo-dev-env
1fc5220405 Merge commit '58d3eae1d7797a74febc752f4185337a6eb95dad' 2025-01-09 09:56:21 +00:00
harukin-expo-dev-env
5489406578 Merge commit 'a7c4f689bc0762a63b662901f943a62827b765eb' 2024-11-22 05:40:18 +00:00
harukin-expo-dev-env
2b217e98c7 Merge commit 'd8108e2c9c60a60ba7f933af12af996b3cc0491c' 2024-11-22 05:19:00 +00:00
harukin-expo-dev-env
2c2e61a2fa Merge commit '6d3e6623a0774cb489efa3b81335db319fad2b2d' 2024-10-31 12:27:16 +00:00
harukin-expo-dev-env
c222b303df Merge commit '1346909bb74c80bedf1841aefda66a67adb98443' 2024-09-30 13:00:12 +00:00
harukin-expo-dev-env
8f8c095ecd Merge commit 'ab2a18b562c5fe18087f3140449fc7764b969df6' 2024-09-28 20:45:33 +00:00
harukin-expo-dev-env
e31e84ff34 Merge commit '9b91c4a50e1df914f66c6c5b33007caf4b0c9c32' 2024-09-20 15:18:49 +00:00
harukin-expo-dev-env
2c2b355a3e Merge commit '63209ac88878f70d0896dca429277d09ef1bf492' 2024-09-16 16:34:11 +00:00
harukin-expo-dev-env
5461087ca0 Merge commit 'c9a90809c6b178d5b85d51d47521d2541bbed7f6' 2024-09-16 16:31:31 +00:00
harukin-expo-dev-env
57c7285b6e Merge commit '628d2a42c94801ea42c939dd702ebd448176e62f' 2024-09-16 16:10:05 +00:00
harukin-expo-dev-env
5c134c95cc Merge commit '801b3dc3b0dde2f8a46962cfbca1599fb31cb6a4' 2024-09-02 02:29:04 +00:00
harukin-expo-dev-env
8781653fe8 Merge commit '9b4b4bd0d6572d0d0ffdb35ec72559bf035d07a3' 2024-06-05 10:27:22 +00:00
harukin-expo-dev-env
67ccc37c17 Merge commit '35e05e92f50ebca5d4666b9a008915b7f437f86c' 2024-06-05 09:16:05 +00:00
harukin-expo-dev-env
92caab03f5 Merge commit '52c2da333a97234bb27a25baf8af8479d53c3422' 2024-06-03 12:40:26 +00:00
harukin-expo-dev-env
dd3a57b3ae Merge commit 'b9b983a177d37db717b551f8b18d5f6c87aa0e23' 2024-06-03 12:20:23 +00:00
harukin-expo-dev-env
8df32b9c1d Merge commit '7eea78027649dec4dd7492efd8edfb0e61df5eea' 2024-04-28 10:33:20 +00:00
harukin-expo-dev-env
4b901d5015 Merge commit '5d711d37550d288142e3e768a2a0f42a7279d434' 2024-04-18 03:32:42 +00:00
harukin-expo-dev-env
fc5c62685a Merge commit '85e2ad329d89e57be4c094067de48525fe7673e3' 2024-04-18 03:21:26 +00:00
harukin-expo-dev-env
fbc98b2ff7 Merge commit '05167c810a8b727ed6527dbb07c0b9c1de53c171' 2024-04-06 17:19:41 +00:00
harukin-expo-dev-env
3502043176 Merge commit '0efab93a1451818339bfbed97545e6782eafcb9c' 2024-04-06 17:19:32 +00:00
harukin-expo-dev-env
2d0ad8d59e Merge commit 'dd7da102c43348a5420a4b616509d37c8d03a65f' 2024-03-27 15:52:25 +00:00
harukin-expo-dev-env
b5172df7a9 Merge commit '548d5d3747e6491ae421a716e85f7d60be4e41e4' 2024-03-27 15:02:35 +00:00
harukin-expo-dev-env
740d414d2d Merge commit '7e59b8c7bd7d01b35b5b0d6c5be93baed222f660' 2024-03-26 12:59:20 +00:00
harukin-expo-dev-env
8db3e6c218 Merge commit '736f9a65e92257237f347bbe2d02fe88f0e409d6' 2024-03-26 12:54:31 +00:00
harukin-expo-dev-env
fb35b01d2e Merge commit '720b627011a108979ce07a103aff2d728e68cab0' 2024-03-18 12:50:34 +00:00
harukin-expo-dev-env
5fa6b1f73e Merge commit '481ca0158d93b90af0306ed3d54786d61d6281e2' 2024-03-18 04:17:25 +00:00
harukin-expo-dev-env
c16f7401ea Merge commit '5864e821120ec726c6e96fbc8edc6a7172d5bbd7' 2024-03-18 04:04:16 +00:00
harukin-expo-dev-env
f260c5d2dd Merge commit 'a769ccb9512d8c246be82cb1f16673b13b39d4e6' 2024-03-15 18:04:11 +00:00
harukin-expo-dev-env
80e9f1a869 Merge commit 'd8ce2a7f8aac23e1001bbe16690d37c57d1c704f' 2024-03-13 13:27:05 +00:00
harukin-expo-dev-env
26096ba244 Merge commit '5806e2a259e03182d082fe454f4a1932ad9c5e53' 2024-03-13 13:10:22 +00:00
harukin-expo-dev-env
435a910ef9 Merge commit 'f2aed4b945d3e86381ebb964787fcb5aff35fdbd' 2024-03-12 16:47:26 +00:00
harukin-expo-dev-env
68b9236d65 Merge commit '7bd7d951048357c4c0b81d9048906275066e8526' 2024-03-12 16:36:37 +00:00
harukin-expo-dev-env
0148c12e08 Merge commit '75952f4edea5d59554322a5c611483a0052e4e97' 2024-03-12 14:37:09 +00:00
harukin-expo-dev-env
34dc62aee6 Merge commit 'c0cdad36837f27dee7c22930834272052d53d090' 2024-03-09 15:48:41 +00:00
harukin-OneMix4
54ae681f00 Merge commit '8a94b81052a4cf6b833bf298abcd89ed93a0ada2' 2024-01-27 01:37:29 +09:00
harukin-OneMix4
db40351fec Merge commit '431c4c9c0b426250adefbb42db7893233fabb55b' 2024-01-27 01:04:19 +09:00
harukin-OneMix4
2dd8e62f85 Merge commit '485102b5917eaa819c615dbaf47ee27f81a5751f' 2024-01-12 14:04:37 +09:00
harukin-OneMix4
0937fbb619 Merge commit '65080e68f2197f31b8a4ed4bf94ad325aa77e923' 2024-01-09 18:31:30 +09:00
harukin-OneMix4
32edab3289 Merge commit '87129c6815233ea6e42575b83a26c0a2c34a6e5c' 2024-01-09 18:21:41 +09:00
harukin-OneMix4
fa96e68770 Merge commit 'b54f2f6f7e1478cee3f1f3cacf2bc3949d45583f' 2024-01-04 02:38:22 +09:00
harukin-OneMix4
1681be4437 Merge commit '0e06b6636862fa4728d36bb9b934490087cadf02' 2024-01-04 00:47:55 +09:00
harukin-OneMix4
7f96c44e88 Merge commit '0f0d69b22d4e8b3aea9bec06855d38751881055a' 2024-01-03 01:35:33 +09:00
harukin-OneMix4
7d485c466c Merge commit '29c84bcc1ce7bd1d2512b65ef812a313507d8650' 2024-01-03 01:07:31 +09:00
harukin-OneMix4
7869cbee6d Merge commit 'a4e85ff2e6bccb35ecf04f6bdf51ac193585b765' 2023-12-29 03:50:28 +09:00
harukin-OneMix4
c2ad681891 Merge commit '57459d975bbe3a1b4e145331b57a638b2c2fead5' 2023-12-29 02:09:44 +09:00
harukin-OneMix4
163f9ead18 Merge commit 'b23b59eab349139656b2d32c4b19f744a937aa59' 2023-12-25 17:09:41 +09:00
harukin-OneMix4
611fc9953f Merge commit 'e38f550b94a6c89fd2840ff95af392e8e9f49589' 2023-12-25 15:46:35 +09:00
harukin-OneMix4
fd95e99874 Merge commit '9b70843e9c6ed45ebce609952b0202f5ebf877d7' 2023-12-25 05:47:23 +09:00
harukin-OneMix4
f5d0f993db update three month update 2023-12-13 15:56:40 +09:00
harukin-OneMix4
b7e763d265 update three month update 2023-09-17 15:44:19 +09:00
harukin-OneMix4
0afa6f402b 4.5.4.1 2023-07-16 23:00:26 +09:00
harukin-OneMix4
eacce53775 Merge commit '84d36b88cc71ed591c9a50f086ab38cd08177758' 2023-07-16 23:00:05 +09:00
harukin-OneMix4
47b1eb325e なんかマージミスった? 2023-07-16 19:40:44 +09:00
harukin-OneMix4
a145e2c24f Merge commit '711f0bbe9f00200c02fb70757d7c0ca2d0060ed4' 2023-07-16 19:36:57 +09:00
harukin-OneMix4
862742cd3e update build number 2023-06-19 14:03:37 +09:00
harukin-OneMix4
d5f2d367dd Merge commit 'a3e8e3cbbe13e4fc137937493a91708b1dff7cae' 2023-06-18 21:05:04 +09:00
harukin-OneMix4
b1f72f18b5 Merge commit '81f394d6ca2ae418c89452acabe11196e4b7e940' 2023-05-10 17:19:18 +09:00
harukin-OneMix4
d4d86fb7eb 4.5.3 2023-05-10 17:13:10 +09:00
harukin-OneMix4
056a059a68 Merge commit 'bb115afe358eb7f2fb724beb1da13b2be24780b4' 2023-05-10 17:11:56 +09:00
harukin-DeskMini
12676d59cf 4.5.2リリース(本開放/ニュース更新) 2023-03-30 03:28:34 +09:00
harukin-DeskMini
bca2b300d3 4.5.2リリース(封印開放) 2023-03-30 03:25:28 +09:00
harukin-DeskMini
406808ee58 Merge commit '47d84777e2a26235d5442a68ae3b6bcb07f580cb' 2023-03-30 03:21:25 +09:00
harukin-DeskMini
a8aadb7f08 4.5.1 2023-03-27 07:01:47 +09:00
harukin-DeskMini
b810405573 Merge commit '65dd6dd0fdd41f06cfb686d578f9d604185510d3' 2023-03-27 07:01:20 +09:00
harukin-DeskMini
6f62418426 Merge commit '9eca67901906b8852f1f1f2dfa814ed658514b4b' 2023-03-27 01:06:04 +09:00
harukin-DeskMini
88621dd1c8 Merge commit '98b22db4dbea611907c4d7a6a60b7323dbec7a76' 2023-03-27 01:02:57 +09:00
harukin-DeskMini
12d9c1f49d 封印忘れ物 2023-03-26 21:45:04 +09:00
harukin-DeskMini
30c2b8a2f9 4.5.0-リリース用一部封印 2023-03-26 21:42:49 +09:00
harukin-DeskMini
8bc7069c4e Merge commit '816d96d37be6537c9ebcf0be30c74fd154b80dc5' 2023-03-26 21:09:24 +09:00
harukin-OneMix4
737cd25539 Merge commit '64538e33f317c6fe395859673922f63c2e3b0514' 2023-03-02 17:37:40 +09:00
harukin-DeskMini
2c50e5af67 Merge commit 'e93fe7095ef717bd0ddebeb18f28038a374d83f6' 2023-02-01 17:16:10 +09:00
harukin-DeskMini
ea677b4da5 Merge commit '40fb55c8cf5462a40a499ddcc69cb5313e559f84' 2023-01-29 22:10:09 +09:00
harukin-DeskMini
4525443e39 Merge commit 'e35ab09002641b3813d2055ff8107bd8088c4629' 2023-01-29 09:11:58 +09:00
86 changed files with 2222 additions and 5891 deletions

View File

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

View File

@@ -28,7 +28,6 @@ export function AppContainer() {
"JR-Nishi": require("./assets/fonts/jr-nishi.otf"),
Zou: require("./assets/fonts/DelaGothicOne-Regular.ttf"),
"JNR-font": require("./assets/fonts/JNRfont_pict.ttf"),
"DiaPro": require("./assets/fonts/DiaPro-Regular.otf"),
});
return (
<NavigationContainer ref={navigationRef}>

View File

@@ -6,20 +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 { StationDiagramView } from "@/components/StationDiagram/StationDiagramView";
import GeneralWebView from "./GeneralWebView";
const Stack = createStackNavigator();
export function MenuPage() {
@@ -87,7 +86,7 @@ export function MenuPage() {
})
.catch((error) => {
if (__DEV__) {
console.warn("お気に入り駅の読み込みに失敗しました:", error);
console.warn('お気に入り駅の読み込みに失敗しました:', error);
}
});
});
@@ -95,7 +94,7 @@ export function MenuPage() {
return unsubscribe;
}, [navigation, mapHeight, favoriteStation, setFavoriteStation]);
return (
<Stack.Navigator id={null}>
<Stack.Navigator>
<Stack.Screen
name="menu"
options={{
@@ -113,11 +112,6 @@ export function MenuPage() {
/>
)}
/>
<Stack.Screen
name="stDiagram"
options={{ ...optionData, gestureEnabled: false }}
component={StationDiagramView}
/>
<Stack.Screen name="news" options={optionData} component={News} />
<Stack.Screen
name="setting"
@@ -139,11 +133,7 @@ export function MenuPage() {
component={AllTrainDiagramView}
/>
<Stack.Screen name="howto" options={optionData} component={HowTo} />
<Stack.Screen
name="generalWebView"
options={optionData}
component={GeneralWebView}
/>
<Stack.Screen name="generalWebView" options={optionData} component={GeneralWebView} />
</Stack.Navigator>
);
}

View File

@@ -14,7 +14,6 @@ import { AS } from "./storageControl";
import { news } from "./config/newsUpdate";
import { Linking, Platform } from "react-native";
import GeneralWebView from "./GeneralWebView";
import { StationDiagramView } from "@/components/StationDiagram/StationDiagramView";
const Stack = createStackNavigator();
export const Top = () => {
const { webview } = useCurrentTrain();
@@ -38,8 +37,7 @@ export const Top = () => {
return;
}
if (!isFocused()) navigate("positions", { screen: "Apps" });
else if (mapSwitch == "true")
navigate("positions", { screen: "trainMenu" });
else if (mapSwitch == "true") navigate("positions", { screen: "trainMenu" });
else webview.current?.injectJavaScript(`AccordionClassEvent()`);
return;
};
@@ -50,7 +48,7 @@ export const Top = () => {
}, [addListener, mapSwitch]);
return (
<Stack.Navigator id={null} detachInactiveScreens={false}>
<Stack.Navigator detachInactiveScreens={false}>
<Stack.Screen
name="Apps"
options={{
@@ -66,17 +64,8 @@ export const Top = () => {
options={{ ...optionData }}
component={TrainBase}
/>
<Stack.Screen
name="stDiagram"
options={{ ...optionData, gestureEnabled: false }}
component={StationDiagramView}
/>
<Stack.Screen name="howto" options={optionData} component={HowTo} />
<Stack.Screen
name="generalWebView"
options={optionData}
component={GeneralWebView}
/>
<Stack.Screen name="generalWebView" options={optionData} component={GeneralWebView} />
<Stack.Screen name="news" options={optionData} component={News} />
<Stack.Screen
name="trainMenu"

View File

@@ -7,7 +7,7 @@
"android",
"web"
],
"version": "6.0.4",
"version": "6.0.2",
"orientation": "default",
"icon": "./assets/icons/s8600.png",
"splash": {
@@ -22,7 +22,7 @@
"**/*"
],
"ios": {
"buildNumber": "50",
"buildNumber": "48",
"supportsTablet": false,
"bundleIdentifier": "jrshikokuinfo.xprocess.hrkn",
"config": {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

View File

@@ -0,0 +1,157 @@
import React from "react";
import { View, Text, TouchableWithoutFeedback } from "react-native";
import dayjs from "dayjs";
import lineColorList from "../../../assets/originData/lineColorList";
export const EachStopList = ({
i,
index,
stationList,
points,
currentTrainData,
openStationACFromEachTrainInfo,
showThrew,
}) => {
if (!showThrew && i.split(",")[1] == "通過") return null;
const [station, se, time] = i.split(","); // 阿波池田,発,6:21
const Stations = stationList
.map((a) => a.filter((d) => d.StationName == station))
.reduce((newArray, e) => newArray.concat(e), []);
/*Array [
Object {
"StationName": "佐古",
"StationNumber": "T01",
},
Object {
"StationName": "佐古",
"StationNumber": "B01",
},
] */
const StationNumbers =
Stations &&
Stations.filter((d) => d.StationNumber).map((d) => d.StationNumber);
// Array [ "T01", "B01",]
const lineIDs = [];
const EachIDs = [];
StationNumbers.forEach((d) => {
const textArray = d.split("");
lineIDs.push(textArray.filter((s) => "A" < s && s < "Z").join(""));
EachIDs.push(textArray.filter((s) => "0" <= s && s <= "9").join(""));
});
// Array [ "T", "B",]
// Array [ "01", "01",]
const dates = dayjs()
.set("hour", parseInt(time.split(":")[0]))
.set("minute", parseInt(time.split(":")[1]))
.add(isNaN(currentTrainData?.delay) ? 0 : currentTrainData.delay, "minute");
const timeString = se == "通過" ? "" : dates.format("HH:mm").split(":");
const onClickStateText = (string) => {
if (string != "通過") return;
alert("この駅は通過駅です");
};
return (
<TouchableWithoutFeedback
onPress={() =>
openStationACFromEachTrainInfo &&
openStationACFromEachTrainInfo(station)
}
key={station}
>
<View style={{ flexDirection: "row", backgroundColor: "white" }}>
<View
style={{
width: 35,
position: "relative",
marginHorizontal: 15,
flexDirection: "row",
height: "101%",
}}
>
{lineIDs.map((lineID, index) => (
<View
style={{
backgroundColor: `${lineColorList[lineID]}${
se == "通過" ? "80" : ""
}`,
flex: 1,
}}
key={lineID}
>
<View style={{ flex: 1 }} />
<Text
style={{
color: "white",
textAlign: "center",
fontSize: 10,
fontWeight: "bold",
}}
>
{lineIDs[index]}
{"\n"}
{EachIDs[index]}
</Text>
<View style={{ flex: 1 }} />
</View>
))}
</View>
<View
style={{
padding: 8,
flexDirection: "row",
borderBottomWidth: 1,
borderBottomColor: "#f0f0f0",
flex: 1,
}}
>
<Text
style={{ fontSize: 20, color: `#000${se == "通過" ? "5" : ""}` }}
>
{station}
</Text>
<View style={{ flex: 1 }} />
<View style={{ position: "relative", width: 0 }}>
{points ? (
<Text style={{ fontSize: 20, position: "absolute", left: -60 }}>
🚊
</Text>
) : null}
</View>
{!isNaN(currentTrainData?.delay) && currentTrainData?.delay != 0 && (
<Text
style={{
fontSize: 15,
color: "black",
width: 60,
position: "absolute",
right: 120,
textAlign: "right",
textDecorationLine: "line-through",
}}
>
{time}
</Text>
)}
<Text
style={{
fontSize: 20,
color: isNaN(currentTrainData?.delay)
? "black"
: currentTrainData?.delay == 0
? "black"
: "red",
width: 60,
}}
onPress={() => onClickStateText(se)}
>
{se == "通過" ? "レ" : `${timeString[0]}:${timeString[1]}`}
</Text>
<Text style={{ fontSize: 18, width: 50 }}>
{se?.replace("発", "出発").replace("着", "到着")}
</Text>
</View>
</View>
</TouchableWithoutFeedback>
);
};

View File

@@ -1,237 +0,0 @@
import React, { FC } from "react";
import { View, Text, TouchableWithoutFeedback } from "react-native";
import dayjs from "dayjs";
import lineColorList from "../../../assets/originData/lineColorList";
type seTypes =
| "発編"
| "着編"
| "通編"
| "頃編"
| "発"
| "着"
| "休編"
| "通休編"
| string;
type currentTrainDataType = {
Index: number;
num: string;
delay: "入線" | number | undefined;
Pos: string;
PosNum: number;
Direction: number;
Type: string;
Line: string;
};
type props = {
i: string;
index: number;
stationList: { StationName: string; StationNumber: string }[][];
points: boolean;
currentTrainData?: currentTrainDataType;
openStationACFromEachTrainInfo?: (station: string) => void;
showThrew: boolean;
};
export const EachStopList: FC<props> = ({
i,
index,
stationList,
points,
currentTrainData,
openStationACFromEachTrainInfo,
showThrew,
}) => {
const [station, se, time] = i.split(",") as [string, seTypes, string]; // 阿波池田,発,6:21
if (!showThrew) {
if (se == "通過") return null;
if (se == "通編") return null;
if (se == "通休編") return null;
}
const Stations = stationList
.map((a) => a.filter((d) => d.StationName == station))
.reduce((newArray, e) => newArray.concat(e), []);
/*Array [
Object {
"StationName": "佐古",
"StationNumber": "T01",
},
Object {
"StationName": "佐古",
"StationNumber": "B01",
},
] */
const StationNumbers =
Stations &&
Stations.filter((d) => d.StationNumber).map((d) => d.StationNumber);
const [seString, seType] = (() => {
switch (se) {
case "発":
return ["出発", "normal"];
case "着":
return ["到着", "normal"];
case "発編":
return ["出発", "community"];
case "着編":
return ["到着", "community"];
case "通編":
return ["通過", "community"];
case "頃編":
return ["頃", "community"];
case "休編":
case "通休編":
return ["運休", "community"];
default:
return [se, "normal"];
}
})();
// Array [ "T01", "B01",]
// Array [ "T", "B",]
// Array [ "01", "01",]
const textColor = `#${seType == "community" ? "44f" : "000"}${
se == "通過" || se == "通編" || se == "通休編" ? "5" : ""
}`;
return (
<TouchableWithoutFeedback
onPress={() =>
openStationACFromEachTrainInfo &&
openStationACFromEachTrainInfo(station)
}
key={station}
>
<View
style={{
flexDirection: "row",
backgroundColor: (se != "休編" && se != "通休編") ? "#ffffffc2" : "#474747c2",
}}
>
<View
style={{
width: 35,
position: "relative",
marginHorizontal: 15,
flexDirection: "row",
height: "101%",
}}
>
{StationNumbers.map((stn, index) => (
<StationNumbersBox stn={stn} se={se} key={index} />
))}
</View>
<View
style={{
padding: 8,
flexDirection: "row",
borderBottomWidth: 1,
borderBottomColor: "#f0f0f0",
flex: 1,
}}
>
<Text
style={{
fontSize: 20,
color: textColor,
fontStyle: seType == "community" ? "italic" : "normal",
}}
>
{station}
</Text>
<View style={{ flex: 1 }} />
<View style={{ position: "relative", width: 0 }}>
{points && (
<Text style={{ fontSize: 20, position: "absolute", left: -60 }}>
🚊
</Text>
)}
</View>
{!!currentTrainData?.delay &&
currentTrainData?.delay != "入線" &&
currentTrainData?.delay != 0 && (
<Text
style={{
fontSize: 15,
color: textColor,
width: 60,
position: "absolute",
right: 120,
textAlign: "right",
textDecorationLine: "line-through",
fontStyle: seType == "community" ? "italic" : "normal",
}}
>
{time}
</Text>
)}
<StationTimeBox
delay={currentTrainData?.delay}
textColor={textColor}
seType={seType}
se={se}
time={time}
/>
<Text style={{ fontSize: 18, width: 50, color: textColor }}>
{seString}
</Text>
</View>
</View>
</TouchableWithoutFeedback>
);
};
const StationNumbersBox: FC<{ stn: string; se: seTypes }> = (props) => {
const { stn, se } = props;
const lineColor = lineColorList[stn.charAt(0)];
const hasThrew = (se == "通過" || se == "通編" || se == "通休編") ? "80" : "";
const backgroundColor = `${lineColor}${hasThrew}`;
return (
<View style={{ backgroundColor, flex: 1 }} key={stn}>
<View style={{ flex: 1 }} />
<Text
style={{
color: "white",
textAlign: "center",
fontSize: 10,
fontWeight: "bold",
}}
>
{stn.charAt(0)}
{"\n"}
{stn.slice(1)}
</Text>
<View style={{ flex: 1 }} />
</View>
);
};
type StationTimeBoxType = {
delay: "入線" | number | undefined;
textColor: string;
seType: seTypes;
se: string;
time: string;
};
const StationTimeBox: FC<StationTimeBoxType> = (props) => {
const { delay, textColor, seType, se, time } = props;
const dates = dayjs()
.set("hour", parseInt(time.split(":")[0]))
.set("minute", parseInt(time.split(":")[1]))
.add(delay == "入線" || delay == undefined ? 0 : delay, "minute");
return (
<Text
style={{
fontSize: 20,
color:
delay != "入線" && delay != undefined
? delay != 0 && "red"
: textColor,
width: 60,
fontStyle: seType == "community" ? "italic" : "normal",
}}
>
{se.includes("通") && time == "" ? "レ" : dates.format("HH:mm")}
</Text>
);
};

View File

@@ -0,0 +1,46 @@
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,15 +1,8 @@
import React, { FC } from "react";
import React from "react";
import { ScrollView } from "react-native";
import { TrainDataView } from "./TrainDataView";
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> = ({
export const LongHeader = ({
currentTrainData,
currentPosition,
nearTrainIDList,

View File

@@ -1,122 +0,0 @@
import { trainPosition } from "@/lib/trainPositionTextArray";
import React, { FC } from "react";
import { View, Text, TextStyle, ViewStyle } from "react-native";
type stateBox = {
currentTrainData: any;
platformNumber: any;
title: string;
style?: ViewStyle;
mode?: number;
platformDescription: string;
lineNumber: string;
};
export const PositionBox: FC<stateBox> = (props) => {
const {
currentTrainData,
platformNumber,
title,
style,
mode,
platformDescription,
lineNumber,
} = props;
let firstText = "";
let secondText = "";
let marginText = "";
let externalText = "";
const { isBetween, Pos: PosData } = trainPosition(currentTrainData);
if (isBetween === true) {
const { from, to } = PosData;
firstText = from;
secondText = to;
marginText = mode == 2 ? "→" : "↓";
} else {
const { Pos } = PosData;
if (Pos !== "") {
firstText = Pos;
if (platformNumber) {
secondText = `${platformNumber}番乗り場`;
if (lineNumber) {
externalText = `${lineNumber}番線`;
}
} else if (lineNumber) {
secondText = `${lineNumber}番線`;
}
}
}
return (
<View style={{ ...(mode == 2 ? boxStyle2 : boxStyle), ...style }}>
<Text style={{ fontSize: 12, color: "#0099CC" }}>{title}</Text>
<View style={{ flex: 1 }} />
<View style={{ flexDirection: mode == 2 ? "row" : "column" }}>
{firstText && (
<Text style={mode == 2 ? boxTextStyle2 : (isBetween ? boxTextStyle : boxTextStyleBig)}>
{firstText}
</Text>
)}
{marginText && (
<Text style={{ color: "#0099CC", textAlign: "right" }}>
{marginText}
</Text>
)}
{secondText && (
<Text style={mode == 2 ? boxTextStyle2 :(isBetween ? boxTextStyle : boxTextStyleMini)}>
{secondText}
</Text>
)}
</View>
{(platformDescription || externalText) && (
<View style={{ flexDirection: mode == 2 ? "row" : "column" }}>
<Text
style={{
...{ ...(mode == 2 ? boxTextStyle2 : boxTextStyle) },
fontSize: 10,
}}
>
{" " + externalText}
{" " + platformDescription}
</Text>
</View>
)}
</View>
);
};
const boxStyle: ViewStyle = {
flex: 1,
backgroundColor: "white",
borderRadius: 10,
padding: 10,
margin: 10,
};
const boxStyle2: ViewStyle = {
flex: 1,
backgroundColor: "white",
borderRadius: 10,
padding: 5,
margin: 5,
};
const boxTextStyle2: TextStyle = {
fontSize: 18,
color: "#0099CC",
textAlign: "right",
};
const boxTextStyleBig: TextStyle = {
fontSize: 28,
color: "#0099CC",
textAlign: "right",
};
const boxTextStyleMini: TextStyle = {
fontSize: 16,
color: "#0099CC",
textAlign: "right",
};
const boxTextStyle: TextStyle = {
fontSize: 25,
color: "#0099CC",
textAlign: "right",
};

View File

@@ -7,7 +7,7 @@ export const ScrollStickyContent = (props) => {
<View
style={{
alignItems: "center",
backgroundColor: "#ffffffc2",
backgroundColor: "white",
flexDirection: "row",
}}
>
@@ -16,7 +16,7 @@ export const ScrollStickyContent = (props) => {
padding: 8,
flexDirection: "row",
borderBottomWidth: 1,
borderBottomColor: "#ffffffc2",
borderBottomColor: "#f0f0f0",
flex: 1,
}}
>

View File

@@ -1,15 +1,8 @@
import React, { FC } from "react";
import React from "react";
import { ScrollView } from "react-native";
import { TrainDataView } from "./TrainDataView";
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> = ({
export const ShortHeader = ({
currentTrainData,
currentPosition,
nearTrainIDList,

View File

@@ -14,29 +14,24 @@ export const ShowSpecialTrain = ({
};
return (
<>
{isTrainDataNothing &&
trueTrainID?.map((ids) => {
return (
<TouchableOpacity
onPress={() => replaceSpecialTrainDetail(ids)}
style={{
padding: 10,
flexDirection: "row",
borderColor: "blue",
borderWidth: 1,
margin: 10,
borderRadius: 5,
alignItems: "center",
}}
>
<Text
style={{ fontSize: 18, fontWeight: "bold", color: "black" }}
>
本来の列車情報候補を表示:({ids})
</Text>
</TouchableOpacity>
);
})}
{isTrainDataNothing && trueTrainID && (
<TouchableOpacity
onPress={() => replaceSpecialTrainDetail(trueTrainID)}
style={{
padding: 10,
flexDirection: "row",
borderColor: "blue",
borderWidth: 1,
margin: 10,
borderRadius: 5,
alignItems: "center",
}}
>
<Text style={{ fontSize: 18, fontWeight: "bold", color: "black" }}>
本来の列車情報を表示
</Text>
</TouchableOpacity>
)}
</>
);
};

View File

@@ -15,7 +15,21 @@ export const StateBox: FC<stateBox> = (props) => {
<Text style={{ fontSize: 12, color: "#0099CC" }}>{title}</Text>
<View style={{ flex: 1 }} />
<View style={{ flexDirection: mode == 2 ? "row" : "column" }}>
<Text style={mode == 2 ? boxTextStyle2 : boxTextStyle}>{text}</Text>
{text?.match("") ? (
<>
<Text style={mode == 2 ? boxTextStyle2 : boxTextStyle}>
{text.split("")[0]}
</Text>
<Text style={{ color: "#0099CC", textAlign: "right" }}>
{mode == 2 ? "→" : "↓"}
</Text>
<Text style={mode == 2 ? boxTextStyle2 : boxTextStyle}>
{text.split("")[1]}
</Text>
</>
) : (
<Text style={mode == 2 ? boxTextStyle2 : boxTextStyle}>{text}</Text>
)}
</View>
{endText && (
<View style={{ flexDirection: mode == 2 ? "row" : "column" }}>

View File

@@ -0,0 +1,187 @@
import React, { useState, useEffect } from "react";
import { View, TouchableOpacity, useWindowDimensions } from "react-native";
import { StateBox } from "./StateBox";
import { useDeviceOrientationChange } from "../../../stateBox/useDeviceOrientationChange";
import { getStationList2 } from "../../../lib/getStationList";
import { useCurrentTrain } from "../../../stateBox/useCurrentTrain";
import { SheetManager } from "react-native-actions-sheet";
import { trainPosition } from "../../../lib/trainPositionTextArray";
import { TrainPositionDataPush } from "../../発車時刻表/LED_inside_Component/TrainPositionDataPush";
import { getStationID } from "../../../lib/eachTrainInfoCoreLib/getStationData";
import { useStationList } from "../../../stateBox/useStationList";
export const TrainDataView = ({
currentTrainData,
currentPosition,
nearTrainIDList,
openTrainInfo,
mode = 0,
navigate,
}) => {
const { stationList } = useStationList();
const { width, height } = useWindowDimensions();
const { isLandscape } = useDeviceOrientationChange();
const { inject } = useCurrentTrain();
const [mapsStationData, setMapsStationData] = useState(undefined);
const [platformNumber, setPlatformNumber] = useState();
const [platformDescription, setPlatformDescription] = useState();
useEffect(() => {
//currentTrainData.Pos = "鴨川~端岡"; //test
if (!currentTrainData) return;
fetch(
`https://n8n.haruk.in/webhook/JR-shikoku-PosID?PosNum=${currentTrainData?.PosNum}&Line=${currentTrainData?.Line}`
)
.then((res) => res.json())
.then((data) => {
setPlatformNumber(data?.type == "Station" ? data?.platform : undefined);
setPlatformDescription(
data?.type == "Station" ? data?.description : undefined
);
});
}, [currentTrainData]);
useEffect(() => {
getStationList2().then(setMapsStationData);
}, []);
const onLine = !!currentPosition?.toString().length;
const trainPositionText = (trainData) => {
const { isBetween, Pos: PosData } = trainPosition(trainData);
const { from, to, Pos } = PosData;
if (isBetween === true) return `${from}${to}`;
if (Pos == "") return "";
return `${Pos}${platformNumber ? ` ${platformNumber}番線` : ""}`;
};
const [dialog, setDialog] = useState(false);
const [deleteDialog, setDeleteDialog] = useState(false);
const [posInput, setPosInput] = useState("");
const [descInput, setDescInput] = useState("");
const [stationInput, setStationInput] = useState("");
const [stationNumberInput, setStationNumberInput] = useState("");
return (
<>
<TrainPositionDataPush
dialog={dialog}
setDialog={setDialog}
currentTrainData={currentTrainData}
stationInput={stationInput}
stationNumberInput={stationNumberInput}
posInput={posInput}
descInput={descInput}
setPosInput={setPosInput}
setDescInput={setDescInput}
station={{
Station_JP: trainPositionText(currentTrainData),
StationNumber: currentPosition[0],
}}
/>
<View
style={{
flexDirection: "row",
//minHeight: 200,
//height: heightPercentageToDP("20%"),
width: isLandscape ? (width / 100) * 40 : width,
flex: 1,
}}
>
<TouchableOpacity
style={{ flex: 1, flexDirection: "row" }}
//disabled={!onLine}
onLongPress={() => {
const { isBetween, Pos } = trainPosition(currentTrainData);
if (isBetween === true) {
if (
platformNumber == undefined &&
platformDescription == undefined
)
return;
setStationInput(`${Pos.from}${Pos.to}`);
setStationNumberInput(
getStationID(currentTrainData?.Pos, stationList)
);
setPosInput(platformNumber?.toString() || "");
setDeleteDialog(true);
} else {
setStationInput(Pos.Pos);
setStationNumberInput(
getStationID(currentTrainData?.Pos, stationList)
);
setDescInput(platformDescription || "");
setPosInput(platformNumber?.toString() || "");
setDialog(true);
}
}}
onPress={() => {
if (!onLine) return;
const test = [];
Object.keys(mapsStationData).forEach((d) => {
mapsStationData[d].forEach((x) => {
if (x.StationNumber == currentPosition[0])
test.push({ line: d, station: x });
});
if (currentPosition[0] == "M12") {
test.push({
line: "seto",
station: { Station_JP: "児島", MyStation: "0" },
});
}
});
if (!test.length) return;
navigate("positions", { screen: "Apps" });
inject(
`MoveDisplayStation('${test[0].line}_${test[0].station.MyStation}_${test[0].station.Station_JP}');document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");`
);
SheetManager.hide("EachTrainInfo");
}}
>
<StateBox
mode={mode}
title={`現在地 ${currentPosition?.toString()}${onLine ? "▶️" : ""}`}
text={trainPositionText(currentTrainData)}
endText={platformDescription ? `${platformDescription}` : ""}
style={
onLine
? { borderWidth: 1, borderColor: "red", borderStyle: "solid" }
: {}
}
/>
</TouchableOpacity>
<View style={{ flex: 1, flexDirection: mode == 2 ? "row" : "column" }}>
<View style={{ flex: 1, flexDirection: "row" }}>
<StateBox
mode={mode}
title={isNaN(currentTrainData?.delay) ? "状態" : "遅延時分"}
text={`${currentTrainData?.delay}${
isNaN(currentTrainData?.delay) ? "" : "分"
}`}
/>
</View>
<TouchableOpacity
style={{ flex: 1, flexDirection: "row" }}
disabled={nearTrainIDList.length == 0}
onPress={() => {
if (nearTrainIDList.length == 0) return;
openTrainInfo(nearTrainIDList[0]);
}}
>
{nearTrainIDList.length == 0 ? (
<StateBox mode={mode} title="列番" text={currentTrainData?.num} />
) : (
<StateBox
mode={mode}
title="増解結相手を表示▶️"
text={`${nearTrainIDList}`}
style={{
borderWidth: 1,
borderColor: "red",
borderStyle: "solid",
}}
/>
)}
</TouchableOpacity>
</View>
</View>
</>
);
};

View File

@@ -1,229 +0,0 @@
import React, { useState, useEffect, FC } from "react";
import { View, TouchableOpacity, useWindowDimensions } from "react-native";
import { StateBox } from "./StateBox";
import { PositionBox } from "./PositionBox";
import { useDeviceOrientationChange } from "../../../stateBox/useDeviceOrientationChange";
import { getStationList2 } from "../../../lib/getStationList";
import { useCurrentTrain } from "../../../stateBox/useCurrentTrain";
import { SheetManager } from "react-native-actions-sheet";
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";
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,
openTrainInfo,
mode = 0,
navigate,
}) => {
const { stationList } = useStationList();
const { width, height } = useWindowDimensions();
const { isLandscape } = useDeviceOrientationChange();
const { setInjectData } = useCurrentTrain();
const { allCustomTrainData } = useAllTrainDiagram();
const [mapsStationData, setMapsStationData] = useState(undefined);
const [platformNumber, setPlatformNumber] = useState();
const [lineNumber, setLineNumber] = useState();
const [platformDescription, setPlatformDescription] = useState();
type data = {
type: string;
lineNumber: string;
platformNumber: string;
position: string;
stationName: string;
description: string;
};
const [database, setDatabase] = useState<data>(null);
useEffect(() => {
//currentTrainData.Pos = "鴨川~端岡"; //test
if (!currentTrainData) return;
fetch(
`https://n8n.haruk.in/webhook/JR-shikoku-PosID-v3?PosId=${currentTrainData?.PosNum}&lineName=${currentTrainData?.Line}&StationName=${currentTrainData?.Pos}`
)
.then((res) => res.json())
.then((data) => {
if (!data) return;
const {
type,
stationName,
lineNumber,
platformNumber,
position,
description,
} = data;
setDatabase(data);
if (type == "Station") {
setLineNumber(lineNumber);
setPlatformNumber(platformNumber);
setPlatformDescription(description);
} else {
setLineNumber(undefined);
setPlatformNumber(undefined);
setPlatformDescription(undefined);
}
});
}, [currentTrainData]);
useEffect(() => {
getStationList2().then(setMapsStationData);
}, []);
const onLine = !!currentPosition?.toString().length;
const [trainNumber, setTrainNumber] = useState(currentTrainData?.num);
useEffect(() => {
const { TrainNumberOverride } = customTrainDataDetector(
currentTrainData?.num,
allCustomTrainData
);
if (TrainNumberOverride) {
setTrainNumber(TrainNumberOverride);
}else{
setTrainNumber(currentTrainData?.num);
}
}, [currentTrainData?.num, allCustomTrainData]);
// 投稿システム関係
// Dialog表示関係
const [dialog, setDialog] = useState(false);
const [deleteDialog, setDeleteDialog] = useState(false);
//固定値
const [PosNum, setPosNum] = useState<number | undefined>();
const [Pos, setPos] = useState<string>("");
const [Line, setLine] = useState<string>("");
const [StationNum, setStationNum] = useState<string>("");
//編集情報
const [lineInput, setLineInput] = useState<string>("");
const [posInput, setPosInput] = useState<string>("");
const [descInput, setDescInput] = useState<string>("");
const openEditWindow = () => {
const { isBetween, Pos } = trainPosition(currentTrainData);
if (isBetween === true) return;
//固定値
setPosNum(currentTrainData?.PosNum);
setPos(currentTrainData?.Pos);
setLine(currentTrainData?.Line);
setStationNum(getStationID(currentTrainData?.Pos, stationList));
//入力欄
setPosInput(database?.platformNumber?.toString() || "");
setDescInput(database?.description || "");
setLineInput(database?.lineNumber?.toString() || "");
setDialog(true);
};
return (
<>
<StationPosPushDialog
// Dialog表示関係
dialog={dialog}
setDialog={setDialog}
// 固定情報
PosNum={PosNum}
Pos={Pos}
Line={Line}
StationNum={StationNum}
// 入力欄
lineInput={lineInput}
setLineInput={setLineInput}
posInput={posInput}
setPosInput={setPosInput}
descInput={descInput}
setDescInput={setDescInput}
/>
<View
style={{
flexDirection: "row",
//minHeight: 200,
//height: heightPercentageToDP("20%"),
width: isLandscape ? (width / 100) * 40 : width,
flex: 1,
}}
>
<TouchableOpacity
style={{ flex: 1, flexDirection: "row" }}
//disabled={!onLine}
//onLongPress={openEditWindow}
onLongPress={()=>{
if (!onLine) return;
setInjectData({ type:"train", value:currentTrainData?.num, fixed:true});
navigate("positions", { screen: "Apps" });
SheetManager.hide("EachTrainInfo");
}}
onPress={() => {
if (!onLine) return;
setInjectData({ type: "station", value: currentPosition[0], fixed: false });
navigate("positions", { screen: "Apps" });
SheetManager.hide("EachTrainInfo");
}}
>
<PositionBox
mode={mode}
title={`現在地 ${currentPosition?.toString()}${onLine ? "▶️" : ""}`}
currentTrainData={currentTrainData}
platformNumber={platformNumber}
lineNumber={lineNumber}
platformDescription={platformDescription || ""}
style={
onLine
? { borderWidth: 1, borderColor: "red", borderStyle: "solid" }
: {}
}
/>
</TouchableOpacity>
<View style={{ flex: 1, flexDirection: mode == 2 ? "row" : "column" }}>
<View style={{ flex: 1, flexDirection: "row" }}>
<StateBox
mode={mode}
title={isNaN(currentTrainData?.delay) ? "状態" : "遅延時分"}
text={`${currentTrainData?.delay}${
isNaN(currentTrainData?.delay) ? "" : "分"
}`}
/>
</View>
<TouchableOpacity
style={{ flex: 1, flexDirection: "row" }}
disabled={nearTrainIDList.length == 0}
onPress={() => {
if (nearTrainIDList.length == 0) return;
openTrainInfo(nearTrainIDList[0]);
}}
>
{nearTrainIDList.length == 0 ? (
<StateBox mode={mode} title="列番" text={trainNumber} />
) : (
<StateBox
mode={mode}
title="増解結相手を表示▶️"
text={`${nearTrainIDList}`}
style={{
borderWidth: 1,
borderColor: "red",
borderStyle: "solid",
}}
/>
)}
</TouchableOpacity>
</View>
</View>
</>
);
};

View File

@@ -42,19 +42,21 @@ export const EachTrainInfoCore = ({
from,
navigate,
}) => {
const { currentTrain, getCurrentStationData, getPosition } =
useCurrentTrain();
const { currentTrain } = useCurrentTrain();
const { originalStationList, stationList } = useStationList();
const { allTrainDiagram: trainList, allCustomTrainData } =
const { allTrainDiagram: trainList, allCustonTrainData } =
useAllTrainDiagram();
const { setTrainInfo } = useTrainMenu();
const [currentTrainData, setCurrentTrainData] = useState();
useEffect(() => {
const stationData = getCurrentStationData(data.trainNum);
if (stationData) {
setCurrentTrainData(stationData);
}
if (!currentTrain.length) return;
setCurrentTrainData(
checkDuplicateTrainData(
currentTrain.filter((d) => d.num == data.trainNum),
stationList
)
);
}, [currentTrain, data.trainNum]);
useEffect(() => {
@@ -83,36 +85,27 @@ export const EachTrainInfoCore = ({
const [haveThrough, setHaveThrough] = useState(false);
// 使用例
const [stopStationIDList, setStopStationList] = useState([]);
const stopStationIDList = trainDataWidhThrough.map((i) => {
const [station, se, time] = i.split(",");
const Stations = stationList.map((a) =>
a.filter((d) => d.StationName == station)
);
const StationNumbers =
Stations &&
Stations.reduce((newArray, e) => {
return newArray.concat(e);
}, []).map((d) => d.StationNumber);
return StationNumbers;
});
useEffect(() => {
const x = trainDataWidhThrough.map((i) => {
const stopStationList = trainData.map((i) => {
const [station, se, time] = i.split(",");
const Stations = stationList.map((a) =>
a.filter((d) => d.StationName == station)
);
const StationNumbers =
Stations &&
Stations.reduce((newArray, e) => {
return newArray.concat(e);
}, []).map((d) => d.StationNumber);
return StationNumbers;
});
setStopStationList(x);
}, [trainDataWidhThrough]);
useEffect(() => {
const isCancel = [];
const stopStationList = trainData.map((i, index, array) => {
const [station, se, time] = i.split(",");
const [nextStation, nextSe, nextTime] =
array[index + 1]?.split(",") || [];
isCancel.push(se.includes("休") && nextSe.includes("休"));
if (se == "通編") setHaveThrough(true);
return stationList.map((a) => a.filter((d) => d.StationName == station));
});
const allThroughStationList = stopStationList.map((i, index, array) => {
let allThroughStation = [];
if (index == array.length - 1) return;
const firstItem = array[index];
const secondItem = array[index + 1];
let betweenStationLine = "";
@@ -137,9 +130,7 @@ export const EachTrainInfoCore = ({
d.StationNumber > baseStationNumberFirst &&
d.StationNumber < baseStationNumberSecond
) {
allThroughStation.push(
`${d.Station_JP},${isCancel[index] ? "通休編" : "通過"},`
);
allThroughStation.push(`${d.Station_JP},通過,`);
setHaveThrough(true);
reverse = false;
} else {
@@ -147,9 +138,7 @@ export const EachTrainInfoCore = ({
d.StationNumber < baseStationNumberFirst &&
d.StationNumber > baseStationNumberSecond
) {
allThroughStation.push(
`${d.Station_JP},${isCancel[index] ? "通休編" : "通過"},`
);
allThroughStation.push(`${d.Station_JP},通過,`);
setHaveThrough(true);
reverse = true;
}
@@ -208,18 +197,15 @@ export const EachTrainInfoCore = ({
const scrollHandlers = actionSheetRef
? useScrollHandlers("scrollview-1", actionSheetRef)
: null;
const [trueTrainID, setTrueTrainID] = useState([]);
const [trueTrainID, setTrueTrainID] = useState();
useEffect(() => {
if (!data.trainNum) return;
const TD = trainList[data.trainNum];
setHeadStation([]);
setTailStation([]);
if (!TD) {
const specialTrainActualIDs = searchSpecialTrain(
data.trainNum,
trainList
);
setTrueTrainID(specialTrainActualIDs || []);
const specialTrainActualID = searchSpecialTrain(data.trainNum, trainList);
setTrueTrainID(specialTrainActualID || undefined);
setTrainData([]);
return;
}
@@ -260,37 +246,72 @@ export const EachTrainInfoCore = ({
}, [trainData, data]);
useEffect(() => {
const position = getPosition(currentTrainData);
if (stopStationIDList.length == 0) return;
if (position) {
if (position.length > 1) {
if (position[0] == "-Iyo") {
position[0] =
stopStationIDList[
stopStationIDList.findIndex((d) => d.includes("U14")) - 1
][0];
} else if (position[0] == "+Iyo") {
position[0] =
stopStationIDList[
stopStationIDList.findIndex((d) => d.includes("U14")) + 1
][0];
}
if (position[1] == "+Iyo") {
position[1] =
stopStationIDList[
stopStationIDList.findIndex((d) => d.includes("U14")) + 1
][0];
} else if (position[1] == "-Iyo") {
position[1] =
stopStationIDList[
stopStationIDList.findIndex((d) => d.includes("U14")) - 1
][0];
}
//currentTrainData.Pos = "鴨川~端岡"; //test
if (!currentTrainData) return;
if (!currentTrainData?.Pos) return;
if (currentTrainData?.Pos.match("")) {
const pos = currentTrainData?.Pos.replace("(下り)", "")
.replace("(上り)", "")
.replace("(徳島線)", "")
.replace("(高徳線)", "")
.split("");
const direction = parseInt(currentTrainData?.Direction) || 0;
if (pos[0] == "児島" && pos[1] == "宇多津") {
setCurrentPosition(["M12", "Y09"]);
return;
} else if (pos[1] == "児島" && pos[0] == "宇多津") {
setCurrentPosition(["Y09", "M12"]);
return;
} else if (pos[0] == "伊予若宮" && pos[1] == "伊予白滝") {
setCurrentPosition(["S18", "S14"]);
return;
} else if (pos[0] == "伊予白滝" && pos[1] == "伊予若宮") {
setCurrentPosition(["S14", "S18"]);
return;
} else if (pos[0] == "伊予大洲" && pos[1] == "伊予若宮") {
setCurrentPosition(["U14", "U14"]);
return;
} else if (pos[0] == "伊予若宮" && pos[1] == "伊予大洲") {
setCurrentPosition(["U14", "U14"]);
return;
}
setCurrentPosition(position);
const currentPosID = Object.keys(originalStationList).map((key) => {
let firstStation = false;
let firstStationID = "";
let secondStation = false;
let secondStationID = "";
originalStationList[key].forEach((station) => {
if (station.Station_JP === pos[0]) {
firstStation = true;
firstStationID = station.StationNumber;
}
if (station.Station_JP === pos[1]) {
secondStation = true;
secondStationID = station.StationNumber;
}
});
if (firstStation && secondStation) {
return [firstStationID, secondStationID];
} else return false;
});
const currentPos = currentPosID.filter((d) => d != false)[0];
if (currentPos) {
setCurrentPosition(direction == 0 ? currentPos.reverse() : currentPos);
} else if (direction == 0) {
setCurrentPosition([
getStationID(pos[1], stationList),
getStationID(pos[0], stationList),
]);
} else {
setCurrentPosition([
getStationID(pos[0], stationList),
getStationID(pos[1], stationList),
]);
}
} else {
setCurrentPosition([getStationID(currentTrainData?.Pos, stationList)]);
}
}, [currentTrainData,stopStationIDList]);
}, [currentTrainData]);
useEffect(() => {
//列車現在地アイコン表示スイッチ
@@ -300,23 +321,21 @@ 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);
const train = customTrainDataDetector(d, allCustonTrainData);
let TrainNumber = "";
if (train.trainNumDistance != undefined) {
const timeInfo =
parseInt(d.replace("M", "").replace("D", "")) - train.trainNumDistance;
TrainNumber = timeInfo + "号";
}
const limitedData = getTrainType({ type: train.type });
const payload = {
data: {
trainNum: d,
limited: `${limitedData.data}:${train.trainName}${TrainNumber}`,
limited: `${getTrainType(train.type).data}:${
train.trainName
}${TrainNumber}`,
},
navigate,
from: from == "LED" ? "LED2" : "NearTrainDiagramView",
@@ -373,8 +392,6 @@ export const EachTrainInfoCore = ({
containerProps={{
style: {
maxHeight: isLandscape ? height - 94 : (height / 100) * 70,
backgroundColor:
customTrainType.data === "notService" ? "#777777ff" : "white",
},
}}
shortHeader={
@@ -405,11 +422,6 @@ export const EachTrainInfoCore = ({
/>
}
>
{customTrainType.data === "notService" && (
<Text style={{ backgroundColor: "#ffffffc2", fontWeight: "bold" }}>
この列車には乗車できません
</Text>
)}
{headStation.length != 0 &&
headStation.map((i, index) =>
showHeadStation.findIndex((d) => d == index) == -1 ? (
@@ -429,7 +441,6 @@ export const EachTrainInfoCore = ({
borderRadius: 5,
alignItems: "center",
}}
key={i.station + "-head"}
>
<Text
style={{ fontSize: 18, fontWeight: "bold", color: "black" }}
@@ -459,7 +470,6 @@ export const EachTrainInfoCore = ({
margin: 10,
borderRadius: 5,
alignItems: "center",
backgroundColor: "#ffffffc2",
}}
>
<Text style={{ fontSize: 18, fontWeight: "bold", color: "black" }}>
@@ -469,7 +479,7 @@ export const EachTrainInfoCore = ({
)}
{trainDataWidhThrough.map((i, index) =>
i.split(",")[1] == "提" ? (
<DataFromButton i={i} key={i + "-data"} />
<DataFromButton i={i} />
) : (
<EachStopList
{...{
@@ -481,13 +491,9 @@ export const EachTrainInfoCore = ({
openStationACFromEachTrainInfo,
showThrew,
}}
key={i + "-stop"}
/>
)
)}
<Text style={{ backgroundColor: "#ffffffc2" }}>
時刻が斜体,青色になっている時刻はコミュニティで追加されている独自データです
</Text>
{tailStation.length != 0 &&
tailStation.map(({ station, dia }, index) =>
showTailStation.findIndex((d) => d == index) == -1 ? (
@@ -528,7 +534,6 @@ export const EachTrainInfoCore = ({
flexDirection: "row",
borderBottomWidth: 1,
borderBottomColor: "#f0f0f0",
backgroundColor: "#ffffffc2",
flex: 1,
}}
>

View File

@@ -10,9 +10,6 @@ import { InfogramText } from "@/components/ActionSheetComponents/EachTrainInfoCo
import { useTrainMenu } from "@/stateBox/useTrainMenu";
import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
import { useNotification } from "@/stateBox/useNotifications";
import { getStringConfig } from "@/lib/getStringConfig";
import { FontAwesome, MaterialCommunityIcons } from "@expo/vector-icons";
import { getPDFViewURL } from "@/lib/getPdfViewURL";
type Props = {
data: { trainNum: string; limited: string };
@@ -47,82 +44,86 @@ export const HeaderText: FC<Props> = ({
const { limited, trainNum } = data;
const { updatePermission } = useTrainMenu();
const { allCustomTrainData } = useAllTrainDiagram();
const { allCustonTrainData } = useAllTrainDiagram();
const { expoPushToken } = useNotification();
// 列車名、種別、フォントの取得
const [
typeName,
trainName,
fontAvailable,
isOneMan,
infogram,
isEdit,
uwasa,
vehicleFormation,
trainInfoUrl,
] = useMemo(() => {
const {
type,
trainName,
trainNumDistance,
infogram,
isEdit,
uwasa,
vehicleFormation,
trainInfoUrl,
} = customTrainDataDetector(trainNum, allCustomTrainData);
const [typeString, fontAvailable, isOneMan] = getStringConfig(
type,
trainNum
);
switch (true) {
case trainName !== "":
// 特急の場合は、列車名を取得
// 列番対称データがある場合はそれから列車番号を取得
return [
typeString,
trainName +
(trainNumDistance !== null
? ` ${parseInt(trainNum) - trainNumDistance}`
: ""),
fontAvailable,
isOneMan,
infogram,
isEdit,
uwasa,
vehicleFormation,
trainInfoUrl,
];
case trainData[trainData.length - 1] === undefined:
return [
typeString,
"",
fontAvailable,
isOneMan,
infogram,
isEdit,
uwasa,
vehicleFormation,
trainInfoUrl,
];
default:
// 行先がある場合は、行先を取得
return [
typeString,
migrateTrainName(
trainData[trainData.length - 1].split(",")[0] + "行き"
),
fontAvailable,
isOneMan,
infogram,
isEdit,
uwasa,
vehicleFormation,
trainInfoUrl,
];
}
}, [trainData]);
const [typeName, trainName, fontAvailable, isOneMan, infogram] =
useMemo(() => {
const customTrainData = customTrainDataDetector(
trainNum,
allCustonTrainData
);
const [type, fontAvailable, isOneMan] = (() => {
switch (customTrainData.type) {
case "LTDEXP":
return ["特急", true, false];
case "Rapid":
return ["快速", true, false];
case "Normal":
return ["普通", true, false];
case "OneManRapid":
return ["快速", true, true];
case "OneMan":
return ["普通", true, true];
case "NightLTDEXP":
return ["特急", true, false];
case "SPCL":
return ["臨時", false, false];
case "SPCL_EXP":
return ["臨時特急", false, false];
case "SPCL_Rapid":
return ["臨時快速", true, false];
case "SPCL_Normal":
return ["臨時", true, false];
case "Freight":
return ["貨物", false, false];
case "Other":
switch (true) {
case !!trainNum.includes("T"):
return ["単機回送", false, false];
case !!trainNum.includes("R"):
case !!trainNum.includes("E"):
case !!trainNum.includes("L"):
case !!trainNum.includes("A"):
case !!trainNum.includes("B"):
return ["回送", false, false];
case !!trainNum.includes("H"):
return ["試運転", false, false];
}
return ["", false, false];
}
})();
switch (true) {
case customTrainData.trainName !== "":
// 特急の場合は、列車名を取得
// 列番対称データがある場合はそれから列車番号を取得
const distance = customTrainData.trainNumDistance;
const number =
distance !== null ? ` ${parseInt(trainNum) - distance}` : "";
const trainName = customTrainData.trainName + number;
return [
type,
trainName,
fontAvailable,
isOneMan,
customTrainData.infogram,
];
case trainData[trainData.length - 1] === undefined:
return [type, "", fontAvailable, isOneMan, customTrainData.infogram];
default:
// 行先がある場合は、行先を取得
return [
type,
migrateTrainName(
trainData[trainData.length - 1].split(",")[0] + "行き"
),
fontAvailable,
isOneMan,
customTrainData.infogram,
];
}
}, [trainData]);
return (
<View
@@ -133,28 +134,19 @@ export const HeaderText: FC<Props> = ({
>
<TrainIconStatus {...{ data, navigate, from }} />
<TouchableOpacity
style={{
borderRadius: 5,
flexDirection: "row",
alignItems: "center",
...(trainInfoUrl
? {
borderWidth: 0,
borderBottomWidth: 1,
borderStyle: "solid",
borderColor: "white",
}
: {}),
}}
onPress={() => {
if (!trainInfoUrl) return;
const uri = trainInfoUrl.includes("pdf")
? getPDFViewURL(trainInfoUrl)
: trainInfoUrl;
navigate("generalWebView", { uri, useExitButton: true });
style={{ borderRadius: 5, flexDirection: "row", alignItems: "center" }}
onLongPress={() => {
navigate("generalWebView", {
uri:
"https://jr-shikoku-data-post-system.pages.dev?trainNum=" +
trainNum +
"&token=" +
expoPushToken,
useExitButton: false,
});
SheetManager.hide("EachTrainInfo");
}}
disabled={!trainInfoUrl}
disabled={!updatePermission}
>
<Text
style={{
@@ -168,48 +160,16 @@ export const HeaderText: FC<Props> = ({
{typeName}
</Text>
{isOneMan && <OneManText />}
<Text style={{...textConfig,...trainName.length >10 ?{fontSize:14}:{} }}>{trainName}</Text>
<Text style={textConfig}>{trainName}</Text>
<InfogramText infogram={infogram} />
{/* {trainInfoUrl && (
<MaterialCommunityIcons
name={"open-in-new"}
color="white"
size={15}
/>
)} */}
</TouchableOpacity>
{isEdit && (
<FontAwesome
name="commenting-o"
size={20}
color="white"
style={{ marginLeft: 5 }}
onPress={() =>
alert(
`[このアイコン、列車データはコミュニティによってリアルタイム追加されています。]\n使用車両情報:\n${vehicleFormation}\n投稿者メモ:\n${
uwasa || "なし"
}`
)
}
/>
)}
<View style={{ flex: 1 }} />
<TouchableOpacity
onLongPress={() => {
if (!updatePermission) return;
const uri = `https://jr-shikoku-data-post-system.pages.dev?trainNum=${trainNum}&token=${expoPushToken}`;
navigate("generalWebView", { uri, useExitButton: false });
SheetManager.hide("EachTrainInfo");
}}
disabled={!updatePermission}
>
<Text style={textConfig}>
{showHeadStation.map((d) => `${headStation[d].id} + `)}
{trainNum}
{showTailStation.map((d) => ` + ${tailStation[d].id}`)}
</Text>
</TouchableOpacity>
<Text style={textConfig}>
{showHeadStation.map((d) => `${headStation[d].id} + `)}
{trainNum}
{showTailStation.map((d) => ` + ${tailStation[d].id}`)}
</Text>
<TrainViewIcon {...{ data, navigate, from }} />
</View>

View File

@@ -23,12 +23,12 @@ export const TrainIconStatus: FC<Props> = ({ data, navigate, from }) => {
const [trainIcon, setTrainIcon] = useState(null);
const [anpanmanStatus, setAnpanmanStatus] = useState<apt>();
const [address, setAddress] = useState("");
const { allCustomTrainData } = useAllTrainDiagram();
const { allCustonTrainData } = useAllTrainDiagram();
useEffect(() => {
if (!data.trainNum) return;
const { img, infoUrl } = customTrainDataDetector(
data.trainNum,
allCustomTrainData
allCustonTrainData
);
if (img) setTrainIcon(img);
if (infoUrl) setAddress(infoUrl);
@@ -111,13 +111,13 @@ export const TrainIconStatus: FC<Props> = ({ data, navigate, from }) => {
{move ? (
<Image
source={{ uri: trainIcon }}
style={{ height: 30, width: 24, marginRight: 5 }}
resizeMethod="resize"
style={{ height: 34, width: 30, marginRight: 5 }}
resizeMethod="scale"
/>
) : (
<Ionicons
{...anpanmanStatus}
size={24}
size={30}
style={{ marginRight: 5 }}
/>
)}

View File

@@ -1,14 +1,10 @@
import React, { FC, useRef } from "react";
import React, { useRef } from "react";
import { View, Platform } from "react-native";
import ActionSheet from "react-native-actions-sheet";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { SpecialTrainInfoBox } from "../Menu/SpecialTrainInfoBox";
type props = {
payload: { navigate: (screen: string, params?: object) => void };
};
export const SpecialTrainInfo: FC<props> = ({ payload }) => {
export const SpecialTrainInfo = ({ payload }) => {
const { navigate } = payload;
const actionSheetRef = useRef(null);
const insets = useSafeAreaInsets();

View File

@@ -19,8 +19,6 @@ import { 駅構内図 } from "./StationDeteilView/StationInsideMapButton";
import { WebSiteButton } from "./StationDeteilView/WebSiteButton";
import { StationTimeTableButton } from "./StationDeteilView/StationTimeTableButton";
import { StationTrainPositionButton } from "./StationDeteilView/StationTrainPositionButton";
import { StationDiagramButton } from "./StationDeteilView/StationDiagramButton";
import { useTrainMenu } from "@/stateBox/useTrainMenu";
export const StationDeteilView = (props) => {
if (!props.payload) return <></>;
@@ -28,7 +26,6 @@ export const StationDeteilView = (props) => {
const { width } = useWindowDimensions();
const { busAndTrainData } = useBusAndTrainData();
const [trainBus, setTrainBus] = useState();
const { updatePermission } = useTrainMenu();
useEffect(() => {
if (!currentStation) return () => {};
@@ -135,11 +132,6 @@ export const StationDeteilView = (props) => {
onExit={onExit}
/>
)}
{updatePermission &&<StationDiagramButton
navigate={navigate}
onExit={onExit}
currentStation={currentStation}
/>}
{!currentStation[0].StationTimeTable || (
<StationTimeTableButton
info={info}

View File

@@ -1,40 +0,0 @@
import React, { FC } from "react";
import { Linking } from "react-native";
import { FontAwesome } from "@expo/vector-icons";
import { TicketBox } from "@/components/atom/TicketBox";
type Props = {
navigate: (screen: string, params?: object) => void;
onExit: () => void;
currentStation: {
Station_JP: string;
Station_EN: string;
StationName?: string;
MyStation?: string;
StationNumber: string;
DispNum?: string;
StationTimeTable: string;
StationMap?: string;
JrHpUrl?: string;
lat: number;
lng: number;
jslodApi: string;
}[];
};
export const StationDiagramButton: FC<Props> = (props) => {
const { navigate, onExit, currentStation } = props;
return (
<TicketBox
backgroundColor={"#8F5902"}
icon={<FontAwesome name="table" color="white" size={50} />}
flex={1}
onPressButton={() => {
navigate("stDiagram", {
currentStation,
});
onExit();
}}
>
v2
</TicketBox>
);
};

View File

@@ -1,5 +1,6 @@
import { FC } from "react";
import { TouchableOpacity, View, Text, Linking } from "react-native";
import { useStationList } from "@/stateBox/useStationList";
import { useCurrentTrain } from "@/stateBox/useCurrentTrain";
import AntDesign from "react-native-vector-icons/AntDesign";
type Props = {
@@ -9,7 +10,10 @@ type Props = {
};
export const StationTrainPositionButton: FC<Props> = (props) => {
const { stationNumber, onExit, navigate } = props;
const { setInjectData } = useCurrentTrain();
const {
inject,
} = useCurrentTrain();
const { getInjectJavascriptAddress } = useStationList();
return (
<TouchableOpacity
style={{
@@ -19,16 +23,12 @@ export const StationTrainPositionButton: FC<Props> = (props) => {
alignContent: "center",
alignItems: "center",
margin: 2,
flex: 1,
}}
onLongPress={() => {
navigate("positions", { screen: "Apps" });
setInjectData({ type: "station", value:stationNumber, fixed: true });
onExit();
flex: 1
}}
onPress={() => {
navigate("positions", { screen: "Apps" });
setInjectData({ type: "station", value: stationNumber, fixed: false });
const script = getInjectJavascriptAddress(stationNumber);
inject(script);
onExit();
}}
>

View File

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

View File

@@ -10,7 +10,6 @@ import {
Keyboard,
ScrollView,
Linking,
Image,
} from "react-native";
import { useAllTrainDiagram } from "../stateBox/useAllTrainDiagram";
@@ -20,12 +19,9 @@ import { SheetManager } from "react-native-actions-sheet";
import { useNavigation } from "@react-navigation/native";
import { BigButton } from "./atom/BigButton";
import { Switch } from "react-native-elements";
import { migrateTrainName } from "@/lib/eachTrainInfoCoreLib/migrateTrainName";
import { OneManText } from "./ActionSheetComponents/EachTrainInfoCore/HeaderTextParts/OneManText";
import { getStringConfig } from "@/lib/getStringConfig";
export default function AllTrainDiagramView() {
const { goBack, navigate } = useNavigation();
const { keyList, allTrainDiagram, allCustomTrainData } = useAllTrainDiagram();
const { keyList, allTrainDiagram, allCustonTrainData } = useAllTrainDiagram();
const [input, setInput] = useState(""); // 文字入力
const [keyBoardVisible, setKeyBoardVisible] = useState(false);
const [useStationName, setUseStationName] = useState(false);
@@ -57,14 +53,14 @@ export default function AllTrainDiagramView() {
}, []);
const openTrainInfo = (d) => {
const train = customTrainDataDetector(d, allCustomTrainData);
const train = customTrainDataDetector(d, allCustonTrainData);
let TrainNumber = "";
if (train.trainNumDistance != undefined) {
const timeInfo =
parseInt(d.replace("M", "").replace("D", "")) - train.trainNumDistance;
TrainNumber = timeInfo + "号";
}
const type = getTrainType({type:train.type}).data;
const type = getTrainType(train.type).data;
const limited = `${type}:${train.trainName}${TrainNumber}`;
const payload = {
data: { trainNum: d, limited },
@@ -75,75 +71,6 @@ export default function AllTrainDiagramView() {
payload,
});
};
const Item = ({ id, openTrainInfo }) => {
const { img, trainName, type, trainNumDistance, infogram } =
customTrainDataDetector(id, allCustomTrainData);
const [typeString, fontAvailable, isOneMan] = getStringConfig(type, id);
const trainNameString = (() => {
switch (true) {
case trainName !== "":
// 特急の場合は、列車名を取得
// 列番対称データがある場合はそれから列車番号を取得
const distance = trainNumDistance;
const number =
distance !== null ? ` ${parseInt(id) - distance}` : "";
return trainName + number;
case allTrainDiagram[id] === undefined:
return "";
default:
// 行先がある場合は、行先を取得
const s = allTrainDiagram[id].split("#");
const hoge = s[s.length - 2].split(",")[0];
return migrateTrainName(hoge + "行き");
}
})();
return (
<TouchableOpacity
style={{
padding: 5,
flexDirection: "row",
borderColor: "white",
borderWidth: 1,
margin: 5,
borderRadius: 5,
alignItems: "center",
}}
onPress={() => openTrainInfo(id)}
>
{img && (
<Image
source={{ uri: img }}
style={{ width: 20, height: 20, marginLeft: 10, marginRight: 10 }}
/>
)}
{typeString && (
<Text
style={{
fontSize: 20,
color: "white",
fontFamily: fontAvailable ? "JR-Nishi" : undefined,
fontWeight: !fontAvailable ? "bold" : undefined,
marginRight: 5,
}}
>
{typeString}
</Text>
)}
{isOneMan && <OneManText />}
{trainNameString && (
<Text style={{ fontSize: 20, fontWeight: "bold", color: "white" }}>
{trainNameString}
</Text>
)}
<View style={{ flex: 1 }} />
<Text style={{ fontSize: 20, fontWeight: "bold", color: "white" }}>
{id}
</Text>
</TouchableOpacity>
);
};
return (
<View style={{ backgroundColor: "#0099CC", height: "100%" }}>
<FlatList
@@ -151,20 +78,10 @@ export default function AllTrainDiagramView() {
style={{ flex: 1 }}
data={keyList?.filter((d) => {
if (useStationName) {
const EachStopInfo = allTrainDiagram[d].split("#");
const ls = input.split(",").map((inputStationValue) => {
const isHit = EachStopInfo.find((dx) => {
if (!dx) return undefined;
const returnData = dx.split(",")[0] == inputStationValue;
if (returnData) {
const isThrew = dx.split(",")[1].includes("通");
if (isThrew) return undefined;
}
return returnData;
});
return isHit;
const ls = input.split(",").map((stationName) => {
return allTrainDiagram[d].includes(stationName);
});
return !ls.includes(undefined);
return !ls.includes(false);
}
if (useRegex) {
try {
@@ -174,8 +91,7 @@ export default function AllTrainDiagramView() {
return false;
}
}
const { img, trainName, type, trainNumDistance, infogram, TrainNumberOverride } = customTrainDataDetector(d, allCustomTrainData);
return d.includes(input) || trainName.includes(input) || (TrainNumberOverride && TrainNumberOverride.includes(input));
return d.includes(input);
})}
renderItem={({ item }) => <Item {...{ openTrainInfo, id: item }} />}
ListEmptyComponent={
@@ -185,6 +101,7 @@ export default function AllTrainDiagramView() {
</Text>
</View>
}
keyExtractor={(item) => item}
//initialNumToRender={100}
/>
@@ -288,7 +205,7 @@ export default function AllTrainDiagramView() {
}}
>
<TextInput
placeholder="列番・列車名を入力してフィルタリングします。"
placeholder="列番を入力してフィルタリングします。"
onFocus={() => setKeyBoardVisible(true)}
onEndEditing={() => {}}
onChange={(ret) => setInput(ret.nativeEvent.text)}
@@ -308,3 +225,25 @@ export default function AllTrainDiagramView() {
</View>
);
}
const Item = ({ id, openTrainInfo }) => {
return (
<TouchableOpacity
style={{
padding: 5,
flexDirection: "row",
borderColor: "white",
borderWidth: 1,
margin: 5,
borderRadius: 5,
alignItems: "center",
}}
onPress={() => openTrainInfo(id)}
>
<View style={{ flex: 1 }} />
<Text style={{ fontSize: 25, fontWeight: "bold", color: "white" }}>
{id}
</Text>
<View style={{ flex: 1 }} />
</TouchableOpacity>
);
};

View File

@@ -4,7 +4,6 @@ import {
Platform,
useWindowDimensions,
LayoutAnimation,
Text,
} from "react-native";
import Constants from "expo-constants";
import * as Updates from "expo-updates";
@@ -24,7 +23,6 @@ import { MapsButton } from "./Apps/MapsButton";
import { ReloadButton } from "./Apps/ReloadButton";
import { LandscapeBackButton } from "./Apps/LandscapeBackButton";
import { useStationList } from "../stateBox/useStationList";
import { FixedPositionBox } from "./Apps/FixedPositionBox";
/*
import StatusbarDetect from '../StatusbarDetect';
var Status = StatusbarDetect(); */
@@ -32,7 +30,7 @@ var Status = StatusbarDetect(); */
const top = Platform.OS == "ios" ? Constants.statusBarHeight : 0;
export default function Apps() {
const { webview, fixedPosition, setFixedPosition } = useCurrentTrain();
const { webview } = useCurrentTrain();
const { height, width } = useWindowDimensions();
const { navigate } = useNavigation();
const { isLandscape } = useDeviceOrientationChange();
@@ -127,10 +125,6 @@ export default function Apps() {
}}
/>
)}
{fixedPosition.type && (
<FixedPositionBox />
)}
{mapSwitch == "true" ? (
<ReloadButton
onPress={() => Updates.reloadAsync()}

View File

@@ -1,45 +0,0 @@
import { useCurrentTrain } from "@/stateBox/useCurrentTrain";
import { View, Platform } from "react-native";
import { useKeepAwake } from "expo-keep-awake";
import Constants from "expo-constants";
import { FixedTrain } from "./FixedPositionBox/FixedTrainBox";
import { FixedStation } from "./FixedPositionBox/FixedStationBox";
import { useState } from "react";
import { useTrainMenu } from "@/stateBox/useTrainMenu";
export const FixedPositionBox = () => {
const { mapSwitch } = useTrainMenu();
const { fixedPosition } = useCurrentTrain();
const [displaySize, setDisplaySize] = useState(mapSwitch == "true" ? 76 : 80);
useKeepAwake();
return (
<View
style={{
position: "absolute",
top: Platform.OS == "ios" ? Constants.statusBarHeight : 0,
borderRadius: 5,
zIndex: 1500,
width: "100%",
height: displaySize,
flexDirection: "row",
}}
pointerEvents="box-none"
>
{fixedPosition.type === "station" && (
<FixedStation
stationID={fixedPosition.value}
displaySize={displaySize}
setDisplaySize={setDisplaySize}
/>
)}
{fixedPosition.type === "train" && (
<FixedTrain
trainID={fixedPosition.value}
displaySize={displaySize}
setDisplaySize={setDisplaySize}
/>
)}
</View>
);
};

View File

@@ -1,381 +0,0 @@
import lineColorList from "@/assets/originData/lineColorList";
import { StationNumberMaker } from "@/components/駅名表/StationNumberMaker";
import { checkDuplicateTrainData } from "@/lib/checkDuplicateTrainData";
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 { getTime, trainTimeFiltering } from "@/lib/trainTimeFiltering";
import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
import { useAreaInfo } from "@/stateBox/useAreaInfo";
import { useCurrentTrain } from "@/stateBox/useCurrentTrain";
import { useStationList } from "@/stateBox/useStationList";
import { useTrainMenu } from "@/stateBox/useTrainMenu";
import { Ionicons } from "@expo/vector-icons";
import { useNavigation } from "@react-navigation/native";
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 { mapSwitch } = useTrainMenu();
const { currentTrain, setFixedPosition } = useCurrentTrain();
const { getStationDataFromId } = useStationList();
const { navigate } = useNavigation();
const [station, setStation] = useState<StationProps[]>([]);
useEffect(() => {
const data = getStationDataFromId(stationID);
setStation(data);
}, [stationID]);
const lineColor =
station.length > 0
? lineColorList[station[0]?.StationNumber.slice(0, 1)]
: "white";
////
const { allTrainDiagram } = useAllTrainDiagram();
const { areaStationID } = useAreaInfo();
const [stationDiagram, setStationDiagram] = useState({}); //当該駅の全時刻表
const [isInfoArea, setIsInfoArea] = useState(false);
useEffect(() => {
// 現在の駅に停車するダイヤを作成する副作用[列車ダイヤと現在駅情報]
if (!allTrainDiagram) {
setStationDiagram({});
return;
}
if (station.length == 0) {
setStationDiagram({});
return;
}
let returnData = {};
Object.keys(allTrainDiagram).forEach((key) => {
if (allTrainDiagram[key].match(station[0].Station_JP + ",")) {
returnData[key] = allTrainDiagram[key];
}
});
setStationDiagram(returnData);
setIsInfoArea(station.some((s) => areaStationID.includes(s.StationNumber)));
}, [allTrainDiagram, station]);
const [trainTimeAndNumber, setTrainTimeAndNumber] = useState<
eachTrainDiagramType[]
>([]);
useEffect(() => {
//現在の駅に停車する列車から時刻を切り出してLEDベースにフォーマット
if (objectIsEmpty(stationDiagram)) return () => {};
const getTimeData = getTime(stationDiagram, station[0]);
setTrainTimeAndNumber(getTimeData);
}, [stationDiagram]);
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((d) => trainTimeFiltering({ d, currentTrain, station })) //時間フィルター
.filter((d) => !d.isThrough)
.filter((d) => d.lastStation != station[0].Station_JP); //最終列車表示設定
setSelectedTrain(data);
}, [trainTimeAndNumber, currentTrain /*finalSwitch*/]);
return (
<View
style={{ display: "flex", flexDirection: "column", flex: 1 }}
pointerEvents="box-none"
>
<TouchableOpacity
style={{
flex: 1,
flexDirection: "row",
borderBottomColor: lineColor,
borderBottomWidth: 2,
position: "relative",
}}
activeOpacity={1}
onPress={() => {
const payload = {
currentStation: station,
navigate,
goTo: "menu",
onExit: () => SheetManager.hide("StationDetailView"),
};
//@ts-ignore
SheetManager.show("StationDetailView", { payload });
}}
>
<View
style={{
flex: 3,
flexDirection: "column",
alignContent: "center",
alignSelf: "center",
alignItems: "center",
height: "100%",
backgroundColor: "white",
}}
>
<View
style={{
backgroundColor: lineColor,
flexDirection: "row",
width: "100%",
alignContent: "center",
alignItems: "center",
height: 22,
overflow: "hidden",
paddingLeft: 5,
}}
>
<StationNumberMaker
currentStation={station}
singleSize={18}
useEach={true}
/>
<Text
style={{
fontSize: 14,
textAlignVertical: "center",
margin: 0,
padding: 0,
paddingLeft: 5,
flex: 1,
color: "white",
}}
>
{station[0]?.Station_JP}
</Text>
<View
style={{
backgroundColor: "white",
width: 6,
borderLeftColor: lineColor,
borderTopColor: lineColor,
borderBottomColor: "white",
borderRightColor: "white",
borderBottomWidth: 18,
borderLeftWidth: 10,
borderRightWidth: 0,
borderTopWidth: 5,
height: 20,
}}
/>
</View>
<View
style={{
height: "100%",
backgroundColor: "white",
flex: 1,
}}
>
<Text style={{ fontSize: 18 }}></Text>
</View>
</View>
<View
style={{
flex: 5,
flexDirection: "column",
backgroundColor: "white",
borderTopWidth: 5,
borderTopColor: lineColor,
overflow: "hidden",
}}
>
{selectedTrain.length > 0 ? (
selectedTrain.map((d) => (
<FixedStationBoxEachTrain
d={d}
station={station[0]}
displaySize={displaySize}
key={d.train + "-fixedStationBox"}
/>
))
) : (
<View style={{ backgroundColor: "white", flex: 1 }}>
<Text style={{ fontSize: parseInt("11%") }}>
</Text>
</View>
)}
</View>
</TouchableOpacity>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
borderTopColor: lineColor,
borderTopWidth: 2,
}}
pointerEvents="box-none"
>
<TouchableOpacity
style={{
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={{
flexDirection: "row",
alignItems: "center",
}}
onPress={() => {
LayoutAnimation.configureNext({
duration: 500,
update: { type: "spring", springDamping: 0.7 },
});
if (displaySize === 226) {
setDisplaySize(mapSwitch == "true" ? 76 : 80);
} else {
setDisplaySize(226);
}
}}
>
<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 == 226 ? "chevron-up" : "chevron-down"}
size={15}
color="white"
/>
<Text
style={{
color: "white",
paddingRight: 5,
backgroundColor: lineColor,
fontSize: 15,
}}
>
{displaySize == 226 ? "時刻表を縮小する" : "時刻表を展開する"}
</Text>
</View>
</TouchableOpacity>
</View>
</View>
);
};
const FixedStationBoxEachTrain = ({ d, station, displaySize }) => {
const { currentTrain } = useCurrentTrain();
const { stationList } = useStationList();
const { allCustomTrainData } = useAllTrainDiagram();
const currentTrainData = checkDuplicateTrainData(
currentTrain.filter((a) => a.num == d.train),
stationList
);
const trainDelayStatus = `${getTrainDelayStatus(
currentTrainData,
station.Station_JP
)}`;
const [train, setTrain] = useState<CustomTrainData>(
getCurrentTrainData(d.train, currentTrain, allCustomTrainData)
);
useEffect(() => {
setTrain(getCurrentTrainData(d.train, currentTrain, allCustomTrainData));
}, [currentTrain, d.train]);
const { name, color } = getTrainType({ type: train.type, whiteMode: true });
return (
<View
style={{
backgroundColor: "white",
flexDirection: "row",
height: displaySize == 226 ? "7.5%" : "33%",
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,847 +0,0 @@
import lineColorList from "@/assets/originData/lineColorList";
import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
import { useCurrentTrain } from "@/stateBox/useCurrentTrain";
import { useStationList } from "@/stateBox/useStationList";
import { StationProps } from "@/lib/CommonTypes";
import { FC, useEffect, useState } from "react";
import {
Text,
TouchableOpacity,
View,
Image,
LayoutAnimation,
ScrollView,
} from "react-native";
import { getTrainType } from "@/lib/getTrainType";
import { trainDataType, trainPosition } from "@/lib/trainPositionTextArray";
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";
import { useTrainMenu } from "@/stateBox/useTrainMenu";
type props = {
trainID: string;
displaySize: number;
setDisplaySize: (e: number) => void;
};
export const FixedTrain: FC<props> = ({
trainID,
displaySize,
setDisplaySize,
}) => {
const {
fixedPosition,
setFixedPosition,
currentTrain,
getCurrentStationData,
getPosition,
} = useCurrentTrain();
const { mapSwitch } = useTrainMenu();
const { allCustomTrainData, allTrainDiagram } = useAllTrainDiagram();
const [train, setTrain] = useState<trainDataType>(null);
const [customData, setCustomData] = useState<CustomTrainData>(
getCurrentTrainData(trainID, currentTrain, allCustomTrainData)
);
useEffect(() => {
setCustomData(
getCurrentTrainData(trainID, currentTrain, allCustomTrainData)
);
}, [currentTrain, trainID]);
useEffect(() => {
const stationData = getCurrentStationData(trainID);
if (stationData) {
setTrain(stationData);
} else {
alert("追跡していた列車が消えました。追跡を終了します。");
setFixedPosition({ type: null, value: null });
}
}, [trainID, currentTrain]);
const { getStationDataFromName, stationList, originalStationList } =
useStationList();
const [trainDataWidhThrough, setTrainDataWithThrough] = useState<string[]>(
[]
);
useEffect(() => {
const trainData = allTrainDiagram[trainID]?.split("#");
if (!trainData) return;
//let haveThrough = false;
//
const stopStationList = trainData.map((i) => {
const [station, se, time] = i.split(",");
//if (se == "通編") setHaveThrough(true);
return stationList.map((a) => a.filter((d) => d.StationName == station));
});
const allThroughStationList = stopStationList.map((i, index, array) => {
let allThroughStation = [];
if (index == array.length - 1) return;
const firstItem = array[index];
const secondItem = array[index + 1];
let betweenStationLine = "";
let baseStationNumberFirst = "";
let baseStationNumberSecond = "";
Object.keys(stationIDPair).forEach((d, index2) => {
if (!d) return;
const haveFirst = firstItem[index2];
const haveSecond = secondItem[index2];
if (haveFirst.length && haveSecond.length) {
betweenStationLine = d;
baseStationNumberFirst = haveFirst[0].StationNumber;
baseStationNumberSecond = haveSecond[0].StationNumber;
}
});
if (!betweenStationLine) return;
let reverse = false;
originalStationList[
lineListPair[stationIDPair[betweenStationLine]]
].forEach((d) => {
if (
d.StationNumber > baseStationNumberFirst &&
d.StationNumber < baseStationNumberSecond
) {
allThroughStation.push(`${d.Station_JP},通過,`);
//setHaveThrough(true);
reverse = false;
} else {
if (
d.StationNumber < baseStationNumberFirst &&
d.StationNumber > baseStationNumberSecond
) {
allThroughStation.push(`${d.Station_JP},通過,`);
//setHaveThrough(true);
reverse = true;
}
}
});
if (reverse) allThroughStation.reverse();
return allThroughStation;
});
let mainArray = [...trainData];
let indexs = 0;
trainData.forEach((d, index) => {
indexs = indexs + 1;
if (!allThroughStationList[index]) return;
if (allThroughStationList[index].length == 0) return;
mainArray.splice(indexs, 0, ...allThroughStationList[index]);
indexs = indexs + allThroughStationList[index].length;
});
setTrainDataWithThrough(mainArray);
}, [allTrainDiagram, stationList, trainID]);
const [stopStationIDList, setStopStationList] = useState([]);
useEffect(() => {
const x = trainDataWidhThrough.map((i) => {
const [station, se, time] = i.split(",");
const Stations = stationList.map((a) =>
a.filter((d) => d.StationName == station)
);
const StationNumbers =
Stations &&
Stations.reduce((newArray, e) => {
return newArray.concat(e);
}, []).map((d) => d.StationNumber);
return StationNumbers;
});
setStopStationList(x);
}, [trainDataWidhThrough]);
const [currentPosition, setCurrentPosition] = useState<string[]>([]);
useEffect(() => {
let position = getPosition(train);
if (stopStationIDList.length == 0) return;
if (position) {
if (position.length > 1) {
if (position[0] == "-Iyo") {
position[0] =
stopStationIDList[
stopStationIDList.findIndex((d) => d.includes("U14")) - 1
][0];
} else if (position[0] == "+Iyo") {
position[0] =
stopStationIDList[
stopStationIDList.findIndex((d) => d.includes("U14")) + 1
][0];
}
if (position[1] == "+Iyo") {
position[1] =
stopStationIDList[
stopStationIDList.findIndex((d) => d.includes("U14")) + 1
][0];
} else if (position[1] == "-Iyo") {
position[1] =
stopStationIDList[
stopStationIDList.findIndex((d) => d.includes("U14")) - 1
][0];
}
}
setCurrentPosition(position);
}
}, [train,stopStationIDList]);
const [nextStationData, setNextStationData] = useState<StationProps[]>([]);
const [untilStationData, setUntilStationData] = useState<StationProps[]>([]);
const [probably, setProbably] = useState(false);
useEffect(() => {
//棒線駅判定を入れて、棒線駅なら時間を見て分数がマイナスならcontinue;
const points = findReversalPoints(currentPosition, stopStationIDList);
if (!points) return;
if (points.length == 0) return;
let searchCountFirst = points.findIndex((d) => d == true);
let searchCountLast = points.findLastIndex((d) => d == true);
const delayTime = train?.delay == "入線" ? 0 : train?.delay;
let additionalSkipCount = 0;
for (
let searchCount = searchCountFirst;
searchCount < points.length;
searchCount++
) {
const nextPos = trainDataWidhThrough[searchCount];
if (nextPos) {
const [station, se, time] = nextPos.split(",");
if (searchCountFirst == searchCountLast) {
if (se.includes("通")) {
continue;
}
setNextStationData(getStationDataFromName(station));
break;
}
//棒線駅判定
let distanceMinute = 0;
if (time != "") {
const now = dayjs();
const hour = parseInt(time.split(":")[0]);
const distanceTime = now
.hour(hour < 4 ? hour + 24 : hour)
.minute(parseInt(time.split(":")[1]));
distanceMinute = distanceTime.diff(now, "minute") + delayTime;
if (now.hour() < 4) {
if (hour < 4) {
distanceMinute = distanceMinute - 1440;
}
}
}
if (distanceMinute >= 0) {
if (se.includes("通")) {
continue;
} else {
setNextStationData(getStationDataFromName(station));
break;
}
} else {
additionalSkipCount++;
continue;
}
}
}
let trainList = [];
for (
let searchCount = searchCountFirst - 1;
searchCount < points.length;
searchCount++
) {
trainList.push(trainDataWidhThrough[searchCount]);
}
if (additionalSkipCount > 0) {
trainList = trainList.slice(additionalSkipCount);
setProbably(true);
} else {
setProbably(false);
}
setUntilStationData(trainList);
}, [currentPosition, trainDataWidhThrough]);
const [ToData, setToData] = useState("");
useEffect(() => {
if (customData.ToData && customData.ToData != "") {
setToData(customData.ToData);
} else {
if (trainDataWidhThrough.length == 0) return;
setToData(
trainDataWidhThrough[trainDataWidhThrough.length - 2].split(",")[0]
);
}
}, [customData, trainDataWidhThrough]);
const [station, setStation] = useState<StationProps[]>([]);
useEffect(() => {
const data = getStationDataFromName(ToData);
setStation(data);
}, [ToData]);
const lineColor =
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 (
<View
style={{ display: "flex", flexDirection: "column", flex: 1 }}
pointerEvents="box-none"
>
<View
style={{
flex: 1,
flexDirection: displaySize === 226 ? "column" : "row",
backgroundColor: "black",
//borderBottomColor: "black",
//borderBottomWidth: 2,
}}
>
<View
style={{
flexDirection: displaySize === 226 ? "row" : "column",
flex: 1,
backgroundColor: "white",
height: displaySize === 226 ? 200 : 50,
overflow: "hidden",
}}
>
<View
style={{ flex: displaySize === 226 ? 5 : 1, flexDirection: "row" }}
>
<View
style={{
backgroundColor: customTrainType.color,
flexDirection: "row",
alignContent: "center",
alignSelf: "center",
alignItems: "center",
height: "100%",
}}
>
<Image
source={{ uri: customData.img }}
width={displaySize === 226 ? 23 : 14}
height={displaySize === 226 ? 26 : 17}
style={{ margin: 5 }}
/>
<View
style={{
flexDirection: displaySize === 226 ? "column" : "row",
alignContent: "center",
alignSelf: "center",
alignItems: "center",
maxWidth: displaySize === 226 ? 80 : 100,
}}
>
<Text
style={{
fontSize: trainNameText.length > 4 ? 12 : 14,
fontFamily: customTrainType.fontAvailable
? "JR-Nishi"
: undefined,
fontWeight: !customTrainType.fontAvailable
? "bold"
: undefined,
marginTop: customTrainType.fontAvailable ? 3 : 0,
color: "white",
textAlignVertical: "center",
textAlign: "left",
}}
>
{customTrainType.shortName}
</Text>
{customData.trainName && (
<Text
style={{
fontSize: trainNameText.length > 4 ? 8 : 14,
color: "white",
maxWidth: displaySize === 226 ? 200 : 60,
textAlignVertical: "center",
}}
>
{trainNameText}
</Text>
)}
</View>
<View
style={{
backgroundColor: customTrainType.color,
width: 10,
borderLeftColor: customTrainType.color,
borderTopColor: lineColor,
borderBottomColor: lineColor,
borderTopWidth: displaySize === 226 ? 50 : 14,
borderBottomWidth: displaySize === 226 ? 50 : 14,
borderLeftWidth: displaySize === 226 ? 30 : 10,
borderRightWidth: 0,
//height: displaySize === 226 ? 20 : 100,
height: "100%",
}}
></View>
</View>
<View
style={{
flexDirection: "row",
alignContent: "center",
alignSelf: "center",
height: "100%",
backgroundColor: lineColor,
flex: 1,
}}
>
<View
style={{
flexDirection: "row",
alignContent: "center",
alignSelf: "center",
alignItems: "center",
}}
>
<StationNumberMaker
currentStation={station}
singleSize={18}
useEach={true}
/>
<Text
style={{
fontSize: customData?.ToData?.length > 4 ? 9 : 12,
color: "white",
fontWeight: "bold",
textAlignVertical: "center",
margin: 0,
padding: 0,
height: "100%",
}}
>
{ToData}
</Text>
</View>
</View>
</View>
{displaySize === 226 && (
<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: displaySize === 226 ? 4 : 1,
flexDirection: "row",
alignItems: "center",
}}
>
<View style={{ flexDirection: "column" }}>
<Text
style={{
fontSize: 10,
fontWeight: "bold",
color: "white",
marginHorizontal: 5,
paddingVertical: 0,
marginVertical: -1,
}}
>
{nextStationData[0]?.Station_JP == train?.Pos
? "ただいま"
: "次は"}
</Text>
{probably && (
<Text
style={{
fontSize: 5,
color: "white",
fontWeight: "bold",
marginHorizontal: 5,
paddingVertical: 0,
marginVertical: -1,
}}
>
()
</Text>
)}
</View>
<StationNumberMaker
currentStation={nextStationData}
singleSize={20}
useEach={true}
/>
<Text
style={{
fontSize: 18,
fontWeight: "bold",
color: "white",
flex: 1,
}}
>
{nextStationData[0]?.Station_JP || "不明"}
</Text>
{displaySize !== 226 && (
<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 !== 226}
/>
</View>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
borderTopColor: "black",
borderTopWidth: 2,
}}
pointerEvents="box-none"
>
<TouchableOpacity
style={{
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={{
flexDirection: "row",
alignItems: "center",
}}
onPress={() => {
LayoutAnimation.configureNext({
duration: 200,
update: { type: "easeInEaseOut", springDamping: 0.4 },
});
if (displaySize === 226) {
setDisplaySize(mapSwitch == "true" ? 76 : 80);
} else {
setDisplaySize(226);
}
}}
>
<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,
}}
>
<Ionicons
name={displaySize == 226 ? "chevron-up" : "chevron-down"}
size={15}
color="white"
/>
<Text
style={{
color: "white",
paddingRight: 5,
backgroundColor: "black",
fontSize: 15,
}}
>
{displaySize == 226 ? "列車情報縮小" : "列車情報展開"}
</Text>
</View>
</TouchableOpacity>
</View>
</View>
);
};
const CurrentPositionBox = ({
train,
lineColor,
trainDataWithThrough,
isSmall,
}) => {
let firstText = "";
let secondText = "";
let marginText = "";
const { isBetween, Pos: PosData } = trainPosition(train);
if (isBetween === true) {
const { from, to } = PosData;
firstText = from;
secondText = to;
marginText = "→";
} else {
const { Pos } = PosData;
if (Pos !== "") {
firstText = Pos;
}
}
const delayTime = train?.delay == "入線" ? 0 : parseInt(train?.delay);
return (
<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) => (
<EachStopData
d={d}
index={index}
key={d}
delayTime={delayTime}
isSmall={isSmall}
secondText={secondText}
/>
))}
</ScrollView>
</View>
);
};
type eachStopType = {
d: string;
delayTime: number;
isSmall: boolean;
index: number;
secondText: string;
};
const EachStopData: FC<eachStopType> = (props) => {
const { d, delayTime, isSmall, index, secondText } = props;
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(parseInt(time.split(":")[1]));
distanceMinute = distanceTime.diff(now, "minute") + delayTime;
if (now.hour() < 4) {
if (hour < 4) {
distanceMinute = distanceMinute - 1440;
}
}
}
return (
<>
<View
style={{
flexDirection: "column",
backgroundColor: se.includes("通") ? "#6e6e6e77" : "#6e6e6eff",
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, array) => {
return (
<Text
key={i + index}
style={{
fontSize:
array.length < 5 ? (isSmall ? 5 : 12) : isSmall ? 3 : 10,
color: "white",
margin: 0,
padding: 0,
fontWeight: "bold",
}}
>
{i}
</Text>
);
})}
<View style={{ flex: 1 }} />
{isSmall ||
(time != "" && (
<Text
style={{
fontSize: isSmall ? 8 : 12,
color: "black",
backgroundColor: "white",
fontWeight: "bold",
}}
>
{distanceMinute}
</Text>
))}
<Text
style={{
fontSize: isSmall ? 8 : 14,
color:
index == 1 && secondText == ""
? "#ffe852ff"
: se.includes("通")
? "#020202ff"
: "white",
marginTop: isSmall ? 0 : 3,
height: isSmall ? "auto" : 17,
fontWeight: "bold",
}}
>
{index == 1 && secondText == ""
? "→"
: se.includes("通")
? null
: "●"}
</Text>
</View>
{index == 0 && secondText != "" && (
<View
style={{
flexDirection: "column",
backgroundColor: "#0000",
borderRadius: 10,
marginHorizontal: isSmall ? 2 : 4,
padding: isSmall ? 2 : 4,
justifyContent: "center",
alignItems: "center",
overflow: "hidden",
}}
>
<View style={{ flex: 1 }} />
<Ionicons
name="arrow-forward"
size={isSmall ? 8 : 14}
color="black"
style={{ marginTop: isSmall ? 0 : 3 }}
/>
</View>
)}
</>
);
};

View File

@@ -37,7 +37,6 @@ export const MapsButton: FC<MapsButtonProps> = ({ onPress }) => {
alignSelf: "center",
alignItems: "center",
display: mapSwitch == "true" ? "flex" : "none",
zIndex: 1000,
},
text: {
textAlign: "center",

View File

@@ -38,7 +38,6 @@ export const ReloadButton:FC<ReloadButton> = ({ onPress, right }) => {
alignSelf: "center",
alignItems: "center",
display: mapSwitch,
zIndex: 1000,
},
text: {
textAlign: "center",

View File

@@ -23,8 +23,7 @@ export const AppsWebView = ({ openStationACFromEachTrainInfo }) => {
const { navigate } = useNavigation();
const { favoriteStation } = useFavoriteStation();
const { isLandscape } = useDeviceOrientationChange();
const { originalStationList, stationList, getInjectJavascriptAddress } =
useStationList();
const { originalStationList, stationList, getInjectJavascriptAddress } = useStationList();
const {
setSelectedLine,
mapsStationData: stationData,
@@ -52,6 +51,7 @@ export const AppsWebView = ({ openStationACFromEachTrainInfo }) => {
break;
}
};
const onMessage = (event) => {
const { data } = event.nativeEvent;
/**
@@ -137,9 +137,7 @@ export const AppsWebView = ({ openStationACFromEachTrainInfo }) => {
if (!stationData) return () => {};
if (!originalStationList) return () => {};
if (favoriteStation.length < 1) return () => {};
const string = getInjectJavascriptAddress(
favoriteStation[0][0].StationNumber
);
const string = getInjectJavascriptAddress(favoriteStation[0][0].StationNumber);
if (!string) return () => {};
webview?.current.injectJavaScript(string);
once = true;

View File

@@ -159,7 +159,7 @@ export const DynamicHeaderScrollView = (props) => {
ref={scrollHandlers.ref}
onLayout={scrollHandlers.onLayout}
scrollEventThrottle={scrollHandlers.scrollEventThrottle}
style={{ zIndex: 0 }}
style={{ backgroundColor: "white", zIndex: 0 }}
stickyHeaderIndices={[1]}
onScroll={onScroll}
>

View File

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

View File

@@ -52,6 +52,22 @@ export const FixedContentBottom = (props) => {
旅行ツアー
</TicketBox>
</View>
<TextBox
backgroundColor="red"
flex={1}
onPressButton={() =>
Linking.openURL(
"https://xprocess.haruk.in/JR-shikoku-Apps-Common/2025-update-status"
)
}
>
<Text style={{ color: "white", fontWeight: "bold", fontSize: 20 }}>
ダイヤ改正に伴うデータ更新状況
</Text>
<Text style={{ color: "white", fontSize: 18 }}>
ダイヤ改正に伴うデータの更新状況を随時更新します
</Text>
</TextBox>
<TextBox
backgroundColor="#ed86b5"
flex={1}
@@ -197,19 +213,6 @@ export const FixedContentBottom = (props) => {
</Text>
</TextBox>
<Text style={{ fontWeight: "bold", fontSize: 20 }}>その他</Text>
<TextBox
backgroundColor="rgb(88, 101, 242)"
flex={1}
onPressButton={() => Linking.openURL("https://twitter.com/Xprocess_main/status/1955242437817012300")}
>
<Text style={{ color: "white", fontWeight: "bold", fontSize: 20 }}>
公式Discordのご案内
</Text>
<Text style={{ color: "white", fontSize: 18 }}>
皆さんの目撃情報をアプリに反映しませんかDiscordに登録して運用を報告しましょう
</Text>
</TextBox>
<TextBox
backgroundColor="linear-gradient(120deg, rgba(247,135,54,0.208) 0%, rgba(54,125,247,0.208) 100%)"
flex={1}

View File

@@ -1,4 +1,4 @@
import { FC, useLayoutEffect, useState } from "react";
import { FC, useEffect, useLayoutEffect, useState } from "react";
import { View, Text, TouchableOpacity } from "react-native";
import { getPDFViewURL } from "@/lib/getPdfViewURL";
import { ScrollView, SheetManager } from "react-native-actions-sheet";
@@ -6,27 +6,20 @@ import { ScrollView, SheetManager } from "react-native-actions-sheet";
type props = {
navigate: (screen: string, params?: object) => void;
};
type specialDataType = { address: string; text: string; description: string };
export const SpecialTrainInfoBox: FC<props> = ({ navigate }) => {
const [specialData, setSpecialData] = useState<specialDataType[]>([]);
const [specialData, setSpecialData] = useState([]);
useLayoutEffect(() => {
fetch("https://n8n.haruk.in/webhook/sptrainfo")
.then((res) => res.json())
.then((data) => setSpecialData(data.data))
.catch((err) => console.log(err));
}, []);
const onPressItem: (d: specialDataType) => void = (d) => {
navigate("howto", {
info: getPDFViewURL("https://www.jr-shikoku.co.jp" + d.address),
goTo: "menu",
});
SheetManager.hide("SpecialTrainInfo");
};
return (
<View style={{ backgroundColor: "#0099CC" }}>
<View
style={{
backgroundColor: "#0099CC",
}}
>
<View style={{ flexDirection: "row", alignItems: "center" }}>
<Text
style={{
@@ -40,10 +33,20 @@ export const SpecialTrainInfoBox: FC<props> = ({ navigate }) => {
</Text>
</View>
<ScrollView style={{ backgroundColor: "white" }}>
<ScrollView
style={{
backgroundColor: "white",
}}
>
{specialData.map((d) => (
<TouchableOpacity
onPress={() => onPressItem(d)}
onPress={() => {
navigate("howto", {
info: getPDFViewURL("https://www.jr-shikoku.co.jp" + d.address),
goTo: "menu",
});
SheetManager.hide("SpecialTrainInfo");
}}
onLongPress={() => alert(d.description)}
key={d.address}
style={{

View File

@@ -1,9 +1,22 @@
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 "@/lib/CommonTypes";
import lineColorList from "../../assets/originData/lineColorList";
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;
};
type StationNumberProps = {
currentStation: StationProps[];
active: boolean;

View File

@@ -17,7 +17,7 @@ import { SwitchArea } from "../atom/SwitchArea";
import { useNotification } from "../../stateBox/useNotifications";
import { SheetHeaderItem } from "@/components/atom/SheetHeaderItem";
const versionCode = "6.1.8"; // Update this version code as needed
const versionCode = "6.1.1"; // Update this version code as needed
export const SettingTopPage = ({
testNFC,

View File

@@ -1,355 +0,0 @@
import { FC, useRef, useState, useCallback, useEffect } from "react";
import {
View,
Text,
ScrollView,
useWindowDimensions,
Vibration,
} from "react-native";
import { ExGridViewItem } from "./ExGridViewItem";
import Animated, {
useAnimatedStyle,
useSharedValue,
runOnJS,
useAnimatedScrollHandler,
withTiming,
Easing,
FadeIn,
FadeOut,
BounceInUp,
FadeInUp,
FadeOutUp,
} from "react-native-reanimated";
import { Gesture, GestureDetector } from "react-native-gesture-handler";
import { ExGridViewTimePositionItem } from "./ExGridViewTimePositionItem";
import { useCurrentTrain } from "@/stateBox/useCurrentTrain";
import dayjs from "dayjs";
type hoge = {
trainNumber: string;
array: string;
name: string;
timeType: string;
time: string;
}[];
export const ExGridView: FC<{
data: hoge;
}> = ({ data }) => {
const groupedData: {
[d: number]: {
trainNumber: string;
array: string;
name: string;
timeType: string;
time: string;
isOperating: boolean;
}[];
} = {
"4": [],
"5": [],
"6": [],
"7": [],
"8": [],
"9": [],
"10": [],
"11": [],
"12": [],
"13": [],
"14": [],
"15": [],
"16": [],
"17": [],
"18": [],
"19": [],
"20": [],
"21": [],
"22": [],
"23": [],
"0": [],
"1": [],
"2": [],
"3": [],
};
const groupKeys = [
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"20",
"21",
"22",
"23",
"0",
"1",
"2",
"3",
];
const { width } = useWindowDimensions();
const { currentTrain } = useCurrentTrain();
data.forEach((item) => {
let isOperating = false;
let [hour, minute] = dayjs()
.hour(parseInt(item.time.split(":")[0]))
.minute(parseInt(item.time.split(":")[1]))
.format("H:m")
.split(":");
if (currentTrain.findIndex((x) => x.num == item.trainNumber) != -1) {
const currentTrainTime = currentTrain.find(
(x) => x.num == item.trainNumber
)?.delay;
if (currentTrainTime != "入線") {
[hour, minute] = dayjs()
.hour(parseInt(hour))
.minute(parseInt(minute))
.add(parseInt(currentTrainTime), "minute")
.format("H:m")
.split(":");
}
isOperating = true;
}
groupedData[hour].push({ ...item, time: `${hour}:${minute}`, isOperating });
});
// ドラッグ位置を保持する共有値
const widthX = useSharedValue(width);
const savedWidthX = useSharedValue(width);
const isChanging = useSharedValue(false);
const [scrollEnabled, setScrollEnabled] = useState(true);
const scrollRef = useRef<Animated.ScrollView>(null);
const scrollRef2 = useRef<Animated.ScrollView>(null);
// ScrollViewの有効/無効を切り替える関数
const toggleScrollEnabled = useCallback((enabled: boolean) => {
setScrollEnabled(enabled);
}, []);
// パンジェスチャー(ドラッグ)のハンドラー
const pinchGesture = Gesture.Pinch()
.onUpdate((e) => {
const calc = savedWidthX.value * e.scale;
widthX.value = calc > width ? calc : width;
//runOnJS(scrollToRightEnd)();
})
.onEnd(() => {
savedWidthX.value = widthX.value;
});
const gesture = Gesture.Pan()
.minPointers(2) // 最低2本指
.maxPointers(2) // 最大2本指
.onStart(() => {
runOnJS(toggleScrollEnabled)(false);
})
.onEnd(() => {
runOnJS(toggleScrollEnabled)(true);
savedWidthX.value = widthX.value;
});
const longPressGesture = Gesture.Pan()
.minPointers(1)
.maxPointers(1)
.activateAfterLongPress(200)
.onStart(() => {
runOnJS(Vibration.vibrate)(30);
isChanging.value = true;
})
.onUpdate((e) => {
const calc = widthX.value + e.velocityY;
widthX.value = calc > width ? calc : width;
})
.onEnd(() => {
console.log("Long press ended");
isChanging.value = false;
});
// ジェスチャーを組み合わせる
const composed = Gesture.Simultaneous(
longPressGesture,
pinchGesture,
gesture
);
// アニメーションスタイル
const animatedStyle = useAnimatedStyle(() => ({
width: widthX.value,
backgroundColor: isChanging.value ? "#8adeffff" : "white",
}));
// 時ヘッダーを横にスクロールしたときの処理
const scrollX = useSharedValue(0);
const scrollHandler = useAnimatedScrollHandler({
onScroll: (event) => {
scrollX.value = event.contentOffset.x;
},
});
const stickyTextStyle = useAnimatedStyle(() => ({
transform: [{ translateX: scrollX.value }],
}));
const animatedLongPressStyle = useAnimatedStyle(() => ({
display: isChanging.value ? "flex" : "none",
}));
useEffect(() => {
const getCurrentTime = dayjs().hour();
setTimeout(() => {
const keyTime =
getCurrentTime - 4 <= 0 ? getCurrentTime + 24 : getCurrentTime;
const goTo = keyTime * 60;
if (goTo > 400) {
scrollRef2.current?.scrollTo({ y: goTo - 300, animated: true });
}
}, 400);
}, [scrollRef2]);
return (
<>
<Animated.View
style={[
{
position: "absolute",
width,
backgroundColor: "#26d1baff",
zIndex: 500,
top: 0,
},
animatedLongPressStyle,
]}
entering={FadeInUp}
exiting={FadeOutUp}
>
<Text style={{ fontSize: 30, textAlign: "center", flex: 1 }}>
  
</Text>
</Animated.View>
<GestureDetector gesture={composed}>
<Animated.ScrollView
horizontal
nestedScrollEnabled
pinchGestureEnabled={false}
scrollEnabled={scrollEnabled}
onScroll={scrollHandler}
onContentSizeChange={(contentWidth) => {
// 現在のスクロール位置を取得
const currentScrollX = scrollX.value;
const containerWidth = width - 50;
// コンテンツが画面からはみ出している場合のみ右端にスクロール
if (currentScrollX + containerWidth > contentWidth) {
const newScrollX = Math.max(0, contentWidth - containerWidth);
scrollRef.current?.scrollTo({ x: newScrollX, animated: true });
}
}}
ref={scrollRef}
contentContainerStyle={{
flexDirection: "column",
backgroundColor: "white",
}}
>
<Animated.View
style={[
{
width: width,
flexDirection: "row",
},
animatedStyle,
]}
>
{Array.from({ length: 60 }, (_, i) => i + 1).map((num) => {
if (num % 5 === 0) {
return (
<Text
key={num + "ExGridViewTimeLabel"}
style={{
flex: 1,
textAlign: "left",
borderRightWidth: 0.5,
borderColor: "#ccc",
flexWrap: "nowrap",
fontSize: 12,
}}
>
{num - 5}
</Text>
);
} else return <></>;
})}
<Text
style={{
textAlign: "right",
borderRightWidth: 0.5,
borderColor: "#ccc",
flexWrap: "nowrap",
fontSize: 12,
width: 50,
}}
>
()
</Text>
</Animated.View>
<Animated.ScrollView
style={[{ width: width }, animatedStyle]}
pinchGestureEnabled={false}
minimumZoomScale={0.5}
maximumZoomScale={3.0}
scrollEnabled={scrollEnabled}
stickyHeaderIndices={
groupKeys.at(0) ? groupKeys.map((_, i) => i * 2) : []
}
ref={scrollRef2}
>
{groupKeys.map((hour) => [
<View
style={{
padding: 5,
borderBottomWidth: 0.5,
borderTopWidth: 0.5,
borderBottomColor: "#ccc",
backgroundColor: "#f0f0f0",
}}
key={hour}
>
<Animated.Text
style={[
{
fontSize: 15,
zIndex: 1,
marginLeft: 0,
},
stickyTextStyle,
]}
>
{hour}
</Animated.Text>
</View>,
<View
style={{
flexDirection: "row",
position: "relative",
height: 50,
}}
>
{groupedData[hour].map((d, i, array) => (
<ExGridViewItem
key={d.trainNumber + i}
d={d}
index={i}
width={widthX}
array={array}
/>
))}
<ExGridViewTimePositionItem width={widthX} hour={hour} />
</View>,
])}
</Animated.ScrollView>
</Animated.ScrollView>
</GestureDetector>
</>
);
};

View File

@@ -1,254 +0,0 @@
import { migrateTrainName } from "@/lib/eachTrainInfoCoreLib/migrateTrainName";
import { getStringConfig } from "@/lib/getStringConfig";
import { getTrainType } from "@/lib/getTrainType";
import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
import { FC, useEffect, useLayoutEffect, useMemo, useState } from "react";
import {
View,
Text,
TouchableOpacity,
useWindowDimensions,
} from "react-native";
import { customTrainDataDetector } from "../custom-train-data";
import dayjs from "dayjs";
import { SheetManager } from "react-native-actions-sheet";
import { useNavigation } from "@react-navigation/native";
import { lineList } from "@/lib/getStationList";
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: {
trainNumber: string;
array: string;
name: string;
timeType: string;
time: string;
isOperating: boolean;
};
index: number;
width: SharedValue<number>;
array: {
train: string;
lastStation: string;
time: string;
isThrough?: boolean;
}[];
}> = ({ d, index, width, array }) => {
const { allCustomTrainData } = useAllTrainDiagram();
const { originalStationList, stationList } = useStationList();
const { navigate, goBack } = useNavigation();
const [trainData, setTrainData] = useState<CustomTrainData>();
useEffect(() => {
if (allCustomTrainData) {
allCustomTrainData.forEach((x) => {
if (x.TrainNumber === d.trainNumber) {
setTrainData(x);
}
});
}
}, []);
const { color, name, data } = getTrainType({ type: trainData?.type, whiteMode: true });
// 列車名、種別、フォントの取得
const [
typeString,
trainName,
fontAvailable,
isOneMan,
infogram,
isEdit,
uwasa,
vehicleFormation,
trainInfoUrl,
] = useMemo(() => {
const {
type,
trainName,
trainNumDistance,
infogram,
isEdit,
uwasa,
vehicleFormation,
trainInfoUrl,
} = customTrainDataDetector(d.trainNumber, allCustomTrainData);
const [typeString, fontAvailable, isOneMan] = getStringConfig(
type,
d.trainNumber
);
const trainData = d.array.split("#").filter((d) => d !== "");
switch (true) {
case trainData[trainData.length - 1] === undefined:
return [
typeString,
"",
fontAvailable,
isOneMan,
infogram,
isEdit,
uwasa,
vehicleFormation,
trainInfoUrl,
];
default:
// 行先がある場合は、行先を取得
const trainName = (d.timeType == "着" || d.timeType == "着編") ? trainData[0].split(",")[0] : trainData[trainData.length - 1].split(",")[0]
return [
typeString,
migrateTrainName(trainName),
fontAvailable,
isOneMan,
infogram,
isEdit,
uwasa,
vehicleFormation,
trainInfoUrl,
];
}
}, [d.array]);
const timeArray = d.time.split(":").map((s) => parseInt(s));
const formattedTime = dayjs()
.set("hour", timeArray[0])
.set("minute", timeArray[1])
.format("m");
let isSameTimeBefore = false;
if (index > 0) {
const beforeItem = array[index - 1];
const beforeTimeArray = beforeItem.time.split(":").map((s) => parseInt(s));
const beforeFormattedTime = dayjs()
.set("hour", beforeTimeArray[0])
.set("minute", beforeTimeArray[1])
.format("m");
isSameTimeBefore = beforeFormattedTime === formattedTime;
}
const openStationACFromEachTrainInfo = async (stationName) => {
await SheetManager.hide("EachTrainInfo");
const findStationEachLine = (selectLine) => {
let NearStation = selectLine.filter((d) => d.Station_JP == stationName);
return NearStation;
};
let returnDataBase = lineList
.map((d) => findStationEachLine(originalStationList[d]))
.filter((d) => d.length > 0)
.reduce((pre, current) => {
pre.push(...current);
return pre;
}, []);
if (returnDataBase.length) {
const payload = {
currentStation: returnDataBase,
navigate,
//@ts-ignore
useShow: () => SheetManager.show("StationDetailView", { payload }),
onExit: () => SheetManager.hide("StationDetailView"),
}; //@ts-ignore
setTimeout(() => SheetManager.show("StationDetailView", { payload }), 50);
} else {
SheetManager.hide("StationDetailView");
}
};
const openTrainInfo = () => {
let TrainNumber = "";
if (trainData.trainNumDistance != undefined) {
const timeInfo =
parseInt(trainData.TrainNumber.replace("M", "").replace("D", "")) -
trainData.trainNumDistance;
TrainNumber = timeInfo + "号";
}
const payload = {
data: {
trainNum: trainData.TrainNumber,
limited: `${data}:${trainData.trainName}${TrainNumber}`,
},
navigate,
openStationACFromEachTrainInfo,
from: d.isOperating ? null :"AllTrainIDList",
};
SheetManager.show("EachTrainInfo", {
//@ts-ignore
payload,
onClose: (data) => {
//alert(data);
},
});
};
const [stationColor, setStationColor] = useState(["gray"]);
useEffect(() => {
const Stations = stationList
.map((a) => a.filter((d) => d.StationName == trainName))
.reduce((newArray, e) => newArray.concat(e), []);
const StationNumbers =
Stations &&
Stations.filter((d) => d.StationNumber).map((d) => d.StationNumber);
if (StationNumbers) {
const stationLineColor = StationNumbers.map(
(d) => lineColorList[d.charAt(0)]
);
setStationColor(stationLineColor || ["gray"]);
}
}, [stationList]);
// if(typeString == "回送"){
// return<></>;
// }
const animatedStyle = useAnimatedStyle(() => {
const leftPosition =
((((width.value - 50) / 100) * parseInt(formattedTime)) / 60) * 100;
return {
left: leftPosition,
};
}, [formattedTime]);
return (
<View style={{ left: 0, height: 50 }}>
<Animated.View
style={[
{
flexDirection: "column",
//borderTopWidth: 1,
//borderBottomWidth: 0.5,
borderStyle: "solid",
borderColor: "darkgray",
opacity: d.timeType.includes("通") ? 0.5 : 1,
position: "absolute",
height: "100%",
width: 28,
top: isSameTimeBefore ? 10 : 0,
},
animatedStyle,
]}
>
<TouchableOpacity style={{ flex: 1 }} onPress={() => openTrainInfo()}>
<View style={{ position: "relative" }}>
<Text style={{ fontSize: 20, color: color, opacity: isSameTimeBefore ? 0 : 1, fontWeight:d.isOperating ? "bold" : "thin", fontStyle:d.isOperating? "italic" :"normal" }}>{formattedTime}</Text>
<Text
style={{
fontSize: 10,
position: "absolute",
bottom: 0,
right: 0,
fontWeight: "bold",
}}
>
{d.timeType}
</Text>
</View>
<View style={{ flex: 1, flexDirection: "column" }}>
<Text
style={{
fontSize: 8,
flex: 1,
fontWeight: "bold",
color: stationColor[0],
}}
>
{trainName}
</Text>
</View>
</TouchableOpacity>
</Animated.View>
</View>
);
};

View File

@@ -1,44 +0,0 @@
import { FC } from "react";
import { View } from "react-native";
import dayjs from "dayjs";
import { SharedValue, useAnimatedStyle } from "react-native-reanimated";
import Animated from "react-native-reanimated";
export const ExGridViewTimePositionItem: FC<{
width: SharedValue<number>;
hour: string;
}> = ({ width, hour }) => {
const date = dayjs();
const formattedTime = date.format("m");
const formattedHour = date.format("H");
// if(typeString == "回送"){
// return<></>;
// }
const animatedStyle = useAnimatedStyle(() => {
const leftPosition =
((((width.value - 50) / 100) * parseInt(formattedTime)) / 60) * 100;
return {
left: leftPosition,
};
}, [formattedTime]);
if (formattedHour != hour) return <></>;
return (
<View style={{ left: 0, height: 50, width: 1 }}>
<Animated.View
style={[
{
flexDirection: "column",
borderLeftWidth: 2,
//borderBottomWidth: 0.5,
borderStyle: "solid",
borderColor: "red",
position: "absolute",
height: "100%",
},
animatedStyle,
]}
/>
</View>
);
};

View File

@@ -1,43 +0,0 @@
import { FC } from "react";
import { ListViewItem } from "@/components/StationDiagram/ListViewItem";
import { View, Text, ScrollView } from "react-native";
type hoge = {
trainNumber: string;
array: string;
name: string;
timeType: string;
time: string;
};
export const ListView: FC<{
data: hoge[];
}> = ({ data }) => {
const groupedData: Record<string, hoge[]> = {};
const groupKeys = [];
data.forEach((item) => {
const hour = item.time.split(":")[0];
if (!groupedData[hour]) {
groupedData[hour] = [];
groupKeys.push(hour);
}
groupedData[hour].push(item);
});
return (
<ScrollView
style={{ backgroundColor: "white" }}
stickyHeaderIndices={
groupKeys.at(0) ? groupKeys.map((_, i) => i * 2) : []
}
>
{groupKeys.map((hour) => [
<View style={{ backgroundColor: "white", padding: 5, borderBottomWidth: 0.5, borderTopWidth: 0.5, borderBottomColor: "#ccc" }} key={hour}>
<Text style={{ fontSize: 15 }}>{hour}</Text>
</View>,
<View>
{groupedData[hour].map((d, i) => (
<ListViewItem key={d.trainNumber + i} d={d} />
))}
</View>,
])}
</ScrollView>
);
};

View File

@@ -1,247 +0,0 @@
import { migrateTrainName } from "@/lib/eachTrainInfoCoreLib/migrateTrainName";
import { getStringConfig } from "@/lib/getStringConfig";
import { getTrainType } from "@/lib/getTrainType";
import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
import { FC, useEffect, useMemo, useState } from "react";
import { View, Text, TouchableOpacity } from "react-native";
import { customTrainDataDetector } from "../custom-train-data";
import dayjs from "dayjs";
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";
import { StationNumberMaker } from "../駅名表/StationNumberMaker";
import { getStationID } from "@/lib/eachTrainInfoCoreLib/getStationData";
import lineColorList from "@/assets/originData/lineColorList";
export const ListViewItem: FC<{
d: {
trainNumber: string;
array: string;
name: string;
timeType: string;
time: string;
};
}> = ({ d }) => {
const { allCustomTrainData } = useAllTrainDiagram();
const { navigate, goBack } = useNavigation();
const [trainData, setTrainData] = useState<CustomTrainData>();
useEffect(() => {
if (allCustomTrainData) {
allCustomTrainData.forEach((x) => {
if (x.TrainNumber === d.trainNumber) {
setTrainData(x);
}
});
}
}, []);
const { color, name, data } = getTrainType({
type: trainData?.type,
whiteMode: true,
});
// 列車名、種別、フォントの取得
const { getStationDataFromName, stationList, originalStationList } =
useStationList();
const [
typeString,
trainName,
fontAvailable,
isOneMan,
infogram,
isEdit,
uwasa,
vehicleFormation,
trainInfoUrl,lineColor
] = useMemo(() => {
const {
type,
trainName,
trainNumDistance,
infogram,
isEdit,
uwasa,
vehicleFormation,
trainInfoUrl,
} = customTrainDataDetector(d.trainNumber, allCustomTrainData);
const [typeString, fontAvailable, isOneMan] = getStringConfig(
type,
d.trainNumber
);
const trainData = d.array.split("#").filter((d) => d !== "");
const station = getStationDataFromName(trainData[trainData.length - 1].split(",")[0]);
const lineColor =
station.length > 0
? lineColorList[station[0]?.StationNumber.slice(0, 1)]
: "black";
switch (true) {
case trainData[trainData.length - 1] === undefined:
return [
typeString,
"",
fontAvailable,
isOneMan,
infogram,
isEdit,
uwasa,
vehicleFormation,
trainInfoUrl,lineColor
];
default:
// 行先がある場合は、行先を取得
return [
typeString,
migrateTrainName(
trainData[trainData.length - 1].split(",")[0] + "行き"
),
fontAvailable,
isOneMan,
infogram,
isEdit,
uwasa,
vehicleFormation,
trainInfoUrl,lineColor
];
}
}, [d.array]);
const timeArray = d.time.split(":").map((s) => parseInt(s));
const formattedTime = dayjs()
.set("hour", timeArray[0])
.set("minute", timeArray[1])
.format("HH:mm");
const openStationACFromEachTrainInfo = async (stationName) => {
await SheetManager.hide("EachTrainInfo");
const findStationEachLine = (selectLine) => {
let NearStation = selectLine.filter((d) => d.Station_JP == stationName);
return NearStation;
};
let returnDataBase = lineList
.map((d) => findStationEachLine(originalStationList[d]))
.filter((d) => d.length > 0)
.reduce((pre, current) => {
pre.push(...current);
return pre;
}, []);
if (returnDataBase.length) {
const payload = {
currentStation: returnDataBase,
navigate,
//@ts-ignore
useShow: () => SheetManager.show("StationDetailView", { payload }),
onExit: () => SheetManager.hide("StationDetailView"),
}; //@ts-ignore
setTimeout(() => SheetManager.show("StationDetailView", { payload }), 50);
} else {
SheetManager.hide("StationDetailView");
}
};
const openTrainInfo = () => {
let TrainNumber = "";
if (trainData.trainNumDistance != undefined) {
const timeInfo =
parseInt(trainData.TrainNumber.replace("M", "").replace("D", "")) -
trainData.trainNumDistance;
TrainNumber = timeInfo + "号";
}
const payload = {
data: {
trainNum: trainData.TrainNumber,
limited: `${data}:${trainData.trainName}${TrainNumber}`,
},
navigate,
openStationACFromEachTrainInfo,
from: "AllTrainIDList",
};
SheetManager.show("EachTrainInfo", {
//@ts-ignore
payload,
onClose: (data) => {
//alert(data);
},
});
};
return (
<TouchableOpacity
style={{
flexDirection: "row",
marginHorizontal: 10,
borderTopWidth: 1,
borderBottomWidth: 0.5,
borderStyle: "solid",
borderColor: "darkgray",
padding: 10,
opacity: d.timeType?.includes("通") ? 0.5 : 1,
}}
onPress={() => openTrainInfo()}
>
<View style={{ position: "relative", flex: 3 }}>
<Text style={{ fontSize: 30, fontFamily: "DiaPro" }}>
{formattedTime}
</Text>
<Text
style={{
fontSize: 10,
position: "absolute",
bottom: -3,
right: 0,
fontWeight: "bold",
}}
>
{d.timeType}
</Text>
</View>
<View style={{ flex: 10, flexDirection: "column" }}>
<View style={{ flexDirection: "row" }}>
<Text
style={{
fontSize: 15,
fontFamily: fontAvailable ? "JR-Nishi" : undefined,
fontWeight: !fontAvailable ? "bold" : undefined,
paddingTop: fontAvailable ? 2 : 0,
paddingLeft: 10,
color: color,
}}
>
{typeString}
</Text>
<Text
style={{
fontSize: 15,
fontWeight: "bold",
flex: 1,
paddingLeft: 2,
color: color,
}}
>
{trainData?.trainName +
(trainData?.trainNumDistance !== null
? ` ${parseInt(d.trainNumber) - trainData?.trainNumDistance}`
: "")}
</Text>
<Text
style={{
fontSize: 15,
fontWeight: "bold",
}}
>
{trainData?.TrainNumber}
</Text>
</View>
<View style={{ flexDirection: "row", alignItems: "center", flex: 1 }}>
<Text
style={{
fontSize: 15,
flex: 1,
paddingHorizontal: 10,
fontWeight: "bold",
color: lineColor
}}
>
{trainName}
</Text>
</View>
</View>
</TouchableOpacity>
);
};

View File

@@ -1,164 +0,0 @@
import lineColorList from "@/assets/originData/lineColorList";
import { useStationList } from "@/stateBox/useStationList";
import { FC, useEffect, useState } from "react";
import {
View,
Text,
ScrollView,
TouchableOpacity,
LayoutAnimation,
} from "react-native";
type hoge = {
trainNumber: string;
array: string;
name: string;
timeType: string;
time: string;
}[];
export const SearchInputSuggestBox: FC<{
input: string;
setInput: (f: string) => void;
currentStationDiagram: hoge;
}> = ({ input, setInput, currentStationDiagram }) => {
const { getStationDataFromName } = useStationList();
const [stationList, setStationList] = useState<
{
stationName: string;
number: string[];
}[]
>([]);
const [listFiltered, setListFiltered] = useState<string>("");
const [filteredStationLine, setFilteredStationLine] = useState<string[]>([]);
useEffect(() => {
const x: { stationName: string; number: string[] }[] = [];
currentStationDiagram.forEach((d) => {
d.array.split("#").forEach((s) => {
if (s == "") return;
const [stationName, type, time] = s.split(",");
if (!x.find((item) => item.stationName === stationName)) {
if (!type?.includes("通")) {
const stationData = getStationDataFromName(stationName);
if (listFiltered === "その他") {
if (stationData.length === 0) {
x.push({
stationName,
number: stationData.map((item) => item.StationNumber),
});
return;
}
}
const filter = stationData.filter((s) => {
if (listFiltered === "") return true;
if (listFiltered === "その他") {
return !(
s.StationNumber ? s.StationNumber.slice(0, 1) : ""
).match(/[A-Z]/);
}
return (
s.StationNumber ? s.StationNumber.slice(0, 1) : ""
).includes(listFiltered);
});
if (filter.length === 0) return;
x.push({
stationName,
number: stationData.map((item) => item.StationNumber),
});
}
}
});
});
setStationList(x);
}, [currentStationDiagram, listFiltered]);
useEffect(() => {
const filtered = stationList
.map((s) => s.number?.map((r) => (r ? r.slice(0, 1) : "")))
.flat();
const arrayB = Array.from(new Set(filtered));
setFilteredStationLine(arrayB.map((r) => (r !== "" ? r : "その他")));
}, [stationList]);
return (
<View
style={{
maxHeight: 200,
width: "100%",
backgroundColor: "#0099CC",
zIndex: 100,
}}
>
<Text>{input}</Text>
<ScrollView keyboardShouldPersistTaps="handled">
<View style={{ flexDirection: "row", flexWrap: "wrap" }}>
{stationList.map(({ stationName, number }) => (
<TouchableOpacity
style={{
margin: 5,
padding: 5,
backgroundColor: "#eee",
borderRadius: 20,
}}
key={stationName + number.join(",")}
onPress={() => setInput(stationName)}
>
<Text>{stationName}</Text>
</TouchableOpacity>
))}
</View>
</ScrollView>
<View
style={{
flexDirection: "row",
flexWrap: "wrap",
borderTopColor: "#ccc",
borderTopWidth: 0.5,
paddingTop: 0,
marginTop: 10,
}}
>
<TouchableOpacity
style={{
margin: 5,
padding: 5,
backgroundColor: "#eee",
borderRadius: 5,
}}
key={"empty"}
onPress={() => {
LayoutAnimation.configureNext({
duration: 400,
update: { type: "easeInEaseOut", springDamping: 0.6 },
});
setListFiltered("");
}}
>
<Text></Text>
</TouchableOpacity>
{filteredStationLine.map((line) => (
<TouchableOpacity
style={{
margin: 5,
padding: 5,
backgroundColor: lineColorList[line]
? `${lineColorList[line]}`
: "#eee",
borderRadius: 5,
}}
key={line}
onPress={() => {
LayoutAnimation.configureNext({
duration: 400,
update: { type: "easeInEaseOut", springDamping: 0.6 },
});
setListFiltered(line);
}}
>
<Text style={{ color: lineColorList[line] ? `white` : "black" }}>
{line}
</Text>
</TouchableOpacity>
))}
</View>
</View>
);
};

View File

@@ -1,509 +0,0 @@
import { FC, useEffect, useState } from "react";
import {
View,
Text,
ScrollView,
TextInput,
Keyboard,
KeyboardAvoidingView,
Platform,
TouchableOpacity,
LayoutAnimation,
} from "react-native";
import { useNavigation } from "@react-navigation/native";
import { BigButton } from "../atom/BigButton";
import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
import { ListView } from "@/components/StationDiagram/ListView";
import dayjs from "dayjs";
import { ExGridView } from "./ExGridView";
import { Switch } from "react-native-elements";
import { customTrainDataDetector } from "../custom-train-data";
import { getTrainType } from "@/lib/getTrainType";
import { trainTypeID } from "@/lib/CommonTypes";
import { SearchInputSuggestBox } from "./SearchBox/SearchInputSuggestBox";
type props = {
route: {
params: {
currentStation: {
Station_JP: string;
Station_EN: string;
StationName?: string;
MyStation?: string;
StationNumber: string;
DispNum?: string;
StationTimeTable: string;
StationMap?: string;
JrHpUrl?: string;
lat: number;
lng: number;
jslodApi: string;
}[];
};
};
};
export const StationDiagramView: FC<props> = ({ route }) => {
if (!route.params) {
return null;
}
const { currentStation } = route.params;
// 必要な情報:駅情報、全ダイヤ、カスタム列車情報
// 表示モード:縦並びリスト、横並びグリッド(時刻分割)、横並び単純左詰め
// フィルタリング:終点路線、種別、行先、関係停車駅
const { keyList, allTrainDiagram, allCustomTrainData } = useAllTrainDiagram();
const { navigate, addListener, goBack, canGoBack } = useNavigation();
const [keyBoardVisible, setKeyBoardVisible] = useState(false);
const [input, setInput] = useState("");
const [displayMode, setDisplayMode] = useState<"list" | "grid">("list");
const [selectedTypeList, setSelectedTypeList] = useState<trainTypeID[]>([
"Normal",
"OneMan",
"Rapid",
"OneManRapid",
"LTDEXP",
"NightLTDEXP",
]);
type hoge = {
trainNumber: string;
array: string;
name: string;
timeType: string;
time: string;
}[];
const [showTypeFiltering, setShowTypeFiltering] = useState(false);
const [showLastStop, setShowLastStop] = useState(false);
const [threw, setIsThrew] = useState(false);
const [currentStationDiagram, setCurrentStationDiagram] = useState<hoge>([]);
useEffect(() => {
if (allTrainDiagram && currentStation.length > 0) {
const stationName = currentStation[0].Station_JP;
let returnDataArray: hoge = [];
keyList
.filter((s) => {
const boolData = allTrainDiagram[s];
let isStop = false;
let isStopPos = -1;
let isInput = false;
let isInputPos = -1;
boolData.split("#").forEach((d, index, array) => {
const [station, type, time] = d.split(",");
if (station === stationName) {
isStop = true;
isStopPos = index;
}
if (station === input && type && !type.includes("通")) {
isInput = true;
isInputPos = index;
}
});
if (input && input.length > 0) {
if (isInput && isStop) {
return isInputPos > isStopPos;
}
return false;
}
return isStop;
})
.forEach((d) => {
allTrainDiagram[d]
.split("#")
.filter((d) => {
const [station, type, time] = d.split(",");
return station === stationName;
})
.forEach((x) => {
const [name, timeType, time] = x.split(",");
if (!name || !timeType || !time) return;
const { img, trainName, type, trainNumDistance, infogram } =
customTrainDataDetector(d, allCustomTrainData);
const arrayData = {
trainNumber: d,
array: allTrainDiagram[d],
name,
timeType,
time,
};
// //条件によってフィルタリング
if (!threw && timeType && timeType.includes("通")) return;
if (!showLastStop && timeType && timeType.includes("着")) return;
if (
selectedTypeList.findIndex((item) => item === "SPCL") === -1
) {
if (d.match(/9\d\d\d[D,M,S]/)) return;
}
if (
selectedTypeList.length > 0 &&
selectedTypeList.findIndex((item) => item === type) === -1
) {
if (
selectedTypeList.findIndex(
(item) => item === "Forwarding"
) !== -1
) {
if (!d.match(/[A,B,R,H,E,T,L]/)) return;
} else if (
selectedTypeList.findIndex((item) => item === "SPCL") !== -1
) {
if (!d.match(/9\d\d\d[D,M,S]/)) return;
} else {
return;
}
}
returnDataArray.push(arrayData);
});
});
setCurrentStationDiagram(
returnDataArray.sort((a, b) => {
const adjustTime = (t: string) => {
const [h, m] = t.split(":").map(Number);
// 4時未満は翌日の時刻とみなして+24時間
return h < 4
? dayjs().add(1, "day").hour(h).minute(m)
: dayjs().hour(h).minute(m);
};
const aa = adjustTime(a.time);
const bb = adjustTime(b.time);
const x = aa.isAfter(bb);
return x ? 1 : -1;
//return true;
})
);
}
}, [currentStation, showLastStop, threw, input, selectedTypeList]);
useEffect(() => {
const showSubscription = Keyboard.addListener("keyboardDidShow", () => {
LayoutAnimation.configureNext({
duration: 600,
update: { type: "spring", springDamping: 0.6 },
});
setKeyBoardVisible(true);
});
const hideSubscription = Keyboard.addListener("keyboardDidHide", () => {
LayoutAnimation.configureNext({
duration: 600,
update: { type: "spring", springDamping: 0.6 },
});
setKeyBoardVisible(false);
});
return () => {
showSubscription.remove();
hideSubscription.remove();
};
}, []);
return (
<View style={{ height: "100%", backgroundColor: "#0099CC" }}>
<Text
style={{
textAlign: "center",
fontSize: 20,
color: "white",
fontWeight: "bold",
paddingVertical: 10,
}}
>
{currentStation[0].Station_JP}
</Text>
{displayMode === "list" ? (
<ListView data={currentStationDiagram} />
) : (
<ExGridView data={currentStationDiagram} />
)}
{/* <Text
style={{
backgroundColor: "white",
borderWidth: 1,
borderStyle: "solid",
}}
>
お気に入り登録した駅のうち、位置情報システムで移動可能な駅が表示されています。タップすることで位置情報システムの当該の駅に移動します。
</Text> */}
<KeyboardAvoidingView
behavior="padding"
keyboardVerticalOffset={80}
enabled={Platform.OS === "ios"}
>
{!keyBoardVisible ? (
<ScrollView
horizontal
style={{
height: 35,
flexDirection: "row",
display: "flex",
}}
>
<TouchableOpacity
style={{
alignItems: "center",
marginHorizontal: 5,
backgroundColor: threw ? "white" : "#ffffff00",
alignSelf: "center",
borderColor: "white",
borderWidth: 1,
borderRadius: 100,
}}
onPress={() => {
setIsThrew(!threw);
}}
>
<Text
style={{
color: threw ? "#0099CC" : "white",
fontSize: 14,
margin: 5,
}}
>
</Text>
</TouchableOpacity>
<TouchableOpacity
style={{
alignItems: "center",
marginHorizontal: 5,
backgroundColor: showLastStop ? "white" : "#ffffff00",
alignSelf: "center",
borderColor: "white",
borderWidth: 1,
borderRadius: 100,
}}
onPress={() => {
setShowLastStop(!showLastStop);
}}
>
<Text
style={{
color: showLastStop ? "#0099CC" : "white",
fontSize: 14,
margin: 5,
}}
>
</Text>
</TouchableOpacity>
<View
style={{
height: "auto",
borderLeftWidth: 1,
margin: 5,
borderColor: "white",
}}
/>
{showTypeFiltering ? (
<>
<TypeSelectorBox
selectedTypeList={selectedTypeList}
setSelectedTypeList={setSelectedTypeList}
typeID="Normal"
relativeID={["OneMan"]}
/>
<TypeSelectorBox
selectedTypeList={selectedTypeList}
setSelectedTypeList={setSelectedTypeList}
typeID="Rapid"
relativeID={["OneManRapid"]}
/>
<TypeSelectorBox
selectedTypeList={selectedTypeList}
setSelectedTypeList={setSelectedTypeList}
typeID="LTDEXP"
relativeID={["NightLTDEXP"]}
/>
<TypeSelectorBox
selectedTypeList={selectedTypeList}
setSelectedTypeList={setSelectedTypeList}
typeID="SPCL"
relativeID={[
"SPCL_Normal",
"SPCL_Rapid",
"SPCL_EXP",
"Party",
]}
/>
<TypeSelectorBox
selectedTypeList={selectedTypeList}
setSelectedTypeList={setSelectedTypeList}
typeID="Freight"
/>
<TypeSelectorBox
selectedTypeList={selectedTypeList}
setSelectedTypeList={setSelectedTypeList}
typeID="Forwarding"
relativeID={["FreightForwarding"]}
/>
<TouchableOpacity
style={{
alignItems: "center",
marginHorizontal: 5,
backgroundColor: "#ffffff00",
alignSelf: "center",
borderColor: "white",
borderWidth: 1,
borderRadius: 100,
}}
onPress={() => {
LayoutAnimation.configureNext(
LayoutAnimation.Presets.easeInEaseOut
);
setShowTypeFiltering(false);
}}
>
<Text
style={{
color: "white",
fontSize: 14,
margin: 5,
}}
>
</Text>
</TouchableOpacity>
</>
) : (
<TouchableOpacity
style={{
alignItems: "center",
marginHorizontal: 5,
backgroundColor: "#ffffff00",
alignSelf: "center",
borderColor: "white",
borderWidth: 1,
borderRadius: 100,
}}
onPress={() => {
LayoutAnimation.configureNext(
LayoutAnimation.Presets.easeInEaseOut
);
setShowTypeFiltering(true);
}}
>
<Text
style={{
color: "white",
fontSize: 14,
margin: 5,
}}
>
</Text>
</TouchableOpacity>
)}
<TouchableOpacity
style={{
alignItems: "center",
marginHorizontal: 5,
backgroundColor: "#ffffff00",
alignSelf: "center",
borderColor: "white",
borderWidth: 1,
borderRadius: 100,
}}
onPress={() => {
setDisplayMode(displayMode === "list" ? "grid" : "list");
}}
>
<Text
style={{
color: "white",
fontSize: 14,
margin: 5,
}}
>
{displayMode === "list" ? "横並びモード" : "リストモード"}
</Text>
</TouchableOpacity>
</ScrollView>
) : (
<View style={{ position: "relative", display: "flex" }}>
<SearchInputSuggestBox
input={input}
setInput={setInput}
currentStationDiagram={currentStationDiagram}
/>
</View>
)}
<View
style={{
height: 35,
margin: 5,
alignItems: "center",
backgroundColor: "#F4F4F4",
flexDirection: "row",
paddingLeft: 10,
paddingRight: 10,
borderRadius: 25,
borderColor: "#F4F4F4",
}}
>
<TextInput
placeholder="駅名を入力して停車駅でフィルタリングします。"
onFocus={() => setKeyBoardVisible(true)}
onEndEditing={() => {}}
onChange={(ret) => setInput(ret.nativeEvent.text)}
value={input}
style={{ flex: 1 }}
/>
</View>
</KeyboardAvoidingView>
{keyBoardVisible || (
<BigButton onPress={() => goBack()} string="閉じる" />
)}
</View>
);
};
export const TypeSelectorBox: FC<{
selectedTypeList: trainTypeID[];
setSelectedTypeList: (list: trainTypeID[]) => void;
typeID: trainTypeID;
relativeID?: trainTypeID[];
}> = (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={{
alignItems: "center",
marginHorizontal: 5,
opacity: isSelected ? 1 : 0.8,
backgroundColor: isSelected ? "white" : color,
alignSelf: "center",
borderColor: color,
borderWidth: 1,
borderRadius: 100,
}}
onPress={() => {
if (selectedTypeList.findIndex((item) => item === typeID) === -1) {
setSelectedTypeList([
...selectedTypeList,
typeID,
...(relativeID ?? []),
]);
} else {
setSelectedTypeList(
selectedTypeList.filter(
(item) => item !== typeID && !relativeID?.includes(item)
)
);
}
}}
>
<Text
style={{
color: isSelected ? color : "white",
fontSize: 14,
margin: 5,
}}
>
{shortName}
</Text>
</TouchableOpacity>
);
};

View File

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

View File

@@ -180,11 +180,11 @@ export default function TrainMenu({ style }) {
flex={1}
onPressButton={() =>
navigate("howto", {
info: "https://xprocess.haruk.in/JR-shikoku-Apps-Common/info/train-position",
info: "https://train.jr-shikoku.co.jp/usage.htm",
})
}
>
走行位置の見
使い
</UsefulBox>
<UsefulBox
backgroundColor={"#EA4752"}

View File

@@ -1,35 +1,37 @@
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 { Linking, TouchableOpacity, Text } from "react-native";
import { Dialog, Button, Input } from "react-native-elements";
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 "@/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 { 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 { TrainPositionDataPush } from "./LED_inside_Component/TrainPositionDataPush";
import { TrainPositionDataDelete } from "./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: {
train: string;
lastStation: string;
time: string;
isThrough?: boolean;
};
trainIDSwitch: boolean;
trainDescriptionSwitch: boolean;
station: StationProps;
station: {
Station_JP: string;
StationNumber: string;
};
navigate: (screen: string, data?: any) => void;
openStationACFromEachTrainInfo: (station: string) => void;
};
@@ -44,7 +46,7 @@ export const EachData: FC<Props> = (props) => {
} = props;
const { currentTrain } = useCurrentTrain();
const { stationList } = useStationList();
const { allCustomTrainData } = useAllTrainDiagram();
const { allCustonTrainData } = useAllTrainDiagram();
const openTrainInfo = (d: {
train: string;
lastStation: string;
@@ -60,7 +62,7 @@ export const EachData: FC<Props> = (props) => {
const payload = {
data: {
trainNum: d.train,
limited: `${getTrainType({type:train.type}).data}:${
limited: `${getTrainType(train.type).data}:${
train.trainName
}${TrainNumber}`,
},
@@ -73,9 +75,35 @@ export const EachData: FC<Props> = (props) => {
});
};
const [train, setTrain] = useState<CustomTrainData>(getCurrentTrainData(d.train,currentTrain,allCustomTrainData));
const getTrainDataFromCurrentTrain = (trainNum: string) => {
const customTrainData = customTrainDataDetector(
d.train,
allCustonTrainData
);
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(getTrainDataFromCurrentTrain(d.train));
useEffect(() => {
setTrain(getCurrentTrainData(d.train,currentTrain,allCustomTrainData));
setTrain(getTrainDataFromCurrentTrain(d.train));
}, [currentTrain, d.train, trainDescriptionSwitch]);
// 土讃線複数存在対策
const currentTrainData = checkDuplicateTrainData(
@@ -87,31 +115,23 @@ export const EachData: FC<Props> = (props) => {
station.Station_JP
)}`;
// 投稿システム関係
// Dialog表示関係
const [platformNumber, setPlatformNumber] = useState<number>();
const [platformDescription, setPlatformDescription] = useState<string>();
const [dialog, setDialog] = useState(false);
const [deleteDialog, setDeleteDialog] = useState(false);
//固定値
const [PosNum, setPosNum] = useState<number | undefined>();
const [Pos, setPos] = useState<string>("");
const [Line, setLine] = useState<string>("");
const [StationNum, setStationNum] = useState<string>("");
//編集情報
const [lineInput, setLineInput] = useState<string>("");
const [posInput, setPosInput] = useState<string>("");
const [descInput, setDescInput] = useState<string>("");
const [posInput, setPosInput] = useState("");
const [descInput, setDescInput] = useState("");
const [stationInput, setStationInput] = useState("");
const [stationNumberInput, setStationNumberInput] = useState("");
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", IntH < 4 ? IntH + 24 : IntH)
.set("minute", IntM);
.set("hour", parseInt(d.time.split(":")[0]))
.set("minute", parseInt(d.time.split(":")[1]));
const diff = trainTime.diff(currentTime, "minute");
if (diff < 2) setIsDepartureNow(true);
else setIsDepartureNow(false);
@@ -127,30 +147,24 @@ export const EachData: FC<Props> = (props) => {
}, 800);
return (
<>
<StationPosDeleteDialog
<TrainPositionDataDelete
dialog={deleteDialog}
setDialog={setDeleteDialog}
Pos={Pos}
PosNum={PosNum}
Line={Line}
StationNum={StationNum}
{...{ currentTrainData, stationInput, stationNumberInput }}
/>
<StationPosPushDialog
// Dialog表示関係
<TrainPositionDataPush
dialog={dialog}
setDialog={setDialog}
// 固定情報
PosNum={PosNum}
Pos={Pos}
Line={Line}
StationNum={StationNum}
// 入力欄
lineInput={lineInput}
setLineInput={setLineInput}
posInput={posInput}
setPosInput={setPosInput}
descInput={descInput}
setDescInput={setDescInput}
{...{
currentTrainData,
stationInput,
stationNumberInput,
posInput,
descInput,
setPosInput,
setDescInput,
station,
}}
/>
<TouchableOpacity
style={{
@@ -172,50 +186,41 @@ export const EachData: FC<Props> = (props) => {
trainIDSwitch={trainIDSwitch}
trainID={d.train}
type={train.type}
isThrew={d.isThrough}
/>
<LastStation lastStation={d.lastStation} ToData={train.ToData} Station_JP={station.Station_JP} />
<LastStation lastStation={d.lastStation} />
<DependTime time={d.time} />
<StatusAndDelay trainDelayStatus={trainDelayStatus} />
</TouchableOpacity>
{!!isDepartureNow && (
<Description
info={
d.isThrough
? "通過列車にご注意ください"
: d.lastStation == station.Station_JP
d.lastStation == "当駅止"
? "この列車は当駅止です。間もなく到着します。"
: "列車の出発時刻です。"
}
key={d.train + "-isDepartureNow"}
key={d.train + "-description"}
/>
)}
{trainDescriptionSwitch && (
<TrainPosition
// LED表示関係
trainIDSwitch={trainIDSwitch}
currentTrainData={currentTrainData}
// ポップアップ表示関係
setStationInput={setStationInput}
setStationNumberInput={setStationNumberInput}
setDescInput={setDescInput}
setPosInput={setPosInput}
setDialog={setDialog}
setDeleteDialog={setDeleteDialog}
// 固定情報
setPos={setPos}
setPosNum={setPosNum}
setLine={setLine}
setStationNum={setStationNum}
//編集機能関係
setLineInput={setLineInput}
setPosInput={setPosInput}
setDescInput={setDescInput}
setPlatformDescription={setPlatformDescription}
setPlatformNumber={setPlatformNumber}
platformDescription={platformDescription}
platformNumber={platformNumber}
key={d.train + "-trainPosition"}
/>
)}
{trainDescriptionSwitch && !!train.info && (
<Description info={train.info} key={d.train + "-description"} />
)}
{trainDescriptionSwitch && !!train.uwasa && (
<Description info={train.uwasa} key={d.train + "-uwasa"} />
)}
</>
);
};

View File

@@ -1,79 +0,0 @@
import React, { FC, useState, useEffect } from "react";
import { Text, TextStyle, View, TouchableOpacity } from "react-native";
import { useInterval } from "../../../lib/useInterval";
const descriptionStyle: TextStyle = {
fontSize: parseInt("16%"),
fontWeight: "bold",
};
type Props = {
areaInfo: string;
numberOfLines?: number;
onClick?: () => void;
onLongClick?: () => void;
};
export const AreaDescription:FC<Props> = ({ areaInfo, numberOfLines = 0, onClick, onLongClick }) => {
const [areaString, setAreaString] = useState("");
const [areaStringLength, setAreaStringLength] = useState(0);
const [move, setMove] = useState(0);
useInterval(
() => {
if (areaInfo != "") {
setMove(areaStringLength < move ? 0 : move + 1);
}
},
350,
true
);
useEffect(() => {
if (!areaInfo) {
setAreaString("");
return () => {};
}
setAreaString(
areaInfo.substring(move, areaInfo.length) + areaInfo.substring(0, move)
);
}, [move]);
useEffect(() => {
if (!areaInfo) {
setAreaStringLength(0);
return () => {};
}
setAreaStringLength(areaInfo.length);
}, [areaInfo]);
return(
<TouchableOpacity
style={{
alignContent: "center",
alignItems: "center",
width: "94%",
marginVertical: 5,
marginHorizontal: "3%",
backgroundColor: "#000",
flexDirection: "row",
overflow: "hidden",
}}
onPress={onClick}
onLongPress={onLongClick}
>
<View style={{ flex: 4, flexDirection: "row" }}>
{numberOfLines == 1 ? (
<Text style={{ ...descriptionStyle, color: "red" }}>
&gt;{" "}
</Text>
) : (
<Text style={{ ...descriptionStyle, color: "green" }}> &gt; </Text>
)}
<Text
style={{ ...descriptionStyle, color: "green" }}
numberOfLines={numberOfLines}
>
{areaString.replaceAll("\n", "").replaceAll("\r", "")}
</Text>
</View>
</TouchableOpacity>
);
};

View File

@@ -3,22 +3,18 @@ import { Text, View } from "react-native";
type Props = {
lastStation: string;
ToData: string;
Station_JP: string;
};
export const LastStation: FC<Props> = ({ lastStation, ToData, Station_JP }) => {
const isEdit = !ToData ? false : ToData !== lastStation;
const string = isEdit ? ToData : lastStation;
export const LastStation: FC<Props> = ({ lastStation }) => {
return (
<View style={{ flex: 4, flexDirection: "row" }}>
<Text
style={{
fontSize: lastStation?.length > 4 ? parseInt("12%") : parseInt("16%"),
color: isEdit ? "#ffd16fff" : "white",
fontSize: lastStation.length > 4 ? parseInt("12%") : parseInt("16%"),
color: "white",
fontWeight: "bold",
}}
>
{string === Station_JP ? "当駅止" : string}
{lastStation}
</Text>
</View>
);

View File

@@ -1,18 +1,16 @@
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: trainTypeID;
isThrew: boolean;
type: string;
};
export const TrainName: FC<Props> = (props) => {
const { trainName, trainNumDistance, trainIDSwitch, trainID, type, isThrew } = props;
const { name, color } = getTrainType({ type });
const { trainName, trainNumDistance, trainIDSwitch, trainID, type } = props;
const { name, color } = getTrainType(type);
const TrainNumber =
trainNumDistance != undefined
? `${
@@ -28,7 +26,7 @@ export const TrainName: FC<Props> = (props) => {
fontWeight: "bold",
}}
>
{trainIDSwitch ? trainID : `${isThrew ? `★通過列車★` : `${name} ${trainName}${TrainNumber}`} `}
{trainIDSwitch ? trainID : `${name} ${trainName}${TrainNumber}`}
</Text>
</View>
);

View File

@@ -1,4 +1,4 @@
import React, { FC, useEffect, useState } from "react";
import React, { FC, useEffect } from "react";
import { Text, TextStyle, View, TouchableOpacity } from "react-native";
import { useStationList } from "../../../stateBox/useStationList";
import {
@@ -14,118 +14,56 @@ const descriptionStyle: TextStyle = {
};
type Props = {
// LED表示関係
numberOfLines?: number;
trainIDSwitch: boolean;
currentTrainData: trainDataType;
//ポップアップ表示関係
setStationInput: (station: string) => void;
setStationNumberInput: (station: string) => void;
setDescInput: (desc: string) => void;
setPosInput: (pos: string) => void;
setDialog: (dialog: boolean) => void;
setDeleteDialog: (dialog: boolean) => void;
//固定値設定
setPos: React.Dispatch<React.SetStateAction<string>>
setPosNum: React.Dispatch<React.SetStateAction<number>>;
setLine: React.Dispatch<React.SetStateAction<string>>;
setStationNum: React.Dispatch<React.SetStateAction<string>>;
//編集機能関係
setLineInput: (line: string) => void;
setPosInput: (pos: string) => void;
setDescInput: (desc: string) => void;
platformDescription: string;
platformNumber: number;
setPlatformDescription: (desc: string) => void;
setPlatformNumber: (num: number) => void;
};
export const TrainPosition: FC<Props> = ({
// LED表示関係
numberOfLines = 0,
trainIDSwitch,
currentTrainData,
//ポップアップ表示関係
setStationInput,
setStationNumberInput,
setDescInput,
setPosInput,
setDialog,
setDeleteDialog,
//固定値設定
setPos,
setPosNum,
setLine,
setStationNum,
//編集機能関係
setLineInput,
setPosInput,
setDescInput,
setPlatformDescription,
setPlatformNumber,
platformDescription,
platformNumber,
}) => {
const { currentTrain } = useCurrentTrain();
const { stationList } = useStationList();
type data = {
type: string;
lineNumber: string;
platformNumber: string;
position: string;
stationName: string;
description: string;
};
const [database, setDatabase] = useState<data>(null);
const [text, setText] = useState("");
const [masterText, setMasterText] = useState("");
useEffect(() => {
const text = `${currentTrainData?.PosNum} ${currentTrainData?.Line} ${currentTrainData?.Pos}`;
setText(trainIDSwitch ? text : masterText);
return () => {
setText("");
};
}, [masterText, trainIDSwitch]);
useEffect(() => {
fetch(
`https://n8n.haruk.in/webhook/JR-shikoku-PosID-v3?PosId=${currentTrainData?.PosNum}&lineName=${currentTrainData?.Line}&StationName=${currentTrainData?.Pos}`
`https://n8n.haruk.in/webhook/JR-shikoku-PosID?PosNum=${currentTrainData?.PosNum}&Line=${currentTrainData?.Line}`
)
.then((res) => res.json())
.then((data: data) => {
const { type, platformNumber, description, lineNumber } = data;
setDatabase(data);
const { isBetween, Pos } = trainPosition(currentTrainData);
if (isBetween === true) {
// 移動中
setMasterText(`現在地:${Pos.from}${Pos.to}間を走行中`);
} else {
if (Pos.Pos) {
let platform = platformNumber ? `${platformNumber}番乗り場` : "";
let line = lineNumber ? `${lineNumber}番線` : "";
setMasterText(
`現在地:${Pos.Pos} ${platform || line} ${description || ""}`
);
} else {
setMasterText("");
}
}
.then((data: { type: string; platform: number; description: string }) => {
setPlatformNumber(data?.type == "Station" ? data?.platform : undefined);
setPlatformDescription(
data?.type == "Station" ? data?.description : undefined
);
});
return () => {
setMasterText("");
};
}, [currentTrainData?.PosNum, currentTrainData?.Line, currentTrainData?.Pos]);
//editWindow向けにfixした情報を送信
const openEditWindow = () => {
const { isBetween, Pos } = trainPosition(currentTrainData);
}, [currentTrainData, currentTrain]);
//固定値
setPosNum(currentTrainData?.PosNum);
setPos(currentTrainData?.Pos);
setLine(currentTrainData?.Line);
setStationNum(getStationID(currentTrainData?.Pos, stationList));
//入力欄
if (isBetween === true) {
if (
database?.platformNumber == undefined &&
database?.description == undefined
)
return;
setDeleteDialog(true);
} else {
setPosInput(database?.platformNumber?.toString() || "");
setDescInput(database?.description || "");
setLineInput(database?.lineNumber?.toString() || "");
setDialog(true);
}
const trainPositionText = (trainData: trainDataType) => {
const { isBetween, Pos } = trainPosition(trainData);
if (isBetween === true) return `現在地:${Pos.from}${Pos.to}間を走行中`;
else return Pos.Pos == "" ? "" : `現在地:${Pos.Pos}`;
};
return (
@@ -140,14 +78,40 @@ export const TrainPosition: FC<Props> = ({
flexDirection: "row",
overflow: "hidden",
}}
onLongPress={openEditWindow}
onLongPress={() => {
const { isBetween, Pos } = trainPosition(currentTrainData);
if (isBetween === true) {
if (platformNumber == undefined && platformDescription == undefined)
return;
setStationInput(`${Pos.from}${Pos.to}`);
setStationNumberInput(
getStationID(currentTrainData?.Pos, stationList)
);
setPosInput(platformNumber?.toString() || "");
setDeleteDialog(true);
} else {
setStationInput(Pos.Pos);
setStationNumberInput(
getStationID(currentTrainData?.Pos, stationList)
);
setDescInput(platformDescription || "");
setPosInput(platformNumber?.toString() || "");
setDialog(true);
}
}}
>
<View style={{ flex: 4, flexDirection: "row" }}>
<Text
style={{ ...descriptionStyle, color: "green" }}
numberOfLines={numberOfLines}
>
{text}
{`${
trainIDSwitch
? currentTrainData?.PosNum + currentTrainData?.Line
: trainPositionText(currentTrainData)
} ${platformNumber ? platformNumber + "番線" : ""} ${
platformDescription ? "(" + platformDescription + ")" : ""
}`}
</Text>
</View>
</TouchableOpacity>

View File

@@ -1,32 +1,28 @@
import React, { FC } from "react";
import { Text } from "react-native";
import { Dialog, Button } from "react-native-elements";
import { trainDataType } from "../../../lib/trainPositionTextArray";
type Props = {
dialog: boolean;
setDialog: (dialog: boolean) => void;
PosNum: number;
Line: string;
Pos: string;
StationNum: string;
currentTrainData: trainDataType;
stationInput: string;
stationNumberInput: string;
};
export const StationPosDeleteDialog: FC<Props> = ({
export const TrainPositionDataDelete: FC<Props> = ({
dialog,
setDialog,
PosNum,
Line,
Pos,
StationNum
currentTrainData,
stationInput,
stationNumberInput,
}) => {
const sendPlatformData = () => {
fetch(`https://n8n.haruk.in/webhook/JR-shikoku-PosID-v3`, {
fetch(`https://n8n.haruk.in/webhook/JR-shikoku-PosID`, {
method: "DELETE",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
PosId: PosNum,
lineName: Line,
StationName: Pos, //自動:駅名、漢字
PosId: currentTrainData?.PosNum,
lineName: currentTrainData?.Line,
}),
})
.then(() => {
@@ -40,10 +36,10 @@ export const StationPosDeleteDialog: FC<Props> = ({
return (
<Dialog isVisible={dialog} onBackdropPress={() => setDialog(false)}>
<Text></Text>
<Text>: {Line}</Text>
<Text>ID: {PosNum}</Text>
<Text>: {Pos}</Text>
<Text>: {StationNum}</Text>
<Text>: {currentTrainData?.Line}</Text>
<Text>ID: {currentTrainData?.PosNum}</Text>
<Text>: {stationInput}</Text>
<Text>: {stationNumberInput}</Text>
<Button title="送信" onPress={sendPlatformData} />
</Dialog>
);

View File

@@ -1,56 +1,46 @@
import React, { FC } from "react";
import React, { FC, useState } from "react";
import { Text } from "react-native";
import { Dialog, Input, Button } from "react-native-elements";
import { trainDataType } from "../../../lib/trainPositionTextArray";
import { getStationID } from "@/lib/eachTrainInfoCoreLib/getStationData";
import { useStationList } from "@/stateBox/useStationList";
import { useCurrentTrain } from "../../../stateBox/useCurrentTrain";
type Props = {
dialog: boolean;
setDialog: (dialog: boolean) => void;
PosNum:number;
Pos:string;
Line:string;
StationNum: string;
lineInput: string;
setLineInput: (line: string) => void;
currentTrainData: trainDataType;
stationInput: string;
stationNumberInput: string;
posInput: string;
setPosInput: (pos: string) => void;
descInput: string;
setPosInput: (pos: string) => void;
setDescInput: (desc: string) => void;
station: {
Station_JP: string;
StationNumber: string;
};
};
export const StationPosPushDialog: FC<Props> = ({
// Dialog表示関係
export const TrainPositionDataPush: FC<Props> = ({
dialog,
setDialog,
//固定情報
PosNum,//地点ID
Pos,//駅名
Line,//路線名
StationNum,//駅ナンバリング
//入力欄
lineInput,
setLineInput,
currentTrainData,
stationInput,
stationNumberInput,
posInput,
setPosInput,
descInput,
setPosInput,
setDescInput,
station,
}) => {
const { stationList } = useStationList();
const sendPlatformData = () => {
fetch(`https://n8n.haruk.in/webhook/JR-shikoku-PosID-v3`, {
fetch(`https://n8n.haruk.in/webhook/JR-shikoku-PosID`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
PosId: PosNum, //自動位置情報ID
StationId: getStationID(Pos, stationList), //自動駅ID
StationName: Pos, //自動:駅名、漢字
lineName: Line, //自動位置情報路線ID(koutoku/yosan)
Description: descInput, //手動入力、参考情報
platformNumber: parseInt(posInput), //手動入力、乗り場表記
lineNumber: parseInt(lineInput), //手動入力、番線表記
PosId: currentTrainData?.PosNum,
lineName: currentTrainData?.Line,
PlatformNum: parseInt(posInput),
Description: descInput,
StationName: station.Station_JP,
StationId: station.StationNumber,
}),
})
.then(() => {
@@ -65,22 +55,15 @@ export const StationPosPushDialog: FC<Props> = ({
};
return (
<Dialog isVisible={dialog} onBackdropPress={() => setDialog(false)}>
<Text style={{ fontSize: 20, fontWeight: "bold" }}>稿</Text>
<Text>: {Line}</Text>
<Text>ID: {PosNum}</Text>
<Text>: {Pos}</Text>
<Text>: {StationNum}</Text>
<Input
label="乗り場"
inputMode="numeric"
value={posInput}
onChangeText={setPosInput}
/>
<Text>: {currentTrainData?.Line}</Text>
<Text>ID: {currentTrainData?.PosNum}</Text>
<Text>: {stationInput}</Text>
<Text>: {stationNumberInput}</Text>
<Input
label="番線"
inputMode="numeric"
value={lineInput}
onChangeText={setLineInput}
value={posInput}
onChangeText={setPosInput}
/>
<Input
label="参考情報"
@@ -88,7 +71,6 @@ export const StationPosPushDialog: FC<Props> = ({
value={descInput}
onChangeText={setDescInput}
/>
<Text style={{ fontSize: 12, fontWeight: "bold" }}>稿稿</Text>
<Button title="送信" onPress={sendPlatformData} />
</Dialog>
);

View File

@@ -0,0 +1,259 @@
import React, { useState, useEffect } 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 { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
import { trainPosition } from "@/lib/trainPositionTextArray";
/**
*
* 1-30M しおかぜ
* 31-58D 南風
* 1001-1030M いしづち(併結)
* 1041-1046M いしづち(単独)
* 1051-1082D 宇和海
* 1091M MX松山
* 1092M MX高松
* 2001-2010D しまんと
* 2071-2086D あしずり
* 3001-3033D うずしお
* 3101-3177M マリンライナー
* 4001-4011D 剣山
* 5006,13,22,29 うずしお(岡山直通南風併結)
* 5831-5843D 土佐くろしお鉄道ごめん・なはり線直通快速
* 5853-5892D 土佐くろしお鉄道ごめん・なはり線直通普通
* 8011,8012D 四国まんなか千年ものがたり
* 8031,(8041) サンライズ瀬戸, 琴平(延長)
* 8053,8054D トキの夜明けのものがたり
* 8176,8179D アンパントロッコタカマツ
* 8277,8278D アンパントロッココトヒラ
* 8451,8452D よしの川トロッコ
* 8814,8819D しまんトロッコ
* 8911-8914D 伊予灘ものがたり
* 9001-9030* いしづち(リレー)
* 9031M サンライズ瀬戸琴平(延長)(臨時?)
* 9062D 四国まんなか千年ものがたり(臨時?)
*/
export default function LED_vision(props) {
const { station, navigate, openStationACFromEachTrainInfo } = props;
const { currentTrain } = useCurrentTrain();
const [stationDiagram, setStationDiagram] = useState({}); //当該駅の全時刻表
const [finalSwitch, setFinalSwitch] = useState(false);
const [trainIDSwitch, setTrainIDSwitch] = useState(false);
const [trainDescriptionSwitch, setTrainDescriptionSwitch] = useState(false);
const [isInfoArea, setIsInfoArea] = useState(false);
const { areaInfo, areaStationID } = useAreaInfo();
const { allTrainDiagram } = useAllTrainDiagram();
useEffect(() => {
AS.getItem("LEDSettings/trainIDSwitch").then((data) => {
setTrainIDSwitch(data === "true");
});
AS.getItem("LEDSettings/trainDescriptionSwitch").then((data) => {
setTrainDescriptionSwitch(data === "true");
});
AS.getItem("LEDSettings/finalSwitch").then((data) => {
setFinalSwitch(data === "true");
});
}, []);
useEffect(() => {
// 現在の駅に停車するダイヤを作成する副作用[列車ダイヤと現在駅情報]
if (!allTrainDiagram) {
setStationDiagram({});
return;
}
let returnData = {};
Object.keys(allTrainDiagram).forEach((key) => {
if (allTrainDiagram[key].match(station[0].Station_JP + ",")) {
returnData[key] = allTrainDiagram[key];
}
});
setStationDiagram(returnData);
setIsInfoArea(station.some((s) => areaStationID.includes(s.StationNumber)));
}, [allTrainDiagram, station]);
/*
{lastStation: "当駅止", time: "12:34", train: "1234M"}
*/
const [trainTimeAndNumber, setTrainTimeAndNumber] = useState([]);
useEffect(() => {
//現在の駅に停車する列車から時刻を切り出してLEDベースにフォーマット
if (objectIsEmpty(stationDiagram)) return () => {};
const getTimeData = getTime(stationDiagram, station[0]);
setTrainTimeAndNumber(getTimeData);
}, [stationDiagram]);
const [selectedTrain, setSelectedTrain] = useState([]);
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 != "当駅止");
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.split(",")[0] === station.Station_JP) {
if (data.match(",発,")) {
trainData.time = data.split(",発,")[1];
} else if (data.match(",着,")) {
trainData.time = data.split(",着,")[1];
trainData.lastStation = "当駅止";
}
}
});
return {
train: trainNum,
time: trainData.time,
lastStation: trainData.lastStation,
};
})
.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 != "当駅止") 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 [areaString, setAreaString] = useState("");
const [areaStringLength, setAreaStringLength] = useState(0);
const [move, setMove] = useState(0);
useInterval(
() => {
if (areaInfo != "") {
setMove(areaStringLength < move ? 0 : move + 1);
}
},
350,
true
);
useEffect(() => {
if (!areaInfo) {
setAreaString("");
return () => {};
}
setAreaString(
areaInfo.substring(move, areaInfo.length) + areaInfo.substring(0, move)
);
}, [move]);
useEffect(() => {
if (!areaInfo) {
setAreaStringLength(0);
return () => {};
}
setAreaStringLength(areaInfo.length);
}, [areaInfo]);
const { width } = useWindowDimensions();
const adjustedWidth = width * 0.98;
return (
<View
style={{
width: adjustedWidth,
/* height: wp("98%")/10*9, */ backgroundColor: "#432",
borderWidth: 1,
margin: 10,
marginHorizontal: width * 0.01,
}}
>
<Header station={station[0]} />
{selectedTrain.map((d) => (
<EachData
{...{
d,
trainIDSwitch,
trainDescriptionSwitch,
navigate,
openStationACFromEachTrainInfo,
}}
station={station[0]}
key={d.train}
/>
))}
{areaString != "" && isInfoArea && (
<Description
numberOfLines={1}
info={areaString.replaceAll("\n", "").replaceAll("\r", "")}
onClick={() => alert(areaInfo)}
/>
)}
<Footer
{...{
trainIDSwitch,
setTrainIDSwitch,
trainDescriptionSwitch,
setTrainDescriptionSwitch,
finalSwitch,
setFinalSwitch,
}}
/>
</View>
);
}

View File

@@ -1,164 +0,0 @@
import React, { useState, useEffect, FC } from "react";
import { View, useWindowDimensions } from "react-native";
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 { 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";
/**
*
* 1-30M しおかぜ
* 31-58D 南風
* 1001-1030M いしづち(併結)
* 1041-1046M いしづち(単独)
* 1051-1082D 宇和海
* 1091M MX松山
* 1092M MX高松
* 2001-2010D しまんと
* 2071-2086D あしずり
* 3001-3033D うずしお
* 3101-3177M マリンライナー
* 4001-4011D 剣山
* 5006,13,22,29 うずしお(岡山直通南風併結)
* 5831-5843D 土佐くろしお鉄道ごめん・なはり線直通快速
* 5853-5892D 土佐くろしお鉄道ごめん・なはり線直通普通
* 8011,8012D 四国まんなか千年ものがたり
* 8031,(8041) サンライズ瀬戸, 琴平(延長)
* 8053,8054D トキの夜明けのものがたり
* 8176,8179D アンパントロッコタカマツ
* 8277,8278D アンパントロッココトヒラ
* 8451,8452D よしの川トロッコ
* 8814,8819D しまんトロッコ
* 8911-8914D 伊予灘ものがたり
* 9001-9030* いしづち(リレー)
* 9031M サンライズ瀬戸琴平(延長)(臨時?)
* 9062D 四国まんなか千年ものがたり(臨時?)
*/
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<{
[key: string]: string;
}>({}); //当該駅の全時刻表
const [finalSwitch, setFinalSwitch] = useState(false);
const [trainIDSwitch, setTrainIDSwitch] = useState(false);
const [trainDescriptionSwitch, setTrainDescriptionSwitch] = useState(false);
const [isInfoArea, setIsInfoArea] = useState(false);
const { areaInfo, areaStationID } = useAreaInfo();
const { allTrainDiagram } = useAllTrainDiagram();
useEffect(() => {
AS.getItem("LEDSettings/trainIDSwitch").then((data) => {
setTrainIDSwitch(data === "true");
});
AS.getItem("LEDSettings/trainDescriptionSwitch").then((data) => {
setTrainDescriptionSwitch(data === "true");
});
AS.getItem("LEDSettings/finalSwitch").then((data) => {
setFinalSwitch(data === "true");
});
}, []);
useEffect(() => {
// 現在の駅に停車するダイヤを作成する副作用[列車ダイヤと現在駅情報]
if (!allTrainDiagram) {
setStationDiagram({});
return;
}
let returnData = {};
Object.keys(allTrainDiagram).forEach((key) => {
if (allTrainDiagram[key].match(station[0].Station_JP + ",")) {
returnData[key] = allTrainDiagram[key];
}
});
setStationDiagram(returnData);
setIsInfoArea(station.some((s) => areaStationID.includes(s.StationNumber)));
}, [allTrainDiagram, station]);
/*
{lastStation: "当駅止", time: "12:34", train: "1234M"}
*/
const [trainTimeAndNumber, setTrainTimeAndNumber] = useState<
eachTrainDiagramType[]
>([]);
useEffect(() => {
//現在の駅に停車する列車から時刻を切り出してLEDベースにフォーマット
if (objectIsEmpty(stationDiagram)) return () => {};
const getTimeData = getTime(stationDiagram, station[0]);
setTrainTimeAndNumber(getTimeData);
}, [stationDiagram]);
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((d) => trainTimeFiltering({ d, currentTrain, station })) //時間フィルター
.filter((d) => !!finalSwitch || d.lastStation != station[0].Station_JP); //最終列車表示設定
setSelectedTrain(data);
}, [trainTimeAndNumber, currentTrain, finalSwitch]);
const { width } = useWindowDimensions();
const adjustedWidth = width * 0.98;
return (
<View
style={{
width: adjustedWidth,
/* height: wp("98%")/10*9, */ backgroundColor: "#432",
borderWidth: 1,
margin: 10,
marginHorizontal: width * 0.01,
}}
>
<Header station={station[0]} />
{selectedTrain.map((d) => (
<EachData
{...{
d,
trainIDSwitch,
trainDescriptionSwitch,
navigate,
openStationACFromEachTrainInfo: () => {},
}}
station={station[0]}
key={d.train}
/>
))}
{areaInfo != "" && isInfoArea && (
<AreaDescription
numberOfLines={1}
areaInfo={areaInfo}
onClick={() => alert(areaInfo)}
/>
)}
<Footer
{...{
trainIDSwitch,
setTrainIDSwitch,
trainDescriptionSwitch,
setTrainDescriptionSwitch,
finalSwitch,
setFinalSwitch,
}}
/>
</View>
);
};

View File

@@ -197,7 +197,9 @@ export default function Sign(props) {
source={require("../../assets/StationSign.json")}
/>
)}
<StationNumberMaker {...{ currentStation: currentStationData }} />
<StationNumberMaker
{...{ currentStation: currentStationData, isMatsuyama }}
/>
<StationNameArea
{...{ currentStation: currentStationData, isMatsuyama }}
/>

View File

@@ -1,16 +1,10 @@
import React, { FC } from "react";
import React from "react";
import { Text, View } from "react-native";
import { useWindowDimensions } from "react-native";
import lineColorList from "@/assets/originData/lineColorList";
import { StationProps } from "@/lib/CommonTypes";
import lineColorList from "../../assets/originData/lineColorList";
type props = {
currentStation: StationProps[];
useEach?: boolean;
singleSize?: number;
};
export const StationNumberMaker: FC<props> = (props) => {
const { currentStation, useEach = false, singleSize } = props;
export const StationNumberMaker = (props) => {
const { currentStation, isMatsuyama } = props;
const { width } = useWindowDimensions();
const getTop = (array: number[], index: number) => {
if (array.length == 1) return 20;
@@ -18,7 +12,7 @@ export const StationNumberMaker: FC<props> = (props) => {
else if (index == 1) return 35;
else return 20;
};
return <>{currentStation
return currentStation
.filter((d) => (d.StationNumber ? true : false))
.map((d, index, array) => {
const lineID = d.StationNumber.slice(0, 1);
@@ -26,41 +20,29 @@ export const StationNumberMaker: FC<props> = (props) => {
return (
<View
style={{
position: "absolute",
alignContent: "center",
alignItems: "center",
top: `${getTop(array, index)}%`,
right: "10%",
width: (width / 100 * 10),
height: (width / 100 * 10),
borderColor: lineColorList[lineID],
backgroundColor: "white",
...(useEach ? {
width: singleSize,
height: singleSize,
borderWidth: parseInt("1%"),
borderRadius: parseInt("100%"),
} : {
width: (width / 100) * 10,
height: (width / 100) * 10,
borderWidth: parseInt("3%"),
borderRadius: parseInt("100%"),
position: "absolute",
top: `${getTop(array, index)}%`,
right: "10%"
})
}}
key={array[index].StationNumber}
>
<View style={{ flex: 1 }} />
<Text
style={{
fontSize: parseInt("13%"),
margin: 0,
padding: 0,
textAlign: "center",
color: "black",
color: "black",
fontWeight: "bold",
...(useEach ? {
fontSize: 6,//singleSize * 0.03,
}:{
fontSize: parseInt("13%"),
})
}}
>
{lineID + "\n" + lineName}
@@ -68,5 +50,5 @@ export const StationNumberMaker: FC<props> = (props) => {
<View style={{ flex: 1 }} />
</View>
);
})}</>
});
};

View File

@@ -1,58 +0,0 @@
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

@@ -21,27 +21,15 @@ export const findReversalPoints = (array, stopStationIDList) => {
}
// 駅間の場合
if (array.length == 2) {
const allThroughStation = stopStationIDList.map((d, index, arrays) => {
if (array[0] == "Y09" && array[1] == "M12") {
const allThroughStation = stopStationIDList.map((d) => {
if (
(array[0] == "M12" && array[1] == "Y09") ||
(array[0] == "Y09" && array[1] == "M12")
)
return d[0] == "M12" ? true : false;
} else if (array[0] == "M12" && array[1] == "Y09") {
if (index) {
if (arrays[index - 1][0] == "M12") {
return true;
}
}
return false;
} else if (array[0] == "U15" && array[1] == "U14") {
return d[0] == "U13" ? true : false;
} else if (array[0] == "S17" && array[1] == "U14") {
return d[0] == "U14" ? true : false;
}
let returndata = false;
d.forEach((x) => {
console.log(array, x, d);
if (array[0] < x && x < array[1]) {
returndata = true;
} else if (array[0] < x && x == array[1]) {

View File

@@ -8,9 +8,8 @@ export const searchSpecialTrain = (trainNum: string, trainList: any[]) => {
}
return false;
};
const returnBase = [];
if (search("D")) returnBase.push(searchBase + "D");
if (search("M")) returnBase.push(searchBase + "M");
if (search("D")) return searchBase + "D";
if (search("M")) return searchBase + "M";
//増結いしづちの場合
const baseStr = trainNum
@@ -22,7 +21,6 @@ export const searchSpecialTrain = (trainNum: string, trainList: any[]) => {
if (9000 < baseNum && baseNum < 9047) {
//いしづちの1001M-1046Mが9000番台になっている場合に発動
const TD = trainList[`${baseNum - 8000}M`];
if (TD) returnBase.push(`${baseNum - 8000}M`);
if (TD) return `${baseNum - 8000}M`;
}
return returnBase;
};

View File

@@ -1,31 +0,0 @@
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,49 +0,0 @@
import { trainTypeID } from "@/lib/CommonTypes";
type types = (types: trainTypeID, id: string) => [string, boolean, boolean];
export const getStringConfig: types = (type, id) => {
switch (type) {
case "Normal":
return ["普通", true, false];
case "OneMan":
return ["普通", true, true];
case "Rapid":
return ["快速", true, false];
case "OneManRapid":
return ["快速", true, true];
case "LTDEXP":
return ["特急", true, false];
case "NightLTDEXP":
return ["特急", true, false];
case "SPCL":
return ["臨時", true, false];
case "SPCL_Normal":
return ["臨時", true, false];
case "SPCL_Rapid":
return ["臨時快速", true, false];
case "SPCL_EXP":
return ["臨時特急", true, false];
case "Party":
return ["団体臨時", true, false];
case "Freight":
return ["貨物", false, false];
case "Forwarding":
return ["回送", false, false];
case "FreightForwarding":
return ["単機回送", false, false];
case "Other":
switch (true) {
case !!id.includes("T"):
return ["単機回送", false, false];
case !!id.includes("R"):
case !!id.includes("E"):
case !!id.includes("L"):
case !!id.includes("A"):
case !!id.includes("B"):
return ["回送", false, false];
case !!id.includes("H"):
return ["試運転", false, false];
}
return ["", false, false];
}
};

View File

@@ -1,18 +1,11 @@
import { trainTypeID } from "./CommonTypes";
export type colorString =
| "aqua"
| "#00a0bdff"
| "#007488ff"
| "red"
| "#297bff"
| "#ff7300ff"
| "#5f5f5fff"
| "#e000b0ff"
| "white"
| "black"
| "pink";
type nameString =
| "Rapid"
| "LTDEXP"
| "NightLTDEXP"
| "SPCL"
| "Normal"
| string;
type colorString = "aqua" | "red" | "#297bff" | "white" | "pink";
type trainTypeString =
| "快速"
| "特急"
@@ -20,191 +13,32 @@ type trainTypeString =
| "臨時"
| "普通列車"
| "普通列車(ワンマン)"
| "臨時快速"
| "臨時特急"
| "団体臨時"
| "貨物"
| "回送"
| "単機回送"
| "試運転"
| "その他";
type trainTypeDataString = "rapid" | "express" | "normal" | "notService";
type getTrainType = (e: {
type: trainTypeID;
id?: string;
whiteMode?: boolean;
}) => {
type trainTypeDataString = "rapid" | "express" | "normal";
type getTrainType = (d: nameString) => {
color: colorString;
name: trainTypeString;
shortName: string;
fontAvailable: boolean;
isOneMan: boolean;
data: trainTypeDataString;
};
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",
};
export const getTrainType: getTrainType = (nameString) => {
switch (nameString) {
case "Rapid":
return {
color: whiteMode ? "#00a0bdff" : "aqua",
name: "快速",
shortName: "快速",
fontAvailable: true,
isOneMan: false,
data: "rapid",
};
case "OneManRapid":
return {
color: whiteMode ? "#00a0bdff" : "aqua",
name: "快速",
shortName: "快速",
fontAvailable: true,
isOneMan: true,
data: "rapid",
};
return { color: "aqua", name: "快速", data: "rapid" };
case "LTDEXP":
return {
color: "red",
name: "特急",
shortName: "特急",
fontAvailable: true,
isOneMan: false,
data: "express",
};
return { color: "red", name: "特急", data: "express" };
case "NightLTDEXP":
return {
color: whiteMode ? "#e000b0ff" : "pink",
name: "寝台特急",
shortName: "特急",
fontAvailable: true,
isOneMan: false,
data: "express",
};
return { color: "pink", name: "寝台特急", data: "express" };
case "SPCL":
case "SPCL_Normal":
return {
color: "#297bff",
name: "臨時",
shortName: "臨時",
fontAvailable: true,
isOneMan: false,
data: "normal",
};
case "SPCL_Rapid":
return {
color: "#297bff",
name: "臨時快速",
shortName: "臨時快速",
fontAvailable: true,
isOneMan: false,
data: "normal",
};
case "SPCL_EXP":
return {
color: "#297bff",
name: "臨時特急",
shortName: "臨時特急",
fontAvailable: true,
isOneMan: false,
data: "normal",
};
case "Party":
return {
color: "#ff7300ff",
name: "団体臨時",
shortName: "団体臨時",
fontAvailable: true,
isOneMan: false,
data: "normal",
};
case "Freight":
return {
color: "#007488ff",
name: "貨物",
shortName: "貨物",
fontAvailable: false,
isOneMan: false,
data: "notService",
};
case "Forwarding":
return {
color: "#5f5f5fff",
name: "回送",
shortName: "回送",
fontAvailable: false,
isOneMan: false,
data: "notService",
};
case "FreightForwarding":
return {
color: "#5f5f5fff",
name: "単機回送",
shortName: "単機回送",
fontAvailable: false,
isOneMan: false,
data: "notService",
};
case "Other":
case "SPCL_Normal":
return { color: "#297bff", name: "臨時", data: "normal" };
case "OneMan":
return { color: "white", name: "普通列車(ワンマン)", data: "normal" };
case "Normal":
return { color: "white", name: "普通列車", data: "normal" };
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",
};
return { color: "white", name: "その他", data: "normal" };
}
};

View File

@@ -9,13 +9,30 @@ export const initIcon = (
tabBarBadge: string,
isInfo: boolean
) => {
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"} />
</>
);
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"}
/>
</>
);
}
};
type BadgeProps = { tabBarBadge: string; isInfo: boolean };
@@ -43,7 +60,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?: "入線" | number;
delay?: string | number;
num?: string;
};
type trainData = (

View File

@@ -1,107 +0,0 @@
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

@@ -24,8 +24,6 @@ export const useInterval = (fn: Fn, interval: number, autostart = true) => {
useEffect(() => {
if (autostart) {
setState("RUNNING");
}else{
setState("STOPPED");
}
}, [autostart]);
useEffect(() => {

View File

@@ -17,7 +17,6 @@ export const injectJavascriptData: InjectJavascriptData = (
mapSwitch != "true"
? `
document.querySelector('#header a').style.display = 'none';
document.querySelector('#main').style.left = '0px';
document.querySelector('#header').style.height = '50px';
document.querySelector('#main').style.paddingTop = '54px';
document.querySelector('#headerStr').style.display = 'none';
@@ -25,91 +24,50 @@ export const injectJavascriptData: InjectJavascriptData = (
: `
document.querySelector('.accordionClass').style.display = 'none';
document.querySelector('#header').style.display = 'none';
document.querySelector('#main').style.left = '0px';
document.querySelector('#main').style.paddingTop = '0px';
document.querySelector('#headerStr').style.display = 'none';
`;
// 上部ヘッダーの取り扱い、自動再読み込み、setStringsの実行
const bootData = `
// 起動時にブラウザにlodashを読み込むscript追加処理
const script = document.createElement('script');
script.src = "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js";
document.head.appendChild(script);
const script2 = document.createElement('link');
script2.rel = "stylesheet";
script2.href = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.0/css/all.min.css";
document.head.appendChild(script2);
let stationList = {};
fetch("https://n8n.haruk.in/webhook/jr-shikoku-station-list").then((response) => response.json()).then((data) => {
stationList = data;
}).then(()=>setReload());
});
let trainDataList = [];
const DatalistUpdate = () =>{
try{
fetch("https://n8n.haruk.in/webhook/jr-shikoku-position-custom-datalist").then((response) => response.json())
.then((data) => data[0].data)
.then((data) => {
if(!_.isEqual(data, trainDataList)) {
trainDataList = data;
setReload();
}
});
}catch(error){}
setTimeout(DatalistUpdate, 60000);
}
DatalistUpdate();
fetch("https://n8n.haruk.in/webhook/jr-shikoku-position-custom-datalist").then((response) => response.json()).then((data) => {
trainDataList = data[0].data;
}).then(()=>setReload());
let trainDiagramData2 = {};
const TrainDiagramData2Update = () =>{
try{
fetch("https://n8n.haruk.in/webhook/JR-shikoku-diagram-migrate-original")
.then((response) => response.json())
.then((res)=>res.data)
.then((res) => {
const data = {};
res.forEach((d) => {
const keys = Object.keys(d);
data[keys] = d[keys];
});
return data;
})
.then((data) => {
if(!_.isEqual(data, trainDiagramData2)) {
trainDiagramData2 = data;
setReload();
}
});
}catch(error){}
setTimeout(TrainDiagramData2Update, 60000);
}
TrainDiagramData2Update();
let probremsData = [];
const getProblemsData = () =>{
try{
fetch("https://n8n.haruk.in/webhook/jrshikoku-position-problems").then((response) => response.json()).then((data) => {
if(!_.isEqual(data, probremsData)) {
probremsData = data.data;
setReload();
}
fetch("https://n8n.haruk.in/webhook/JR-shikoku-diagram-migrate-original")
.then((response) => response.json())
.then((res)=>res.data)
.then((res) => {
const data = {};
res.forEach((d) => {
const keys = Object.keys(d);
data[keys] = d[keys];
});
}catch(error){}
setTimeout(getProblemsData, 30000);
}
getProblemsData();
return data;
})
.then((data) => {
trainDiagramData2 = data;
});
let probremsData = [];
fetch("https://n8n.haruk.in/webhook/jrshikoku-position-problems").then((response) => response.json()).then((data) => {
probremsData = data.data;
});
const setReload = () =>{
try{
document.getElementById('refreshIcon').click();
fetch("https://n8n.haruk.in/webhook/jrshikoku-position-problems").then((response) => response.json()).then((data) => {
probremsData = data.data;
});
setStrings();
}catch(error){}
};
setTimeout(setReload, 10000);
}
setReload();
`;
// 左か右かを判定してアイコンを設置する
const trainIcon = `
@@ -500,6 +458,432 @@ export const injectJavascriptData: InjectJavascriptData = (
case "8077":
return "https://storage.haruk.in/ef210a.png";
// // 普通列車系統、6000系運用
// //61運用
// case "1213M":
// case "1214M":
// case "143M":
// case "147M":
// //62運用
// case "114M":
// //961運用
// case "143M":
// case "147M":
// //962運用
// case "114M":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s6000p.png',hasProblem);
// break;
// // 土讃線普通列車系統(include ごな線)
// // ごな線
// case "5851D": //219D併結 [ToDo: 219Dとの分割対策]
// case "5854D":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/tosa9640jgr.png',hasProblem);
// break;
// //JR車両乗り入れ運用
// case "5858D":
// case "5869D":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s1000.png',hasProblem);
// break;
// //併結運用の併結される側 [ToDo: 分割対策]
// case "5845D":
// case "5851D":
// case "5818D":
// case "5820D":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/tosa9640.png',hasProblem);
// break;
// // 土讃線単体列車のキハ32運用
// case "715D":
// case "718D":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s32ns.png',hasProblem);
// break;
// // サンライズに伴う気動車代走
// case "6219D":
// case "6222D":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s1000.png',hasProblem);
// break;
// // それ以外の土讃線ごな線直通列車
// case "5811D":
// case "5813D":
// case "5815D":
// case "5817D":
// case "5843D":
// case "5853D":
// case "5855D":
// case "5859D":
// case "5861D":
// case "5865D":
// case "5881D":
// case "5885D":
// case "5889D":
// case "5812D":
// case "5814D":
// case "5816D":
// case "5852D":
// case "5856D":
// case "5860D":
// case "5862D":
// case "5872D":
// case "5874D":
// case "5876D":
// case "5880D":
// case "5882D":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/tosa9640.png',hasProblem);
// break;
// // それ以外の土讃線普通列車(1000)
// case "4210D":
// case "4212D":
// case "4214D":
// case "4218D":
// case "4220D":
// case "4222D":
// case "4224D":
// case "4226D":
// case "4228D":
// case "4230D":
// case "4232D":
// case "4234D":
// case "4236D":
// case "4238D":
// case "4240D":
// case "4242D":
// case "4244D":
// case "4250D":
// case "4252D":
// case "4254D":
// case "4256D":
// case "4211D":
// case "4221D":
// case "4223D":
// case "4225D":
// case "4227D":
// case "4229D":
// case "4231D":
// case "4235D":
// case "4237D":
// case "4239D":
// case "4241D":
// case "4245D":
// case "4247D":
// case "4249D":
// case "4251D":
// case "4253D":
// case "4255D":
// case "4257D":
// case "4259D":
// case "4261D":
// case "4710D":
// case "4726D":
// case "4730D":
// case "4732D":
// case "4734D":
// case "4738D":
// case "4740D":
// case "4742D":
// case "4744D":
// case "4746D":
// case "4752D":
// case "4756D":
// case "4762D":
// case "4764D":
// case "4766D":
// case "4711D":
// case "4713D":
// case "4723D":
// case "4725D":
// case "4727D":
// case "4729D":
// case "4731D":
// case "4737D":
// case "4739D":
// case "4745D":
// case "4753D":
// case "4755D":
// case "4759D":
// case "4761D":
// case "4763D":
// case "216D":
// case "238D":
// case "246D":
// case "248D":
// case "213D":
// case "215D":
// case "217D":
// case "219D":
// case "233D":
// case "243D":
// case "710D":
// case "712D":
// case "714D":
// case "716D":
// case "720D":
// case "722D":
// case "724D":
// case "728D":
// case "736D":
// case "748D":
// case "750D":
// case "754D":
// case "758D":
// case "760D":
// case "768D":
// case "717D":
// case "719D":
// case "721D":
// case "733D":
// case "735D":
// case "737D":
// case "741D":
// case "743D":
// case "747D":
// case "749D":
// case "751D":
// case "755D":
// case "757D":
// case "761D":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s1000.png',hasProblem);
// break;
// // 予讃線/土讃線普通列車運用(7000,7200)
// // 下り列車(伊予西条-松山は全て7000系)
// case "5519M":
// case "5525M":
// case "5215M":
// case "5103M":
// case "107M":
// case "1219M":
// case "5109M":
// case "6109M":
// case "5531M":
// case "1221M":
// case "5225M":
// case "5111M":
// case "1227M":
// case "115M":
// case "5229M":
// case "5117M":
// case "5119M":
// case "119M":
// case "5231M":
// case "4537M":
// case "5233M":
// case "123M":
// case "125M":
// case "5235M":
// case "5239M":
// case "5547M":
// case "129M":
// case "5241M":
// case "5133M":
// case "135M":
// case "1243M":
// case "137M":
// case "5139M":
// case "4559M":
// case "1245M":
// case "141M":
// case "1247M":
// case "5249M":
// case "145M":
// case "5253M":
// case "5149M":
// case "5255M":
// case "151M":
// case "5257M":
// case "153M":
// case "5259M":
// case "155M":
// case "1263M":
// case "157M":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s7200.png',hasProblem);
// break;
// // 下り7000系
// case "101M":
// case "4601M":
// case "4113M":
// case "121M":
// case "127M":
// case "131M":
// case "555M":
// case "4565M":
// case "159M":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s7000.png',hasProblem);
// break;
// // 上り列車 7200系
// case "5102M":
// case "104M":
// case "5210M":
// case "5108M":
// case "4108M":
// case "110M":
// case "112M":
// case "118M":
// case "5218M":
// case "5120M":
// case "5220M":
// case "5512M":
// case "1602M":
// case "1224M":
// case "5124M":
// case "5226M":
// case "5126M":
// case "5128M":
// case "1230M":
// case "4128M":
// case "130M":
// case "4522M":
// case "5232M":
// case "132M":
// case "5234M":
// case "136M":
// case "5236M":
// case "5140M":
// case "5238M":
// case "5240M":
// case "142M":
// case "4530M":
// case "144M":
// case "5242M":
// case "146M":
// case "5244M":
// case "4148M":
// case "1246M":
// case "150M":
// case "5538M":
// case "5152M":
// case "154M":
// case "156M":
// case "1252M":
// case "158M":
// case "4604M":
// case "548M":
// case "5254M":
// case "1606M":
// case "5160M":
// case "5256M":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s7200.png',hasProblem);
// break;
// // 上り7000系
// case "114M":
// case "122M":
// case "134M":
// case "4138M":
// case "138M":
// case "4542M":
// case "162M":
// case "4166M":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s7000.png',hasProblem);
// break;
// // 松山界隈気動車運用
// // 上り下りの概念アリ
// // キハ32 通常運用
// case "4625D":
// case "4916D":
// case "925D":
// case "4618D":
// case "4913D":
// case "4918D":
// case "4643D":
// case "4654D":
// case "4657D":
// case "4928D":
// case "4667D":
// case "653D":
// case "3621D":
// case "4818D":
// case "4821D":
// case "4824D":
// case "4813D":
// case "4664D":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s32s.png',hasProblem);
// break;
// // 河童うようよ号偶数
// case "4816D":
// case "4830D":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s32kpuy2.png',hasProblem);
// break;
// // 河童うようよ号奇数
// case "4827D":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s32kpuy1.png',hasProblem);
// break;
// // 新幹線偶数
// case "4810D":
// case "4822D":
// case "4826D":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s32tht.png',hasProblem);
// break;
// // 新幹線奇数
// case "4817D":
// case "4823D":
// case "4829D":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s32thtk.png',hasProblem);
// break;
// // キハ54 通常運用
// case "4632D":
// case "4634D":
// case "4921D":
// case "4926D":
// case "4927D":
// case "912D":
// case "4917D":
// case "4641D":
// case "4652D":
// case "4651D":
// case "4666D":
// case "4820D":
// case "4825D":
// case "4828D":
// case "4811D":
// case "4640D":
// case "622D":
// case "4633D":
// case "4920D":
// case "4637D":
// case "4648D":
// case "620D":
// case "4627D":
// case "4624D":
// case "4915D":
// case "4924D":
// case "4649D":
// case "4812D":
// case "4815D":
// case "4659D":
// case "4658D":
// case "4665D":
// case "4914D":
// case "4626D":
// case "4631D":
// case "4636D":
// case "4919D":
// case "4922D":
// case "4923D":
// case "4663D":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s54s.png',hasProblem);
// break;
// // 54しまんとろっこ
// case "4623D":
// case "8814D":
// case "8819D":
// case "4662D":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s54to0ys.png',hasProblem);
// break;
// // キハ185 通常運用
// case "911D":
// case "628D":
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s185cm.png',hasProblem);
// break;
// 伊予灘ものがたり 赤
case "8091D":
case "8093D":
@@ -621,12 +1005,54 @@ export const injectJavascriptData: InjectJavascriptData = (
} else if (new RegExp(/^9(5|6|7|8)\\dD$/).test(列番データ)) {
return "https://storage.haruk.in/s1500.png";
}
// 牟岐線普通列車系統 一旦閉鎖
// else if(new RegExp(/^(4|5)5\\d\\dD$/).test(列番データ)){
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s7200.png',hasProblem);
// break;
// }
// else if(new RegExp(/^5\\d\\dD$/).test(列番データ)){
// setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s7000.png',hasProblem);
// break;
// }
break;
}
}
`;
const normal_train_name = `
const getJRF = num =>{
switch(num){
case "71":
return "東京(タ)→高松(タ)";
case "73":
case "75":
return "大阪(タ)→高松(タ)";
case "3079":
return "高松(タ)→伊予三島";
case "3071":
case "3077":
return "高松(タ)→新居浜";
case "3073":
return "高松(タ)→松山貨物";
case "70":
return "高松(タ)→東京(タ)";
case "74":
case "76":
return "高松(タ)→大阪(タ)";
case "3078":
return "伊予三島→高松(タ)";
case "3070":
return "新居浜→高松(タ)";
case "3076":
return "新居浜→高松(タ)";
case "3072":
return "松山貨物→高松(タ)";
case "9070":
return "臨時貨物";
default:
return undefined;
}
}
const nameReplace = (列車名データ,列番データ,行き先情報,hasProblem,isLeft) =>{
let isWanman = false;
let trainName = "";
@@ -635,9 +1061,7 @@ export const injectJavascriptData: InjectJavascriptData = (
let viaData = "";
let ToData = "";
let TrainNumber = 列番データ;
let isEdit = false;
let isSeason = false;
let TrainNumberOverride;
try{
const diagram = trainDiagramData2[列番データ] || trainTimeInfo[列番データ];
if(diagram){
@@ -684,6 +1108,15 @@ export const injectJavascriptData: InjectJavascriptData = (
trainName = "臨時列車";
}
let JRF = true;
const JRFTemp = getJRF(列番データ);
if(JRFTemp){
trainName = JRFTemp;
JRF = false;
}
const getThrew = num =>{
switch(num){
@@ -784,6 +1217,30 @@ export const injectJavascriptData: InjectJavascriptData = (
viaData = "ごめん・なはり線[快速]";
ToData = "(後免にて解結)\\n土佐山田/奈半利";
break;
case "9395D":
viaData = "[臨時]普通";
ToData = "三本松";
break;
case "9174M":
viaData = "[臨時]マリンライナー94号";
ToData = "岡山";
break;
case "9662D":
viaData = "[臨時]れんげ号";
ToData = "八幡浜";
break;
case "9665D":
viaData = "[臨時]れんげ号";
ToData = "宇和島";
break;
case "9664D":
viaData = "[臨時]わらぐろ号";
ToData = "八幡浜";
break;
case "9663D":
viaData = "[臨時]わらぐろ号";
ToData = "卯之町";
break;
default:
if(new RegExp(/^58[1-3][1,3,5,7,9][DM]$/).test(列番データ)){
viaData = "ごめん・なはり線[快速]";
@@ -808,80 +1265,44 @@ export const injectJavascriptData: InjectJavascriptData = (
getThrew(列番データ);
if(trainDataList.find(e => e.id === 列番データ) !== undefined){
const data = trainDataList.find(e => e.id === 列番データ);
//{id,trainName,viaData,ToData,TrainNumber,TrainNumberOverride,type,infoUrl,trainNumDistance,info,infogram,isEdit}
switch(data.type){
case "Normal":
trainTypeColor = "black";
isWanman = false;
trainType = "普通";
break;
case "OneMan":
trainTypeColor = "black";
isWanman = true;
trainType = "普通";
break;
case "Rapid":
trainTypeColor = "rgba(0, 140, 255, 1)";
isWanman = false;
trainType = "快速";
break;
case "OneManRapid":
trainTypeColor = "rgba(0, 140, 255, 1)";
isWanman = true;
trainType = "快速";
break;
case "LTDEXP":
trainTypeColor = "red";
isWanman = false;
trainType = "特急";
break;
case "NightLTDEXP":
trainTypeColor = "#d300b0ff";
isWanman = false;
trainType = "寝台特急";
break;
case "SPCL":
case "SPCL_Normal":
trainTypeColor = "#008d07ff";
isWanman = false;
trainType = "臨時";
break;
case "SPCL_Rapid":
trainTypeColor = "rgba(0, 81, 255, 1)";
isWanman = false;
trainType = "臨時快速";
break;
case "SPCL_EXP":
trainTypeColor = "#a52e2eff";
isWanman = false;
trainType = "臨時特急";
break;
case "Party":
trainTypeColor = "#ff7300ff";
isWanman = false;
trainType = "団体臨時";
break;
case "Freight":
trainTypeColor = "#00869ecc";
isWanman = false;
trainType = "貨物";
break;
case "Forwarding":
trainTypeColor = "#727272cc";
isWanman = false;
trainType = "回送";
break;
case "FreightForwarding":
trainTypeColor = "#727272cc";
isWanman = false;
trainType = "単機回送";
break;
default:
break;
}
isEdit = data.isEdit;
isSeason = data.isSeason;
//{id,isWanman,trainName,viaData,ToData,TrainNumber,JRF,type,infoUrl,trainNumDistance,info,infogram}
trainType = (()=>{
switch(data.type){
case "Normal":
trainTypeColor = "black";
return "普通";
case "OneMan":
trainTypeColor = "black";
return "普通";
case "Freight":
trainTypeColor = "black";
return "貨物";
case "SPCL_Normal":
trainTypeColor = "#297bff";
return "臨時";
case "SPCL_Rapid":
trainTypeColor = "#297bff";
return "臨時快速";
case "SPCL_LTDEXP":
trainTypeColor = "#297bff";
return "臨時特急";
case "LTDEXP":
trainTypeColor = "red";
return "特急";
case "NightLTDEXP":
trainTypeColor = "rgb(211, 0, 176)";
return "寝台特急";
case "OneManRapid":
trainTypeColor = "rgba(0, 140, 255, 1)";
return "快速";
case "Rapid":
trainTypeColor = "rgba(0, 140, 255, 1)";
return "快速";
default:
return "";
}
})();
isWanman = data.isWanman;
if(data.trainName != ""){
trainName = data.trainName;
if(data.trainNumDistance != null){
@@ -894,12 +1315,10 @@ export const injectJavascriptData: InjectJavascriptData = (
if(data.ToData != ""){
ToData = data.ToData;
}
if(data.TrainNumberOverride){
TrainNumberOverride = data.TrainNumberOverride;
}
}
//列番付与
const returnText1 = (isWanman ? "ワンマン " : "") + trainName + viaData;
const returnText2 = (ToData ? ToData+"行 " : ToData)+ TrainNumber;
行き先情報.innerText = "";
${uiSetting === "tokyo" ? `
let stationIDs = [];
@@ -918,38 +1337,19 @@ export const injectJavascriptData: InjectJavascriptData = (
getColors = stationLines.map(e => GetLineBarColor(e));
}
let yosan2Color = undefined;
switch(viaData){
case "(内子経由)":
yosan2Color = "#F5AC13";
break;
case "(海経由)":
yosan2Color = "#9AA7D7";
break;
case "牟岐線直通":
yosan2Color = "#00b8bb";
break;
case "徳島線直通":
yosan2Color = "#2d506e";
break;
case "高徳線直通":
yosan2Color = "#87CA3B";
break;
case "鳴門線直通":
yosan2Color = "#881F61";
break;
case "予土線":
yosan2Color = "#008a5a";
break;
default:
break;
if(viaData == "(内子経由)"){
yosan2Color ="#F5AC13";
}
else if(viaData == "(海経由)"){
yosan2Color = "#9AA7D7";
}
const gradient = getColors.length > 1 ? "linear-gradient(130deg, " + getColors[0] + " 0%, "+ getColors[0]+"50%, "+ getColors[1]+"50%, " + getColors[1] + " 100%)" : getColors[0];
行き先情報.insertAdjacentHTML('beforebegin', "<div style='width:100%;display:flex;flex:1;flex-direction:"+(isLeft ? "column-reverse" : "column") + ";'>" + ( isEdit ? "<div style='position:absolute;"+ (isLeft ? "right" : "left") + ":0;"+ (isLeft ? "bottom" : "top") + ":0;background-color:#00b8bb;border-radius:15px;padding:0px;padding-left:4px;padding-right:4px;'><i class='fa-solid fa-user-group fa-sm' style='color:white;width:100%;height:100%;'></i></div>" : isSeason ? "<div style='position:absolute;"+ (isLeft ? "right" : "left") + ":0;"+ (isLeft ? "bottom" : "top") + ":0;background-color:#00b8bb;border-radius:15px;padding:0px;padding-left:4px;padding-right:4px;'><i class='fa-solid fa-calendar fa-sm' style='color:white;width:100%;height:100%;'></i></div>" : "") + "<p style='font-size:6px;padding:0;color:black;text-align:center;'>" + (TrainNumberOverride ? TrainNumberOverride : TrainNumber) + "</p><div style='flex:1;'></div><p style='font-size:8px;font-weight:bold;padding:0;color: black;text-align:center;'>" + (isWanman ? "ワンマン " : "") + "</p><p style='font-size:6px;font-weight:bold;padding:0;color: black;text-align:center;border-style:solid;border-width: "+(!!yosan2Color ? "2px" : "0px")+";border-color:" + yosan2Color + "'>" + viaData + "</p><p style='font-size:8px;font-weight:bold;padding:0;color: black;text-align:center;'>" + trainName + "</p><div style='width:100%;background:" + gradient + ";'><p style='font-size:10px;font-weight:bold;padding:0;margin:0;color:white;align-items:center;align-content:center;text-align:center;text-shadow:1px 1px 0px #00000030, -1px -1px 0px #00000030,-1px 1px 0px #00000030, 1px -1px 0px #00000030,1px 0px 0px #00000030, -1px 0px 0px #00000030,0px 1px 0px #00000030, 0px -1px 0px #00000030;'>" + (ToData ? ToData + "行" : ToData) + "</p></div><div style='width:100%;background:" + trainTypeColor + ";border-radius:"+(isLeft ? "4px 4px 0 0" : "0 0 4px 4px")+";'><p style='font-size:10px;font-weight:bold;font-style:italic;padding:0;color: white;text-align:center;'>" + trainType + "</p></div><p style='font-size:8px;font-weight:bold;padding:0;text-align:center;color: "+(hasProblem ? "red":"black")+";'>" + (hasProblem ? "‼️停止中‼️" : "") + "</p></div>");
行き先情報.insertAdjacentHTML('beforebegin', "<div style='width:100%;display:flex;flex:1;flex-direction:"+(isLeft ? "column-reverse" : "column") + ";'><p style='font-size:6px;padding:0;color:black;text-align:center;'>" + TrainNumber + (JRF ? "":"レ") + "</p><div style='flex:1;'></div><p style='font-size:8px;font-weight:bold;padding:0;color: black;text-align:center;'>" + (isWanman ? "ワンマン " : "") + "</p><p style='font-size:6px;font-weight:bold;padding:0;color: black;text-align:center;border-style:solid;border-width: "+(!!yosan2Color ? "2px" : "0px")+";border-color:" + yosan2Color + "'>" + viaData + "</p><p style='font-size:8px;font-weight:bold;padding:0;color: black;text-align:center;'>" + trainName + "</p><div style='width:100%;background:" + gradient + ";'><p style='font-size:10px;font-weight:bold;padding:0;margin:0;color:white;align-items:center;align-content:center;text-align:center;text-shadow:1px 1px 0px #00000030, -1px -1px 0px #00000030,-1px 1px 0px #00000030, 1px -1px 0px #00000030,1px 0px 0px #00000030, -1px 0px 0px #00000030,0px 1px 0px #00000030, 0px -1px 0px #00000030;'>" + (ToData ? ToData + "行" : ToData) + "</p></div><div style='width:100%;background:" + trainTypeColor + ";border-radius:"+(isLeft ? "4px 4px 0 0" : "0 0 4px 4px")+";'><p style='font-size:10px;font-weight:bold;font-style:italic;padding:0;color: white;text-align:center;'>" + trainType + "</p></div><p style='font-size:8px;font-weight:bold;padding:0;text-align:center;color: "+(hasProblem ? "red":"black")+";'>" + (hasProblem ? "‼️停止中‼️" : "") + "</p></div>");
`: `
行き先情報.insertAdjacentHTML('beforebegin', "<p style='font-size:10px;font-weight:bold;padding:0;color: black;'>" + returnText1 + "</p>");
行き先情報.insertAdjacentHTML('beforebegin', "<div style='display:inline-flex;flex-direction:row;'><p style='font-size:10px;font-weight: bold;padding:0;color:black;'>" + (ToData ? ToData + "行 " : ToData) + "</p><p style='font-size:10px;padding:0;color:black;'>" + (TrainNumberOverride ? TrainNumberOverride : TrainNumber) + "</p></div>");
行き先情報.insertAdjacentHTML('beforebegin', "<div style='display:inline-flex;flex-direction:row;'><p style='font-size:10px;font-weight: bold;padding:0;color:black;'>" + (ToData ? ToData + "行 " : ToData) + "</p><p style='font-size:10px;padding:0;color:black;'>" + TrainNumber + (JRF ? "":"レ") + "</p></div>");
行き先情報.insertAdjacentHTML('beforebegin', "<p style='font-size:10px;font-weight:bold;padding:0;color: "+(hasProblem ? "red":"black")+";'>" + (hasProblem ? "‼️停止中‼️" : "") + "</p>");
`}
}
@@ -959,81 +1359,34 @@ export const injectJavascriptData: InjectJavascriptData = (
`
const setNewTrainItem = (element,hasProblem,type)=>{
const setNewTrainItem = (element,hasProblem)=>{
var 列番データ = element.getAttribute('offclick').split('"')[1];
if(trainDataList.find(e => e.id === 列番データ) !== undefined){
const data = trainDataList.find(e => e.id === 列番データ);
switch (data.type) {
case "Normal":
element.style.borderColor = "black";
element.style.backgroundColor = '#ffffffcc';
break;
case "OneMan":
element.style.borderColor = "black";
element.style.backgroundColor = '#ffffffcc';
break;
case "Rapid":
element.style.borderColor = "rgba(0, 140, 255, 1)";
element.style.backgroundColor = '#ffffffcc';
break;
case "OneManRapid":
element.style.borderColor = "rgba(0, 140, 255, 1)";
element.style.backgroundColor = '#ffffffcc';
break;
case "LTDEXP":
element.style.borderColor = "red";
element.style.backgroundColor = '#ffffffcc';
break;
case "NightLTDEXP":
element.style.borderColor = "#d300b0ff";
element.style.backgroundColor = '#ffffffcc';
break;
case "SPCL":
case "SPCL_Normal":
element.style.borderColor = "#008d07ff";
element.style.backgroundColor = '#ffffffcc';
break;
case "SPCL_Rapid":
element.style.borderColor = "#0051ffff";
element.style.backgroundColor = '#ffffffcc';
break;
case "SPCL_EXP":
element.style.borderColor = "#a52e2eff";
element.style.backgroundColor = '#ffffffcc';
break;
case "Party":
element.style.borderColor = "#ff7300ff";
element.style.backgroundColor = '#ffd0a9ff';
break;
case "Freight":
element.style.borderColor = "#00869ecc";
element.style.backgroundColor = '#c7c7c7cc';
break;
case "Forwarding":
element.style.borderColor = "#727272cc";
element.style.backgroundColor = '#c7c7c7cc';
break;
case "FreightForwarding":
element.style.borderColor = "#727272cc";
element.style.backgroundColor = '#c7c7c7cc';
break;
default:
element.style.borderColor = 'black';
element.style.backgroundColor = '#ffffffcc';
break;
}
const JRFTemp = getJRF(列番データ);
if(element.getAttribute('offclick').includes("express")){
element.style.borderColor = 'rgba(255, 0, 0, 1)';
}else if(element.getAttribute('offclick').includes("rapid")){
element.style.borderColor = 'rgba(0, 140, 255, 1)';
}else if(JRFTemp){
element.style.borderColor = 'rgba(0, 134, 158, 0.8)';
}else{
if(element.getAttribute('offclick').includes("express")){
element.style.borderColor = '#ff0000ff';
}else if(element.getAttribute('offclick').includes("rapid")){
element.style.borderColor = '#008cffff';
}else{
element.style.borderColor = 'black';
}
element.style.borderColor = 'black';
}
element.style.borderWidth = '2px';
element.style.borderStyle = 'solid';
element.style.borderRadius = '10%';
switch(true){
case 列番データ.indexOf("H") != -1:
case 列番データ.indexOf("R") != -1:
case 列番データ.indexOf("E") != -1:
case 列番データ.indexOf("A") != -1:
case 列番データ.indexOf("B") != -1:
case !!JRFTemp:
element.style.backgroundColor = 'rgba(199, 199, 199, 0.8)';
break;
default:
element.style.backgroundColor = 'rgba(255, 255, 255, 0.8)';
break;
}
if(hasProblem){
element.style.boxShadow = '0 0 10px rgba(255, 0, 0, 0.9)';
}else{
@@ -1096,13 +1449,10 @@ const setStrings = () =>{
i.style.position = "unset";
i.style.display = "flex";
i.style.flexDirection = "column";
i.style.alignItems = "center";
i.style.justifyContent = "center";
i.style.flex = "1";
i.style.backgroundColor = "#00000000";
i.querySelectorAll(":scope > *").forEach(j=>{
j.style.display = "flex";
j.style.flex = "1";
j.style.width = "100%";
j.style.textAlign = "center";
j.style.margin = "5px";
j.style.padding = "5px";

View File

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

View File

@@ -1,19 +1,12 @@
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';
@@ -23,20 +16,6 @@ document.querySelector('.map').style.display = 'block';
document.querySelector('.map').style.marginLeft = '-5px';
document.querySelector('.map').style.marginTop = '0px';
document.querySelector('.pageInformation h1.accent span').style.width = '100%';
document.querySelector('.delay_status').style.width = 'calc(100vw - 4px)';
document.querySelector('.reload').style.width = '100vw';
document.querySelector('.delay_info').style.width = '100vw';
document.querySelector('.related_lnk').style.width = '100%';
document.querySelector('.related_lnk').style.padding = '0px';
document.querySelector('.related_lnk .ttl').style.padding = '20px';
document.querySelector('.related_lnk dl.lnk_item').style.float = 'none';
document.querySelector('.related_lnk dl.lnk_item').style.overflow = 'visible';
document.querySelector('.related_lnk dl.lnk_item').style.width = '100%';
document.querySelectorAll('.attention').forEach((el) => {
el.style.width = '100vw';
});
document.querySelector('.mapbase > img').style.width = '100vw';
document.querySelector('.ml_station > img').style.width = '100vw';
@@ -107,23 +86,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={{
@@ -154,7 +133,7 @@ setInterval(() => {
}
const ReloadButton = ({ onPress, top, LoadError = false }) => {
const styles: StyleProp<ViewStyle> = {
const styles:StyleProp<ViewStyle> = {
position: "absolute",
top,
right: 10,

View File

@@ -0,0 +1,70 @@
import trainList from "@/assets/originData/trainList";
import { AS } from "@/storageControl";
import React, { createContext, useContext, useEffect, useState } from "react";
const initialState = {
allTrainDiagram: undefined,
setAllTrainDiagram: () => {},
allCustonTrainData: [],
};
const AllTrainDiagramContext = createContext(initialState);
export const useAllTrainDiagram = () => useContext(AllTrainDiagramContext);
export const AllTrainDiagramProvider = ({ children }) => {
const [allTrainDiagram, setAllTrainDiagram] = useState(trainList);
const [allCustonTrainData, setAllCustonTrainData] = useState([]); // カスタム列車データ
const [keyList, setKeyList] = useState(); // 第二要素
useEffect(
() => allTrainDiagram && setKeyList(Object.keys(allTrainDiagram)),
[allTrainDiagram]
);
useEffect(() => {
fetch("https://n8n.haruk.in/webhook/JR-shikoku-diagram-migrate-original")
.then((res) => res.json())
.then((res) => res.data)
.then((res) => {
const data = {};
res.forEach((d) => {
const keys = Object.keys(d);
data[keys] = d[keys];
});
return data;
})
.then((res) => {
setAllTrainDiagram(res);
AS.setItem("allTrainDiagram", JSON.stringify(res));
})
.catch((d) => {
AS.getItem("allTrainDiagram")
.then((d) => setAllTrainDiagram(JSON.parse(d)))
.catch(() => {
alert("初回の路線情報の取得に失敗しました。");
});
});
}, []);
useEffect(() => {
// カスタム列車データの取得
fetch("https://n8n.haruk.in/webhook/jr-shikoku-position-custom-datalist")
.then((res) => res.json())
.then((res) => {
setAllCustonTrainData(res[0].data);
})
.catch(() => {
alert("カスタム列車データの取得に失敗しました。");
});
}, []);
return (
<AllTrainDiagramContext.Provider
value={{
allTrainDiagram,
setAllTrainDiagram,
allCustonTrainData,
keyList,
}}
>
{children}
</AllTrainDiagramContext.Provider>
);
};

View File

@@ -1,98 +0,0 @@
import trainList from "@/assets/originData/trainList";
import useInterval from "@/lib/useInterval";
import { AS } from "@/storageControl";
import React, { createContext, FC, useContext, useEffect, useState } from "react";
const initialState = {
allTrainDiagram: {},
setAllTrainDiagram: (e) => {},
allCustomTrainData: [],
keyList: [],
};
type initialStateType = {
allTrainDiagram: { [key: string]: string };
setAllTrainDiagram: (e) => void;
allCustomTrainData: any[];
keyList: string[];
};
const AllTrainDiagramContext = createContext<initialStateType>(initialState);
export const useAllTrainDiagram = () => useContext(AllTrainDiagramContext);
type Props = {
children: React.ReactNode;
};
export const AllTrainDiagramProvider:FC<Props> = ({ children }) => {
const [allTrainDiagram, setAllTrainDiagram] = useState(trainList);
const [allCustomTrainData, setAllCustomTrainData] = useState([]); // カスタム列車データ
const [keyList, setKeyList] = useState<string[]>([]); // 第二要素
useEffect(() => {
if (allTrainDiagram && Object.keys(allTrainDiagram).length > 0)
setKeyList(Object.keys(allTrainDiagram));
else setKeyList([]);
}, [allTrainDiagram]);
const getTrainDiagram = () =>
fetch("https://n8n.haruk.in/webhook/JR-shikoku-diagram-migrate-original")
.then((res) => res.json())
.then((res) => res.data)
.then((res) => {
const data = {};
res.forEach((d) => {
const keys = Object.keys(d)[0];
data[keys] = d[keys];
});
//dataのkeyで並び替え
const sortedData = Object.keys(data)
.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:any) => {
setAllTrainDiagram(res);
AS.setItem("allTrainDiagram", JSON.stringify(res));
})
.catch((d) => {
AS.getItem("allTrainDiagram")
.then((d) => setAllTrainDiagram(JSON.parse(d)))
.catch(() => {
alert("初回の路線情報の取得に失敗しました。");
});
});
useEffect(() => {
getTrainDiagram();
}, []);
useInterval(getTrainDiagram, 30000); //30秒毎に全在線列車取得
const getCustomTrainData = () => {
fetch("https://n8n.haruk.in/webhook/jr-shikoku-position-custom-datalist")
.then((res) => res.json())
.then((res) => {
setAllCustomTrainData(res[0].data);
})
.catch(() => {
alert("カスタム列車データの取得に失敗しました。");
});
};
useEffect(() => {
// カスタム列車データの取得
getCustomTrainData();
}, []);
useInterval(getCustomTrainData, 30000); // 30秒毎にカスタム列車データ取得
return (
<AllTrainDiagramContext.Provider
value={{
allTrainDiagram,
setAllTrainDiagram,
allCustomTrainData,
keyList,
}}
>
{children}
</AllTrainDiagramContext.Provider>
);
};

View File

@@ -1,12 +1,19 @@
import React, {
createContext,
useContext,
useState,
useEffect,
FC,
} from "react";
import React, { createContext, useContext, useState, useEffect } 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",
@@ -333,30 +340,7 @@ const areaStationPair = {
yodo: { id: "G", stationID: yodoStationID },
};
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 }) => {
export const AreaInfoProvider = ({ children }) => {
const [areaInfo, setAreaInfo] = useState("");
const [areaIconBadgeText, setAreaIconBadgeText] = useState("");
const [areaStationID, setAreaStationID] = useState([]);
@@ -394,9 +378,7 @@ export const AreaInfoProvider: FC<props> = ({ children }) => {
);
});
};
useEffect(() => {
getAreaData();
}, []);
useEffect(getAreaData, []);
useInterval(getAreaData, 60000); //60秒毎に全在線列車取得
return (
<AreaInfoContext.Provider

View File

@@ -1,19 +1,13 @@
import React, {
createContext,
useContext,
useState,
useEffect,
FC,
} from "react";
import React, { createContext, useContext, useState, useEffect } from "react";
import { AS } from "../storageControl";
import { useAllTrainDiagram } from "./useAllTrainDiagram";
const initialState = {
busAndTrainData: [],
setBusAndTrainData: (e) => {},
setBusAndTrainData: () => {},
trainPairData: [],
setTrainPairData: (e) => {},
initializeTrainPairList: (e) => {},
getInfluencedTrainData: (e) => {},
setTrainPairData: () => {},
initializeTrainPairList: () => {},
getInfluencedTrainData: () => {},
};
const BusAndTrainDataContext = createContext(initialState);
@@ -21,17 +15,11 @@ const BusAndTrainDataContext = createContext(initialState);
export const useBusAndTrainData = () => {
return useContext(BusAndTrainDataContext);
};
type props = { children: React.ReactNode };
export const BusAndTrainDataProvider: FC<props> = ({ children }) => {
export const BusAndTrainDataProvider = ({ children }) => {
const { allTrainDiagram } = useAllTrainDiagram();
const [busAndTrainData, setBusAndTrainData] = useState<
{
address: string;
name: string;
type: "station-data" | "bus-stop" | "train-info";
}[]
>([]);
const [trainPairData, setTrainPairData] = useState<any[]>([]);
const [busAndTrainData, setBusAndTrainData] = useState([]);
const [trainPairData, setTrainPairData] = useState([]);
useEffect(() => {
AS.getItem("busAndTrain202403")
.then((d) => {
@@ -65,7 +53,7 @@ export const BusAndTrainDataProvider: FC<props> = ({ children }) => {
});
return trainPairList;
};
const getInfluencedTrainData = (trainNum: string) => {
const getInfluencedTrainData = (trainNum) => {
const trainPairList = initializeTrainPairList();
// 9253M ラマル
@@ -113,6 +101,9 @@ export const BusAndTrainDataProvider: FC<props> = ({ children }) => {
case "4452D":
returnArray.push("4545D");
break;
case "4456D":
returnArray.push("4549D");
break;
case "4466D":
returnArray.push("561D");
break;
@@ -153,6 +144,9 @@ export const BusAndTrainDataProvider: FC<props> = ({ children }) => {
case "4545D":
returnArray.push("4452D");
break;
case "4549D":
returnArray.push("4456D");
break;
case "561D":
returnArray.push("4466D");
break;
@@ -284,18 +278,6 @@ export const BusAndTrainDataProvider: FC<props> = ({ children }) => {
case "4368D":
returnArray.push("576D");
break;
case "3710D":
returnArray.push("710D");
break;
case "710D":
returnArray.push("3710D");
break;
case "3751D":
returnArray.push("751D");
break;
case "751D":
returnArray.push("3751D");
break;
}
if (new RegExp(/^4[1-9]\d\d[DM]$/).test(trainNum)) {
if (allTrainDiagram["5" + trainNum.substring(1)])

View File

@@ -0,0 +1,94 @@
import React, {
createContext,
useContext,
useState,
useEffect,
useRef,
} from "react";
import { HeaderConfig } from "../lib/HeaderConfig";
import useInterval from "../lib/useInterval";
const initialState = {
webview: {},
currentTrain: [],
setCurrentTrain: () => {},
currentTrainLoading: "loading",
setCurrentTrainLoading: () => {},
getCurrentTrain: () => {},
inject: (i) => {},
};
const CurrentTrainContext = createContext(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
const getCurrentTrain = () => {
fetch("https://n8n.haruk.in/webhook/c501550c-7d1b-4e50-927b-4429fe18931a")
.then((response) => response.json())
.then((d) => d.data)
.then((d) =>
d.map((x) => ({
Index: x.Index,
num: x.TrainNum,
delay: x.delay,
Pos: x.Pos,
PosNum: x.PosNum,
Direction: x.Direction,
Type: x.Type,
Line: x.Line,
}))
)
.then((d) => {
setCurrentTrain(d);
setCurrentTrainLoading("success");
})
.catch(() => {
//alert("現在の全在線列車取得エラー/再取得します");
fetch(
"https://script.google.com/macros/s/AKfycby9Y2-Bm75J_WkbZimi7iS8v5r9wMa9wtzpdwES9sOGF4i6HIYEJOM60W6gM1gXzt1o/exec",
HeaderConfig
)
.then((response) => response.json())
.then((d) =>
d.map((x) => ({ num: x.TrainNum, delay: x.delay, Pos: x.Pos }))
)
.then((d) => {
setCurrentTrain(d);
setCurrentTrainLoading("success");
})
.catch(() => {
// エラー時の処理
setCurrentTrainLoading("error");
});
});
};
const inject = (i) => {
webview.current?.injectJavaScript(i);
};
useEffect(getCurrentTrain, []); //初回だけ現在の全在線列車取得
useInterval(getCurrentTrain, 15000); //15秒毎に全在線列車取得
const webview = useRef();
return (
<CurrentTrainContext.Provider
value={{
webview,
currentTrain,
setCurrentTrain,
currentTrainLoading,
setCurrentTrainLoading,
getCurrentTrain,
inject,
}}
>
{children}
</CurrentTrainContext.Provider>
);
};

View File

@@ -1,292 +0,0 @@
import React, {
createContext,
useContext,
useState,
useEffect,
useRef,
FC,
} from "react";
import { HeaderConfig } from "@/lib/HeaderConfig";
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: undefined,
currentTrain: [],
setCurrentTrain: (e) => {},
currentTrainLoading: "loading" as loading,
setCurrentTrainLoading: (e) => {},
getCurrentTrain: () => {},
inject: (i) => {},
fixedPosition: null,
setFixedPosition: (e) => {},
setInjectData: (e) => {},
getCurrentStationData: ((e) => {}) as (
e: string
) => trainDataType | undefined,
getPosition: ((e) => {}) as (e: trainDataType) => string[] | undefined,
};
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);
};
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<{
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]
);
inject(script);
} else {
inject(`setReload()`);
}
}, 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;
if (currentTrainData?.Pos.match("")) {
const pos = currentTrainData?.Pos.replace("(下り)", "")
.replace("(上り)", "")
.replace("(徳島線)", "")
.replace("(高徳線)", "")
.replace("(坂出方)", "")
.replace("(児島方)", "")
.split("");
const direction = currentTrainData?.Direction || 0;
if (pos[0] == "児島" && pos[1] == "宇多津") {
if (direction == 0) {
return ["Y09", "M12"];
} else {
return ["M12", "Y09"];
}
} else if (pos[1] == "児島" && pos[0] == "宇多津") {
return ["Y09", "M12"];
} else if (pos[0] == "伊予若宮" && pos[1] == "伊予白滝") {
return ["S18", "S14"];
} else if (pos[0] == "伊予白滝" && pos[1] == "伊予若宮") {
return ["S14", "S18"];
} else if (pos[0] == "伊予大洲" && pos[1] == "伊予若宮") {
return ["U14", "+Iyo"];
} else if (pos[0] == "伊予若宮" && pos[1] == "伊予大洲") {
return ["-Iyo", "U14"];
}
const currentPosID = Object.keys(originalStationList).map((key) => {
let firstStation = false;
let firstStationID = "";
let secondStation = false;
let secondStationID = "";
originalStationList[key].forEach((station: StationProps) => {
if (station.Station_JP === pos[0]) {
firstStation = true;
firstStationID = station.StationNumber;
}
if (station.Station_JP === pos[1]) {
secondStation = true;
secondStationID = station.StationNumber;
}
});
if (firstStation && secondStation) {
return [firstStationID, secondStationID];
} else return false;
});
const currentPos = currentPosID.filter((d) => d != false)[0];
if (currentPos) {
return direction == 0 ? currentPos.reverse() : currentPos;
} else if (direction == 0) {
return [
getStationID(pos[1], stationList),
getStationID(pos[0], stationList),
];
} else {
return [
getStationID(pos[0], stationList),
getStationID(pos[1], stationList),
];
}
} else {
return [getStationID(currentTrainData?.Pos, stationList)];
}
};
type getCurrentStationDataFunc = (e: string) => trainDataType | undefined;
const getCurrentStationData: getCurrentStationDataFunc = (e) => {
//e:trainNumber
if (!currentTrain.length) return;
return checkDuplicateTrainData(
currentTrain.filter((d) => d.num == e),
stationList
);
};
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 });
}
};
const getCurrentTrain = () => {
fetch("https://n8n.haruk.in/webhook/c501550c-7d1b-4e50-927b-4429fe18931a")
.then((response) => response.json())
.then((d) => d.data)
.then((d) =>
d.map((x) => ({
Index: x.Index,
num: x.TrainNum,
delay: x.delay,
Pos: x.Pos,
PosNum: x.PosNum,
Direction: x.Direction,
Type: x.Type,
Line: x.Line,
}))
)
.then((d) => {
setCurrentTrain(d);
setCurrentTrainLoading("success");
})
.catch(() => {
//alert("現在の全在線列車取得エラー/再取得します");
fetch(
"https://script.google.com/macros/s/AKfycby9Y2-Bm75J_WkbZimi7iS8v5r9wMa9wtzpdwES9sOGF4i6HIYEJOM60W6gM1gXzt1o/exec",
HeaderConfig
)
.then((response) => response.json())
.then((d) =>
d.map((x) => ({ num: x.TrainNum, delay: x.delay, Pos: x.Pos }))
)
.then((d) => {
setCurrentTrain(d);
setCurrentTrainLoading("success");
})
.catch(() => {
// エラー時の処理
setCurrentTrainLoading("error");
});
});
};
const inject = (i) => {
webview.current?.injectJavaScript(i);
};
useEffect(() => {
getCurrentTrain();
}, []); //初回だけ現在の全在線列車取得
const [_0, _1] = useInterval(() => {
getCurrentTrain();
}, 10000); //10秒毎に全在線列車取得
return (
<CurrentTrainContext.Provider
value={{
webview,
currentTrain,
setCurrentTrain,
currentTrainLoading,
setCurrentTrainLoading,
getCurrentTrain,
inject,
setInjectData,
getCurrentStationData,
getPosition,
fixedPosition,
setFixedPosition,
}}
>
{children}
</CurrentTrainContext.Provider>
);
};

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: (e) => {} };
const initialState = { isLandscape: false, setIsLandscape: () => {} };
const DeviceOrientationChange = createContext(initialState);
@@ -18,8 +18,8 @@ export const DeviceOrientationChangeProvider = ({ children }) => {
);
};
useEffect(() => {
//data();
ScreenOrientation.unlockAsync();
data();
//ScreenOrientation.unlockAsync();
}, []);
// useEffect(() => {

View File

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

View File

@@ -9,13 +9,13 @@ import {
lineList,
getStationList,
lineList_LineWebID,
} from "@/lib/getStationList";
import { StationProps } from "@/lib/CommonTypes";
} from "../lib/getStationList";
type initialStateType = {
originalStationList: StationProps[][];
setOriginalStationList: React.Dispatch<React.SetStateAction<StationProps[]>>;
getStationDataFromName: (id: string) => StationProps[];
getStationDataFromId: (id: string) => StationProps[];
originalStationList: any[][];
setOriginalStationList: React.Dispatch<React.SetStateAction<any[]>>;
getStationDataFromName: (id: string) => any[];
getStationDataFromId: (id: string) => any[];
getStationDataFromNameBase: (name: string) => any[];
stationList: any[];
getInjectJavascriptAddress: (StationNumber: string) => string;
@@ -74,15 +74,10 @@ export const StationListProvider: FC<Props> = ({ children }) => {
Object.keys(originalStationList).forEach((key) => {
originalStationList[key].forEach((station) => {
if (!station.StationNumber) return;
if (
typeof station.StationNumber === "string" &&
station.StationNumber.includes(name)
) {
if (typeof station.StationNumber === "string" && station.StationNumber.includes(name)) {
if (!!station.jslodApi) returnArray.push(station);
} else if (
typeof station.Station_JP === "string" &&
station.Station_JP.includes(name)
) {
}
else if (typeof station.Station_JP === "string" && station.Station_JP.includes(name)) {
if (!!station.jslodApi) returnArray.push(station);
}
});
@@ -127,9 +122,7 @@ export const StationListProvider: FC<Props> = ({ children }) => {
});
}
});
console.log(bootStationList[0]);
if (bootStationList[0] === undefined) return "";
return `MoveDisplayStation('${bootStationList[0].line}_${bootStationList[0].station.MyStation}_${bootStationList[0].station.Station_JP}');document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");setReload();`;
return `MoveDisplayStation('${bootStationList[0].line}_${bootStationList[0].station.MyStation}_${bootStationList[0].station.Station_JP}');document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");`;
};
return (

View File

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

View File

@@ -1,10 +1,4 @@
import React, {
createContext,
useContext,
useState,
useEffect,
FC,
} from "react";
import React, { createContext, useContext, useState, useEffect } from "react";
import { ASCore } from "../storageControl";
@@ -15,29 +9,29 @@ import { useNotification } from "../stateBox/useNotifications";
const initialState = {
selectedLine: undefined,
setSelectedLine: (e) => {},
setSelectedLine: () => {},
mapsStationData: undefined,
setMapsStationData: (e) => {},
setMapsStationData: () => {},
iconSetting: undefined,
setIconSetting: (e) => {},
setIconSetting: () => {},
mapSwitch: undefined,
setMapSwitch: (e) => {},
setMapSwitch: () => {},
stationMenu: undefined,
setStationMenu: (e) => {},
setStationMenu: () => {},
uiSetting: undefined,
setUiSetting: (e) => {},
setUiSetting: () => {},
LoadError: false,
setLoadError: (e) => {},
setLoadError: () => {},
trainInfo: {
trainNum: undefined,
limited: undefined,
trainData: undefined,
},
setTrainInfo: (e) => {},
setTrainInfo: () => {},
trainMenu: "true",
setTrainMenu: (e) => {},
updatePermission: false,
setUpdatePermission: (e) => {},
setTrainMenu: () => {},
updatePermission : false,
setUpdatePermission : () => {},
injectJavascript: "",
};
@@ -46,36 +40,33 @@ const TrainMenuContext = createContext(initialState);
export const useTrainMenu = () => {
return useContext(TrainMenuContext);
};
type props = { children: React.ReactNode };
export const TrainMenuProvider: FC<props> = ({ children }) => {
export const TrainMenuProvider = ({ 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<boolType>(undefined);
const [mapSwitch, setMapSwitch] = useState<boolType>(undefined);
const [stationMenu, setStationMenu] = useState<boolType>(undefined);
const [iconSetting, setIconSetting] = useState(undefined);
const [mapSwitch, setMapSwitch] = useState(undefined);
const [stationMenu, setStationMenu] = useState(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({
@@ -103,7 +94,7 @@ export const TrainMenuProvider: FC<props> = ({ children }) => {
//列車アイコンスイッチ
ASCore({ k: "iconSwitch", s: setIconSetting, d: "true", u: true });
//地図スイッチ
ASCore({ k: "mapSwitch", s: setMapSwitch, d: "true", u: true });
ASCore({ k: "mapSwitch", s: setMapSwitch, d: "false", u: true });
//駅メニュースイッチ
ASCore({ k: "stationSwitch", s: setStationMenu, d: "true", u: true });
//列車メニュースイッチ

View File

@@ -58,9 +58,7 @@ export const UserPositionProvider: FC<Props> = ({ children }) => {
if (Platform.OS == "web") return;
getLocationPermission();
}, []);
useEffect(() => {
getCurrentPosition();
}, [locationStatus]);
useEffect(getCurrentPosition, [locationStatus]);
useInterval(getCurrentPosition, 5000);
return (