From 9ba1f5d50bfc59859aedd73a6e6beeedf5ac884b Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Thu, 10 Apr 2025 10:24:23 +0000 Subject: [PATCH 01/77] =?UTF-8?q?SpecialTrainInfoBox=E3=82=92=E4=BD=9C?= =?UTF-8?q?=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Menu/FixedContentBottom.js | 23 ++++++--- components/Menu/SpecialTrainInfoBox.tsx | 69 +++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 components/Menu/SpecialTrainInfoBox.tsx diff --git a/components/Menu/FixedContentBottom.js b/components/Menu/FixedContentBottom.js index 2ae1aaf..0144a79 100644 --- a/components/Menu/FixedContentBottom.js +++ b/components/Menu/FixedContentBottom.js @@ -6,10 +6,11 @@ import { MaterialCommunityIcons, } from "@expo/vector-icons"; import { ListItem } from "@rneui/themed"; -import TouchableScale from 'react-native-touchable-scale'; +import TouchableScale from "react-native-touchable-scale"; import Icon from "react-native-vector-icons/Entypo"; import { TextBox } from "../atom/TextBox"; import { TicketBox } from "../atom/TicketBox"; +import { SpecialTrainInfoBox } from "./SpecialTrainInfoBox"; export const FixedContentBottom = (props) => { return ( @@ -50,11 +51,14 @@ export const FixedContentBottom = (props) => { 旅行ツアー + - Linking.openURL("https://xprocess.haruk.in/JR-shikoku-Apps-Common/2025-update-status") + Linking.openURL( + "https://xprocess.haruk.in/JR-shikoku-Apps-Common/2025-update-status" + ) } > @@ -264,12 +268,15 @@ export const FixedContentBottom = (props) => { name: "しこくたぬきのぽんちゃん 【四国家サポーターズクラブ】", }, ].map((d) => ( - Linking.openURL(d.url)} - key={d.url}friction={90} // - tension={100} // These props are passed to the parent component (here TouchableScale) - activeScale={0.95} // - Component={TouchableScale} - > + Linking.openURL(d.url)} + key={d.url} + friction={90} // + tension={100} // These props are passed to the parent component (here TouchableScale) + activeScale={0.95} // + Component={TouchableScale} + > {d.name} diff --git a/components/Menu/SpecialTrainInfoBox.tsx b/components/Menu/SpecialTrainInfoBox.tsx new file mode 100644 index 0000000..71751e2 --- /dev/null +++ b/components/Menu/SpecialTrainInfoBox.tsx @@ -0,0 +1,69 @@ +import { FC, useEffect, useState } from "react"; +import { View, Text, TouchableOpacity } from "react-native"; +import { getPDFViewURL } from "@/lib/getPdfViewURL"; + +type props = { + navigate: (screen: string, params?: object) => void; +}; +export const SpecialTrainInfoBox: FC = ({ navigate }) => { + const [specialData, setSpecialData] = useState([]); + useEffect(() => { + fetch("https://n8n.haruk.in/webhook/sptrainfo") + .then((res) => res.json()) + .then((data) => setSpecialData(data.data)) + .catch((err) => console.log(err)); + }, []); + return ( + + + + 臨時列車情報 + + + + {specialData.map((d) => ( + { + navigate("howto", { + info: getPDFViewURL("https://www.jr-shikoku.co.jp" + d.address), + goTo: "menu", + }); + }} + onLongPress={() => alert(d.description)} + key={d.address} + style={{ + padding: 10, + borderBottomWidth: 1, + borderBottomColor: "#ccc", + flexDirection: "row", + alignItems: "center", + }} + > + {d.text} + + ))} + + + ); +}; From b108029868e6d9778f0d4a018ded19cdb0b48658 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Fri, 11 Apr 2025 10:22:40 +0000 Subject: [PATCH 02/77] =?UTF-8?q?SpecialTrainInfo=E3=82=92ActionSheet?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SpecialTrainInfo.tsx | 51 +++++++++++++++++++ components/ActionSheetComponents/sheets.ts | 2 + components/Menu/FixedContentBottom.js | 6 ++- components/Menu/SpecialTrainInfoBox.tsx | 19 +++---- 4 files changed, 65 insertions(+), 13 deletions(-) create mode 100644 components/ActionSheetComponents/SpecialTrainInfo.tsx diff --git a/components/ActionSheetComponents/SpecialTrainInfo.tsx b/components/ActionSheetComponents/SpecialTrainInfo.tsx new file mode 100644 index 0000000..590f0d9 --- /dev/null +++ b/components/ActionSheetComponents/SpecialTrainInfo.tsx @@ -0,0 +1,51 @@ +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"; +export const SpecialTrainInfo = ({ payload }) => { + const { navigate } = payload; + const actionSheetRef = useRef(null); + const insets = useSafeAreaInsets(); + + return ( + } + ref={actionSheetRef} + isModal={Platform.OS == "ios"} + containerStyle={ + Platform.OS == "android" + ? { + paddingBottom: insets.bottom, + } + : {} + } + useBottomSafeAreaPadding={Platform.OS == "android"} + > + + + + + + + + ); +}; diff --git a/components/ActionSheetComponents/sheets.ts b/components/ActionSheetComponents/sheets.ts index 2f4ba52..e33daa7 100644 --- a/components/ActionSheetComponents/sheets.ts +++ b/components/ActionSheetComponents/sheets.ts @@ -4,11 +4,13 @@ import { JRSTraInfo } from "./JRSTraInfo"; import { StationDeteilView } from "./StationDeteilView"; import { TrainMenuLineSelector } from "./TrainMenuLineSelector"; import { TrainIconUpdate } from "./TrainIconUpdate"; +import { SpecialTrainInfo } from "./SpecialTrainInfo"; registerSheet("EachTrainInfo", EachTrainInfo); registerSheet("JRSTraInfo", JRSTraInfo); registerSheet("StationDetailView", StationDeteilView); registerSheet("TrainMenuLineSelector", TrainMenuLineSelector); registerSheet("TrainIconUpdate", TrainIconUpdate); +registerSheet("SpecialTrainInfo", SpecialTrainInfo); export {}; diff --git a/components/Menu/FixedContentBottom.js b/components/Menu/FixedContentBottom.js index 0144a79..923a8cc 100644 --- a/components/Menu/FixedContentBottom.js +++ b/components/Menu/FixedContentBottom.js @@ -11,6 +11,7 @@ import Icon from "react-native-vector-icons/Entypo"; import { TextBox } from "../atom/TextBox"; import { TicketBox } from "../atom/TicketBox"; import { SpecialTrainInfoBox } from "./SpecialTrainInfoBox"; +import { SheetManager } from "react-native-actions-sheet"; export const FixedContentBottom = (props) => { return ( @@ -51,7 +52,6 @@ export const FixedContentBottom = (props) => { 旅行ツアー - { backgroundColor="#0099CC" flex={1} onPressButton={() => - Linking.openURL("https://www.jr-shikoku.co.jp/sp/index.html#menu-box") + SheetManager.show("SpecialTrainInfo", { + payload: { navigate: props.navigate }, + }) } > diff --git a/components/Menu/SpecialTrainInfoBox.tsx b/components/Menu/SpecialTrainInfoBox.tsx index 71751e2..c24bb95 100644 --- a/components/Menu/SpecialTrainInfoBox.tsx +++ b/components/Menu/SpecialTrainInfoBox.tsx @@ -1,13 +1,14 @@ -import { FC, useEffect, 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"; type props = { navigate: (screen: string, params?: object) => void; }; export const SpecialTrainInfoBox: FC = ({ navigate }) => { const [specialData, setSpecialData] = useState([]); - useEffect(() => { + useLayoutEffect(() => { fetch("https://n8n.haruk.in/webhook/sptrainfo") .then((res) => res.json()) .then((data) => setSpecialData(data.data)) @@ -17,10 +18,6 @@ export const SpecialTrainInfoBox: FC = ({ navigate }) => { @@ -29,17 +26,16 @@ export const SpecialTrainInfoBox: FC = ({ navigate }) => { fontSize: 30, fontWeight: "bold", color: "white", - padding: 10, + paddingHorizontal: 10, + paddingVertical: 5, }} > 臨時列車情報 - {specialData.map((d) => ( @@ -49,6 +45,7 @@ export const SpecialTrainInfoBox: FC = ({ navigate }) => { info: getPDFViewURL("https://www.jr-shikoku.co.jp" + d.address), goTo: "menu", }); + SheetManager.hide("SpecialTrainInfo"); }} onLongPress={() => alert(d.description)} key={d.address} @@ -63,7 +60,7 @@ export const SpecialTrainInfoBox: FC = ({ navigate }) => { {d.text} ))} - + ); }; From bb0ae86f67c2dccf8df6e96f4fc825569fc45200 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Fri, 11 Apr 2025 10:42:50 +0000 Subject: [PATCH 03/77] =?UTF-8?q?Twitter=E3=82=92SocialMenu=E3=81=AB?= =?UTF-8?q?=E7=A7=BB=E5=8B=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ActionSheetComponents/SocialMenu.tsx | 146 ++++++++++++++++++ components/ActionSheetComponents/sheets.ts | 2 + components/Menu/FixedContentBottom.js | 114 ++------------ 3 files changed, 161 insertions(+), 101 deletions(-) create mode 100644 components/ActionSheetComponents/SocialMenu.tsx diff --git a/components/ActionSheetComponents/SocialMenu.tsx b/components/ActionSheetComponents/SocialMenu.tsx new file mode 100644 index 0000000..d2d1890 --- /dev/null +++ b/components/ActionSheetComponents/SocialMenu.tsx @@ -0,0 +1,146 @@ +import React, { useRef } from "react"; +import { View, Platform, Text } from "react-native"; +import ActionSheet ,{ ScrollView } from "react-native-actions-sheet"; +import { useSafeAreaInsets } from "react-native-safe-area-context"; +import { ListItem } from "@rneui/themed"; +import { MaterialCommunityIcons } from "@expo/vector-icons"; +import { Linking } from "react-native"; +import TouchableScale from "react-native-touchable-scale"; +export const Social = () => { + const actionSheetRef = useRef(null); + const insets = useSafeAreaInsets(); + + return ( + } + ref={actionSheetRef} + isModal={Platform.OS == "ios"} + containerStyle={ + Platform.OS == "android" + ? { + paddingBottom: insets.bottom, + } + : {} + } + useBottomSafeAreaPadding={Platform.OS == "android"} + > + + + + + + + + + JR四国公式SNS一族 + + + + {[ + { + url: "https://twitter.com/jr_shikoku_info", + name: "JR四国列車運行情報", + }, + + { + url: "https://twitter.com/JRshikoku_eigyo", + name: "JR四国営業部【公式】", + }, + { + url: "https://twitter.com/JRshikoku_tokyo", + name: "JR四国 東京営業情報【公式】", + }, + { + url: "https://twitter.com/JRshikoku_osaka", + name: "JR四国 大阪営業部【公式】", + }, + { + url: "https://twitter.com/jrs_matsuyama", + name: "JR四国 松山駅 【公式】", + }, + { + url: "https://twitter.com/jrshikoku_kochi", + name: "JR四国 高知駅【公式】", + }, + { + url: "https://twitter.com/jr_tokust", + name: "JR四国 徳島駅【公式】", + }, + { + url: "https://twitter.com/jrshikoku_uwjm", + name: "JR四国 宇和島駅【公式】", + }, + { + url: "https://twitter.com/jrshikoku_wkama", + name: "JR四国 ワープ高松支店【公式】", + }, + { + url: "https://twitter.com/JRshikoku_wkoch", + name: "JR四国 ワープ高知支店【公式】", + }, + { + url: "https://twitter.com/Yoakemonogatari", + name: "志国土佐 時代の夜明けのものがたり【公式】", + }, + { + url: "https://twitter.com/Smile_Eki_Chan", + name: "すまいるえきちゃん♡JR四国【公式】", + }, + { + url: "https://twitter.com/sper_ponchan", + name: "しこくたぬきのぽんちゃん 【四国家サポーターズクラブ】", + }, + ].map((d) => ( + Linking.openURL(d.url)} + key={d.url} + friction={90} // + tension={100} // These props are passed to the parent component (here TouchableScale) + activeScale={0.95} // + Component={TouchableScale} + > + + {d.name} + + + + ))} + + + + ); +}; diff --git a/components/ActionSheetComponents/sheets.ts b/components/ActionSheetComponents/sheets.ts index e33daa7..71d9912 100644 --- a/components/ActionSheetComponents/sheets.ts +++ b/components/ActionSheetComponents/sheets.ts @@ -5,6 +5,7 @@ import { StationDeteilView } from "./StationDeteilView"; import { TrainMenuLineSelector } from "./TrainMenuLineSelector"; import { TrainIconUpdate } from "./TrainIconUpdate"; import { SpecialTrainInfo } from "./SpecialTrainInfo"; +import { Social } from "./SocialMenu"; registerSheet("EachTrainInfo", EachTrainInfo); registerSheet("JRSTraInfo", JRSTraInfo); @@ -12,5 +13,6 @@ registerSheet("StationDetailView", StationDeteilView); registerSheet("TrainMenuLineSelector", TrainMenuLineSelector); registerSheet("TrainIconUpdate", TrainIconUpdate); registerSheet("SpecialTrainInfo", SpecialTrainInfo); +registerSheet("Social", Social); export {}; diff --git a/components/Menu/FixedContentBottom.js b/components/Menu/FixedContentBottom.js index 923a8cc..de78d59 100644 --- a/components/Menu/FixedContentBottom.js +++ b/components/Menu/FixedContentBottom.js @@ -185,108 +185,20 @@ export const FixedContentBottom = (props) => { (通話料がかかります) - + SheetManager.show("Social") + } > - - - - JR四国公式Twitter一族 - - - - {[ - { - url: "https://twitter.com/jr_shikoku_info", - name: "JR四国列車運行情報", - }, - - { - url: "https://twitter.com/JRshikoku_eigyo", - name: "JR四国営業部【公式】", - }, - { - url: "https://twitter.com/JRshikoku_tokyo", - name: "JR四国 東京営業情報【公式】", - }, - { - url: "https://twitter.com/JRshikoku_osaka", - name: "JR四国 大阪営業部【公式】", - }, - { - url: "https://twitter.com/jrs_matsuyama", - name: "JR四国 松山駅 【公式】", - }, - { - url: "https://twitter.com/jrshikoku_kochi", - name: "JR四国 高知駅【公式】", - }, - { - url: "https://twitter.com/jr_tokust", - name: "JR四国 徳島駅【公式】", - }, - { - url: "https://twitter.com/jrshikoku_uwjm", - name: "JR四国 宇和島駅【公式】", - }, - { - url: "https://twitter.com/jrshikoku_wkama", - name: "JR四国 ワープ高松支店【公式】", - }, - { - url: "https://twitter.com/JRshikoku_wkoch", - name: "JR四国 ワープ高知支店【公式】", - }, - { - url: "https://twitter.com/Yoakemonogatari", - name: "志国土佐 時代の夜明けのものがたり【公式】", - }, - { - url: "https://twitter.com/Smile_Eki_Chan", - name: "すまいるえきちゃん♡JR四国【公式】", - }, - { - url: "https://twitter.com/sper_ponchan", - name: "しこくたぬきのぽんちゃん 【四国家サポーターズクラブ】", - }, - ].map((d) => ( - Linking.openURL(d.url)} - key={d.url} - friction={90} // - tension={100} // These props are passed to the parent component (here TouchableScale) - activeScale={0.95} // - Component={TouchableScale} - > - - {d.name} - - - - ))} - - + + ソーシャルメディア + + + JR四国のSNS一覧です。 + + 上級者向け機能 Date: Fri, 11 Apr 2025 11:18:51 +0000 Subject: [PATCH 04/77] =?UTF-8?q?menu=E3=81=AB=E6=96=B0=E3=81=97=E3=81=84?= =?UTF-8?q?=E6=A6=82=E5=BF=B5=E3=82=92=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- menu.js | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/menu.js b/menu.js index 42a8592..644953e 100644 --- a/menu.js +++ b/menu.js @@ -8,7 +8,7 @@ import { Text, TouchableOpacity, LayoutAnimation, - Dimensions, + useWindowDimensions, } from "react-native"; import Constants from "expo-constants"; import * as Location from "expo-location"; @@ -42,6 +42,16 @@ export default function Menu({ getCurrentTrain }) { const { navigate } = useNavigation(); const { favoriteStation } = useFavoriteStation(); const { originalStationList } = useStationList(); + const { height, width } = useWindowDimensions(); + const scrollRef = useRef(null); + useEffect(() => { + if (scrollRef.current) { + scrollRef.current.scrollTo({ + y: (height / 100) * 60 - (((width / 100) * 80) / 20) * 9 + 30, + animated: false, + }); + } + }, []); //位置情報 const [locationStatus, setLocationStatus] = useState(null); @@ -131,7 +141,7 @@ export default function Menu({ getCurrentTrain }) { }, [selectedCurrentStation]); //全列車ダイヤリストを作成するuseEffect - const { allTrainDiagram:trainDiagram} = useAllTrainDiagram(); + const { allTrainDiagram: trainDiagram } = useAllTrainDiagram(); const oPSign = () => { const payload = { @@ -165,7 +175,6 @@ export default function Menu({ getCurrentTrain }) { ); setDotButton(!dotButton); }; - const width = Dimensions.get("window").width; return ( - + + + <> {originalStationList.length != 0 && allStationData.length != 0 && ( Date: Fri, 11 Apr 2025 13:52:48 +0000 Subject: [PATCH 05/77] =?UTF-8?q?=E5=9C=B0=E5=9B=B3=E3=81=AE=E6=A9=9F?= =?UTF-8?q?=E8=83=BD=E3=81=8C=E4=B8=80=E9=80=9A=E3=82=8A=E5=8B=95=E3=81=8F?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E3=81=AA=E3=81=A3=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- menu.js | 74 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 15 deletions(-) diff --git a/menu.js b/menu.js index 644953e..6f712b2 100644 --- a/menu.js +++ b/menu.js @@ -37,6 +37,7 @@ import lineColorList from "./assets/originData/lineColorList"; import { AS } from "./storageControl"; import { SimpleDot } from "./components/Menu/SimpleDot"; import { useAllTrainDiagram } from "./stateBox/useAllTrainDiagram"; +import MapView from "react-native-maps"; export default function Menu({ getCurrentTrain }) { const { navigate } = useNavigation(); @@ -44,13 +45,28 @@ export default function Menu({ getCurrentTrain }) { const { originalStationList } = useStationList(); const { height, width } = useWindowDimensions(); const scrollRef = useRef(null); + const [mapsOpacity, setMapsOpacity] = useState(1); + const mapsSizeOffset = + (height / 100) * 60 - (((width / 100) * 80) / 20) * 9 + 60 - (Platform.OS == "ios" ? Constants.statusBarHeight : 0); useEffect(() => { - if (scrollRef.current) { - scrollRef.current.scrollTo({ - y: (height / 100) * 60 - (((width / 100) * 80) / 20) * 9 + 30, - animated: false, - }); - } + setTimeout(() => { + if (scrollRef.current) { + scrollRef.current.scrollTo({ + y: mapsSizeOffset, + animated: false, + }); + } + }, 10); + }, []); + useEffect(() => { + setTimeout(() => { + if (scrollRef.current) { + scrollRef.current.scrollTo({ + y: mapsSizeOffset, + animated: false, + }); + } + }, 10); }, []); //位置情報 @@ -186,21 +202,49 @@ export default function Menu({ getCurrentTrain }) { { + console.log(Object.keys(scrollRef.current)); + const scrollY = d.nativeEvent.contentOffset.y; + if (scrollY < mapsSizeOffset) { + setMapsOpacity(scrollY / mapsSizeOffset); + } + }} + snapToOffsets={[mapsSizeOffset]} > + + { + alert("地図をタップ"); + }} + > + - + <> {originalStationList.length != 0 && allStationData.length != 0 && ( From 190be0fa676afdb2b811edecab46bd75e5217db0 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Fri, 11 Apr 2025 14:12:10 +0000 Subject: [PATCH 06/77] =?UTF-8?q?=E5=9C=B0=E5=9B=B3=E3=81=8C=E7=A7=BB?= =?UTF-8?q?=E5=8B=95=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E5=A4=89?= =?UTF-8?q?=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- menu.js | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/menu.js b/menu.js index 6f712b2..76bb345 100644 --- a/menu.js +++ b/menu.js @@ -12,6 +12,10 @@ import { } from "react-native"; import Constants from "expo-constants"; import * as Location from "expo-location"; +import { + configureReanimatedLogger, + ReanimatedLogLevel, +} from 'react-native-reanimated'; import StatusbarDetect from "./StatusbarDetect"; import { widthPercentageToDP as wp } from "react-native-responsive-screen"; import { Ionicons } from "@expo/vector-icons"; @@ -38,7 +42,10 @@ import { AS } from "./storageControl"; import { SimpleDot } from "./components/Menu/SimpleDot"; import { useAllTrainDiagram } from "./stateBox/useAllTrainDiagram"; import MapView from "react-native-maps"; - +configureReanimatedLogger({ + level: ReanimatedLogLevel.error, // Set the log level to error + strict: true, // Reanimated runs in strict mode by default +}); export default function Menu({ getCurrentTrain }) { const { navigate } = useNavigation(); const { favoriteStation } = useFavoriteStation(); @@ -46,8 +53,12 @@ export default function Menu({ getCurrentTrain }) { const { height, width } = useWindowDimensions(); const scrollRef = useRef(null); const [mapsOpacity, setMapsOpacity] = useState(1); + const mapsRef = useRef(null); const mapsSizeOffset = - (height / 100) * 60 - (((width / 100) * 80) / 20) * 9 + 60 - (Platform.OS == "ios" ? Constants.statusBarHeight : 0); + (height / 100) * 60 - + (((width / 100) * 80) / 20) * 9 + + 60 - + (Platform.OS == "ios" ? Constants.statusBarHeight : 0); useEffect(() => { setTimeout(() => { if (scrollRef.current) { @@ -58,17 +69,6 @@ export default function Menu({ getCurrentTrain }) { } }, 10); }, []); - useEffect(() => { - setTimeout(() => { - if (scrollRef.current) { - scrollRef.current.scrollTo({ - y: mapsSizeOffset, - animated: false, - }); - } - }, 10); - }, []); - //位置情報 const [locationStatus, setLocationStatus] = useState(null); useEffect(() => { @@ -175,6 +175,25 @@ export default function Menu({ getCurrentTrain }) { const [dotButton, setDotButton] = useState(false); + useEffect(() => { + console.log(selectedCurrentStation); + if(allStationData.length == 0) return; + const currentStationData = + originalStationList && + allStationData[selectedCurrentStation] && + allStationData[selectedCurrentStation][0]; + console.log(currentStationData); + const {lat, lng} = currentStationData; + const mapRegion = { + latitude: lat, + longitude: lng, + latitudeDelta: 0.05, + longitudeDelta: 0.05, + }; + mapsRef.current.animateToRegion(mapRegion, 1000); + + }, [selectedCurrentStation, currentStation, allStationData,mapsRef]); + useEffect(() => { AS.getItem("CarouselSettings/activeDotSettings").then((data) => { setDotButton(data === "true"); @@ -218,6 +237,7 @@ export default function Menu({ getCurrentTrain }) { > Date: Fri, 11 Apr 2025 15:35:25 +0000 Subject: [PATCH 07/77] =?UTF-8?q?=E7=8F=BE=E5=9C=A8=E5=9C=B0=E3=83=99?= =?UTF-8?q?=E3=83=BC=E3=82=B9=E3=81=AE=E3=83=9C=E3=82=BF=E3=83=B3=E3=81=A8?= =?UTF-8?q?=E3=81=8B=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/atom/UsefulBox.js | 3 +- components/発車時刻表/LED_vidion.js | 55 ++++---- menu.js | 161 ++++++++++++++++++----- 3 files changed, 153 insertions(+), 66 deletions(-) diff --git a/components/atom/UsefulBox.js b/components/atom/UsefulBox.js index afab4cd..d6adf3c 100644 --- a/components/atom/UsefulBox.js +++ b/components/atom/UsefulBox.js @@ -1,7 +1,7 @@ import { TouchableOpacity, Text } from "react-native"; import { MaterialCommunityIcons } from "@expo/vector-icons"; export const UsefulBox = (props) => { - const { icon, backgroundColor, flex, onPressButton, children } = props; + const { icon, backgroundColor, flex, onPressButton, children, disable = false } = props; return ( { alignItems: "center", margin: 2, }} + disabled={disable} onPress={onPressButton} > diff --git a/components/発車時刻表/LED_vidion.js b/components/発車時刻表/LED_vidion.js index 6eefb49..3b4e86f 100644 --- a/components/発車時刻表/LED_vidion.js +++ b/components/発車時刻表/LED_vidion.js @@ -10,8 +10,7 @@ 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"; /** * @@ -43,13 +42,8 @@ import { EachData } from "./EachData"; * 9062D 四国まんなか千年ものがたり(臨時?) */ export default function LED_vision(props) { - const { - station, - trainDiagram, - getCurrentTrain, - navigate, - openStationACFromEachTrainInfo, - } = props; + const { station, getCurrentTrain, navigate, openStationACFromEachTrainInfo } = + props; const { currentTrain } = useCurrentTrain(); const [stationDiagram, setStationDiagram] = useState({}); //当該駅の全時刻表 const [finalSwitch, setFinalSwitch] = useState(false); @@ -57,6 +51,7 @@ export default function LED_vision(props) { const [trainDescriptionSwitch, setTrainDescriptionSwitch] = useState(false); const [isInfoArea, setIsInfoArea] = useState(false); const { areaInfo, areaStationID } = useAreaInfo(); + const { allTrainDiagram: trainDiagram } = useAllTrainDiagram(); useEffect(() => { AS.getItem("LEDSettings/trainIDSwitch").then((data) => { @@ -107,27 +102,29 @@ export default function LED_vision(props) { }, [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 = "当駅止"; + const returnData = Object.keys(stationDiagram) + .map((trainNum) => { + let trainData = {}; + stationDiagram[trainNum].split("#").forEach((data) => { + if (data.match("着")) { + trainData.lastStation = data.split(",着,")[0]; } - } - }); - return { - train: trainNum, - time: trainData.time, - lastStation: trainData.lastStation, - }; - }).filter((d) => d.time); + 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]): diff --git a/menu.js b/menu.js index 76bb345..54f71e7 100644 --- a/menu.js +++ b/menu.js @@ -15,12 +15,10 @@ import * as Location from "expo-location"; import { configureReanimatedLogger, ReanimatedLogLevel, -} from 'react-native-reanimated'; +} from "react-native-reanimated"; import StatusbarDetect from "./StatusbarDetect"; -import { widthPercentageToDP as wp } from "react-native-responsive-screen"; import { Ionicons } from "@expo/vector-icons"; import LottieView from "lottie-react-native"; -import { parseAllTrainDiagram } from "./lib/parseAllTrainDiagram"; import LED_vision from "./components/発車時刻表/LED_vidion"; import Sign from "./components/駅名表/Sign"; @@ -52,7 +50,7 @@ export default function Menu({ getCurrentTrain }) { const { originalStationList } = useStationList(); const { height, width } = useWindowDimensions(); const scrollRef = useRef(null); - const [mapsOpacity, setMapsOpacity] = useState(1); + const [mapsOpacity, setMapsOpacity] = useState(false); const mapsRef = useRef(null); const mapsSizeOffset = (height / 100) * 60 - @@ -81,13 +79,17 @@ export default function Menu({ getCurrentTrain }) { ); }); }, []); - + const [position, setPosition] = useState(undefined); const getCurrentPosition = () => { if (!locationStatus) return () => {}; - Location.getCurrentPositionAsync({}).then((location) => - makeCurrentStation(location) - ); + Location.getCurrentPositionAsync({}).then((location) => { + setPosition(location); + }); }; + useEffect(() => { + if (!position) return () => {}; + makeCurrentStation(position); + }, [position]); const makeCurrentStation = (location) => { if (!originalStationList) return () => {}; const findStationEachLine = (selectLine) => { @@ -157,8 +159,6 @@ export default function Menu({ getCurrentTrain }) { }, [selectedCurrentStation]); //全列車ダイヤリストを作成するuseEffect - const { allTrainDiagram: trainDiagram } = useAllTrainDiagram(); - const oPSign = () => { const payload = { currentStation: @@ -177,22 +177,20 @@ export default function Menu({ getCurrentTrain }) { useEffect(() => { console.log(selectedCurrentStation); - if(allStationData.length == 0) return; - const currentStationData = + if (allStationData.length == 0) return; + if (allStationData[selectedCurrentStation] == undefined) return; + const { lat, lng } = originalStationList && allStationData[selectedCurrentStation] && allStationData[selectedCurrentStation][0]; - console.log(currentStationData); - const {lat, lng} = currentStationData; - const mapRegion = { - latitude: lat, - longitude: lng, - latitudeDelta: 0.05, - longitudeDelta: 0.05, - }; - mapsRef.current.animateToRegion(mapRegion, 1000); - - }, [selectedCurrentStation, currentStation, allStationData,mapsRef]); + const mapRegion = { + latitude: lat, + longitude: lng, + latitudeDelta: 0.05, + longitudeDelta: 0.05, + }; + mapsRef.current.animateToRegion(mapRegion, 1000); + }, [selectedCurrentStation, currentStation, allStationData, mapsRef]); useEffect(() => { AS.getItem("CarouselSettings/activeDotSettings").then((data) => { @@ -228,10 +226,8 @@ export default function Menu({ getCurrentTrain }) { decelerationRate={"normal"} onScroll={(d) => { console.log(Object.keys(scrollRef.current)); - const scrollY = d.nativeEvent.contentOffset.y; - if (scrollY < mapsSizeOffset) { - setMapsOpacity(scrollY / mapsSizeOffset); - } + const scrollY = d.nativeEvent.contentOffset.y + 100; + setMapsOpacity(scrollY < mapsSizeOffset); }} snapToOffsets={[mapsSizeOffset]} > @@ -244,7 +240,7 @@ export default function Menu({ getCurrentTrain }) { position: "absolute", height: (height / 100) * 60 + (((width / 100) * 80) / 20) * 9 + 60, - opacity: 1 - mapsOpacity, + opacity: mapsOpacity ? 1 : 0, }} showsUserLocation={true} loadingEnabled={true} @@ -263,8 +259,103 @@ export default function Menu({ getCurrentTrain }) { }} > - - + + + + { + if(!position) return; + const { latitude, longitude } = position.coords; + mapsRef.current.animateToRegion( + { + latitude, + longitude, + latitudeDelta: 0.05, + longitudeDelta: 0.05, + }, + 1000 + ); + }} + > + + + 現在地基準 + + + { + // お気に入りリスト更新 + }} + > + + + お気に入りリスト + + + + + <> {originalStationList.length != 0 && allStationData.length != 0 && ( @@ -346,10 +437,7 @@ export default function Menu({ getCurrentTrain }) { originalStationList.length != 0 && allStationData[selectedCurrentStation] && ( {}} @@ -362,7 +450,7 @@ export default function Menu({ getCurrentTrain }) { ); } -const TopMenuButton = () => { +const TopMenuButton = ({ show }) => { const buttonList = [ { backgroundColor: "#F89038", @@ -388,12 +476,13 @@ const TopMenuButton = () => { }, ]; return ( - + {buttonList.map((d, index) => ( From 44f8be994e1e45a752d1edc27c44185d20e1264b Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 13 Apr 2025 10:32:30 +0000 Subject: [PATCH 08/77] =?UTF-8?q?=E5=8D=98=E7=99=BA=E3=81=AE=E5=A4=89?= =?UTF-8?q?=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Menu/JRSTraInfoBox.tsx | 111 ++++++++++++++++++++++++++++++ components/Menu/TitleBar.js | 25 ++++--- components/Menu/TopMenuButton.tsx | 52 ++++++++++++++ components/atom/UsefulBox.js | 23 ------- stateBox/useTrainDelayData.js | 2 +- 5 files changed, 180 insertions(+), 33 deletions(-) create mode 100644 components/Menu/JRSTraInfoBox.tsx create mode 100644 components/Menu/TopMenuButton.tsx delete mode 100644 components/atom/UsefulBox.js diff --git a/components/Menu/JRSTraInfoBox.tsx b/components/Menu/JRSTraInfoBox.tsx new file mode 100644 index 0000000..b740f31 --- /dev/null +++ b/components/Menu/JRSTraInfoBox.tsx @@ -0,0 +1,111 @@ +import React from "react"; +import { + View, + Text, + TouchableOpacity, + ScrollView, + StyleProp, + ViewStyle, +} from "react-native"; +import { Ionicons } from "@expo/vector-icons"; +import { SheetManager } from "react-native-actions-sheet"; +import LottieView from "lottie-react-native"; +import { useTrainDelayData } from "@/stateBox/useTrainDelayData"; +import dayjs from "dayjs"; +export const JRSTraInfoBox = () => { + const { getTime, delayData, loadingDelayData, setLoadingDelayData } = + useTrainDelayData(); + const styles: { [key: string]: StyleProp } = { + touch: { + backgroundColor: "#0099CC", + borderRadius: 5, + margin: 10, + borderColor: "black", + borderWidth: 2, + overflow: "hidden", + }, + scroll: { + backgroundColor: "#0099CC", + borderRadius: 5, + maxHeight: 300, + }, + bottom: { + position: "absolute", + top: 250, + alignItems: "center", + width: "100%", + height: 50, + backgroundColor: "#007FCC88", + }, + box: { + padding: 10, + backgroundColor: "white", + borderBottomLeftRadius: 5, + borderBottomRightRadius: 5, + }, + }; + return ( + SheetManager.show("JRSTraInfo")} + style={styles.touch} + > + + + + 列車遅延速報EX + + + + {getTime ? dayjs(getTime).format("HH:mm") : NaN} + + setLoadingDelayData(true)} + /> + + + {loadingDelayData ? ( + + + + ) : delayData ? ( + delayData.map((d, index, array) => { + let data = d.split(" "); + return ( + + + {data[0].replace("\n", "")} + + {data[1]} + {data[3]} + + ); + }) + ) : ( + 現在、5分以上の遅れはありません。 + )} + + + + + + 詳細を見る + + + + + ); +}; diff --git a/components/Menu/TitleBar.js b/components/Menu/TitleBar.js index e8672a6..ad05cb5 100644 --- a/components/Menu/TitleBar.js +++ b/components/Menu/TitleBar.js @@ -1,18 +1,25 @@ -import { View, TouchableOpacity, Linking } from "react-native"; -import AutoHeightImage from "react-native-auto-height-image"; -import { widthPercentageToDP as wp } from "react-native-responsive-screen"; +import { View, TouchableOpacity, Linking,Platform, Image, useWindowDimensions } from "react-native"; +import Constants from "expo-constants"; + export const TitleBar = () => { + const { width } = useWindowDimensions(); return ( - + Linking.openURL("https://www.jr-shikoku.co.jp")} > - + ); diff --git a/components/Menu/TopMenuButton.tsx b/components/Menu/TopMenuButton.tsx new file mode 100644 index 0000000..d4950db --- /dev/null +++ b/components/Menu/TopMenuButton.tsx @@ -0,0 +1,52 @@ +import React from "react"; +import { Linking, View } from "react-native"; +import { UsefulBox } from "@/components/TrainMenu/UsefulBox"; +import MaterialCommunityIcons from "@expo/vector-icons/build/MaterialCommunityIcons"; +export const TopMenuButton = () => { + const buttonList:{ + backgroundColor: string; + icon: keyof typeof MaterialCommunityIcons.glyphMap; + onPress: () => void; + title: string; + }[] = [ + { + backgroundColor: "#F89038", + icon: "train-car", + onPress: () => + Linking.openURL("https://www.jr-shikoku.co.jp/01_trainbus/sp/"), + title: "駅・鉄道情報", + }, + { + backgroundColor: "#EA4752", + icon: "google-spreadsheet", + onPress: () => + Linking.openURL( + "https://www.jr-shikoku.co.jp/01_trainbus/jikoku/sp/#mainprice-box" + ), + title: "運賃表", + }, + { + backgroundColor: "#91C31F", + icon: "clipboard-list-outline", + onPress: () => Linking.openURL("https://www.jr-shikoku.co.jp/e5489/"), + title: "予約", + }, + ]; + + + return ( + + {buttonList.map((d, index) => ( + + {d.title} + + ))} + + ); +}; \ No newline at end of file diff --git a/components/atom/UsefulBox.js b/components/atom/UsefulBox.js deleted file mode 100644 index d6adf3c..0000000 --- a/components/atom/UsefulBox.js +++ /dev/null @@ -1,23 +0,0 @@ -import { TouchableOpacity, Text } from "react-native"; -import { MaterialCommunityIcons } from "@expo/vector-icons"; -export const UsefulBox = (props) => { - const { icon, backgroundColor, flex, onPressButton, children, disable = false } = props; - return ( - - - - {children} - - - ); -}; diff --git a/stateBox/useTrainDelayData.js b/stateBox/useTrainDelayData.js index ead6cb3..7c90660 100644 --- a/stateBox/useTrainDelayData.js +++ b/stateBox/useTrainDelayData.js @@ -3,7 +3,7 @@ const initialState = { getTime: new Date(), setGetTime: () => {}, loadingDelayData: true, - setLoadingDelayData: () => {}, + setLoadingDelayData: (loading) => {}, delayData: undefined, setDelayData: () => {}, }; From 934938287d11416cdb4cc09eb64b26d51244ce13 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 13 Apr 2025 10:35:08 +0000 Subject: [PATCH 09/77] =?UTF-8?q?=E3=83=A1=E3=83=8B=E3=83=A5=E3=83=BC?= =?UTF-8?q?=E3=81=AE=E5=9C=B0=E5=9B=B3=E6=A9=9F=E8=83=BD=E3=81=AE=E4=BB=AE?= =?UTF-8?q?=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MenuPage.js | 26 ++- menu.js | 548 ++++++++++++++++++---------------------------------- 2 files changed, 208 insertions(+), 366 deletions(-) diff --git a/MenuPage.js b/MenuPage.js index dc198b5..8c11bda 100644 --- a/MenuPage.js +++ b/MenuPage.js @@ -1,5 +1,10 @@ -import React, { useEffect } from "react"; +import React, { useEffect, useRef } from "react"; import { createStackNavigator } from "@react-navigation/stack"; +import { useWindowDimensions, Platform } from "react-native"; +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"; @@ -13,10 +18,13 @@ import AllTrainDiagramView from "./components/AllTrainDiagramView"; import { useCurrentTrain } from "./stateBox/useCurrentTrain"; import { useNavigation } from "@react-navigation/native"; import { news } from "./config/newsUpdate"; +import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs"; const Stack = createStackNavigator(); export function MenuPage() { const { favoriteStation, setFavoriteStation } = useFavoriteStation(); + const { height, width } = useWindowDimensions(); + const tabBarHeight = useBottomTabBarHeight(); const { getCurrentTrain } = useCurrentTrain(); const navigation = useNavigation(); const { addListener } = navigation; @@ -42,8 +50,20 @@ export function MenuPage() { }) .catch((error) => console.error("Error fetching icon setting:", error)); }, []); + + const scrollRef = useRef(null); + const MapHeight = + height - + tabBarHeight + + (Platform.OS == "android" ? Constants.statusBarHeight : 0) - + 100 - + ((((width / 100) * 80) / 20) * 9 + 10 + 30); useEffect(() => { const unsubscribe = addListener("tabPress", (e) => { + scrollRef.current.scrollTo({ + y: MapHeight - 80, + animated: true, + }); AS.getItem("favoriteStation") .then((d) => { const returnData = JSON.parse(d); @@ -65,7 +85,9 @@ export function MenuPage() { gestureEnabled: true, headerTransparent: true, }} - children={() => } + children={() => ( + + )} /> { setTimeout(() => { if (scrollRef.current) { scrollRef.current.scrollTo({ - y: mapsSizeOffset, + y: MapHeight - 80, animated: false, }); } @@ -82,9 +81,9 @@ export default function Menu({ getCurrentTrain }) { const [position, setPosition] = useState(undefined); const getCurrentPosition = () => { if (!locationStatus) return () => {}; - Location.getCurrentPositionAsync({}).then((location) => { - setPosition(location); - }); + Location.getCurrentPositionAsync({}).then((location) => + setPosition(location) + ); }; useEffect(() => { if (!position) return () => {}; @@ -219,380 +218,201 @@ export default function Menu({ getCurrentTrain }) { { - console.log(Object.keys(scrollRef.current)); const scrollY = d.nativeEvent.contentOffset.y + 100; - setMapsOpacity(scrollY < mapsSizeOffset); + setMapsOpacity(scrollY < MapHeight); }} - snapToOffsets={[mapsSizeOffset]} + snapToOffsets={[MapHeight - 80]} > - - alert("地図をタップ")} + /> + + { - alert("地図をタップ"); - }} - > - - - - { + if (!position) return; + const { latitude, longitude } = position.coords; + mapsRef.current.animateToRegion( + { + latitude, + longitude, + latitudeDelta: 0.05, + longitudeDelta: 0.05, + }, + 1000 + ); }} > - + { - if(!position) return; - const { latitude, longitude } = position.coords; - mapsRef.current.animateToRegion( - { - latitude, - longitude, - latitudeDelta: 0.05, - longitudeDelta: 0.05, - }, - 1000 - ); + textAlign: "center", }} > - - - 現在地基準 - - - { - // お気に入りリスト更新 - }} - > - - - お気に入りリスト - - - - + + - - <> - {originalStationList.length != 0 && allStationData.length != 0 && ( - - { - return ( - - - - - - ); - }} + onPress={() => { + // お気に入りリスト更新 + }} + > + - - {originalStationList && - allStationData.map((d, index) => { - const active = index == selectedCurrentStation; - const numberIndex = d[0].StationNumber; - if (dotButton) { - return ( - setSelectedCurrentStation(index)} - currentStation={d} - active={active} - index={numberIndex} + お気に入りリスト + + + + {allStationData.length != 0 && originalStationList.length != 0 && ( + <> + + { + return ( + + + - ); - } else { - return ( - setSelectedCurrentStation(index)} - active={active} - index={numberIndex} - /> - ); - } - })} + + + ); + }} + /> + + {originalStationList && + allStationData.map((d, index) => { + const active = index == selectedCurrentStation; + const numberIndex = d[0].StationNumber; + if (dotButton) { + return ( + setSelectedCurrentStation(index)} + currentStation={d} + active={active} + index={numberIndex} + /> + ); + } else { + return ( + setSelectedCurrentStation(index)} + active={active} + index={numberIndex} + /> + ); + } + })} + - + {allStationData[selectedCurrentStation] && ( + {}} + /> + )} + )} - {allStationData.length != 0 && - originalStationList.length != 0 && - allStationData[selectedCurrentStation] && ( - {}} - /> - )} + + ); } - -const TopMenuButton = ({ show }) => { - const buttonList = [ - { - backgroundColor: "#F89038", - icon: "train-car", - onPress: () => - Linking.openURL("https://www.jr-shikoku.co.jp/01_trainbus/sp/"), - title: "駅・鉄道情報", - }, - { - backgroundColor: "#EA4752", - icon: "google-spreadsheet", - onPress: () => - Linking.openURL( - "https://www.jr-shikoku.co.jp/01_trainbus/jikoku/sp/#mainprice-box" - ), - title: "運賃表", - }, - { - backgroundColor: "#91C31F", - icon: "clipboard-list-outline", - onPress: () => Linking.openURL("https://www.jr-shikoku.co.jp/e5489/"), - title: "予約", - }, - ]; - return ( - - {buttonList.map((d, index) => ( - - {d.title} - - ))} - - ); -}; - -const JRSTraInfoBox = () => { - const { getTime, delayData, loadingDelayData, setLoadingDelayData } = - useTrainDelayData(); - const styles = { - touch: { - backgroundColor: "#0099CC", - borderRadius: 5, - margin: 10, - borderColor: "black", - borderWidth: 2, - overflow: "hidden", - }, - scroll: { - backgroundColor: "#0099CC", - borderRadius: 5, - maxHeight: 300, - }, - bottom: { - position: "absolute", - top: 250, - alignItems: "center", - width: "100%", - height: 50, - backgroundColor: "#007FCC88", - }, - box: { - padding: 10, - backgroundColor: "white", - borderBottomLeftRadius: 5, - borderBottomRightRadius: 5, - }, - }; - return ( - SheetManager.show("JRSTraInfo")} - style={styles.touch} - > - - - - 列車遅延速報EX - - - - {getTime - ? getTime.toLocaleTimeString("ja-JP").split(":")[0] + - ":" + - getTime.toLocaleTimeString("ja-JP").split(":")[1] - : NaN} - - { - setLoadingDelayData(true); - }} - /> - - - {loadingDelayData ? ( - - - - ) : delayData ? ( - delayData.map((d, index, array) => { - let data = d.split(" "); - return ( - - - {data[0].replace("\n", "")} - - {data[1]} - {data[3]} - - ); - }) - ) : ( - 現在、5分以上の遅れはありません。 - )} - - - - - - 詳細を見る - - - - - ); -}; From 97a6bbc619c8ebdf486b90a50b408dc7bcd80f17 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 13 Apr 2025 12:41:33 +0000 Subject: [PATCH 10/77] =?UTF-8?q?Carousel=E3=81=A8=E5=88=87=E3=82=8A?= =?UTF-8?q?=E6=9B=BF=E3=81=88=E3=83=9C=E3=82=BF=E3=83=B3=E3=82=92=E5=A4=89?= =?UTF-8?q?=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Menu/Carousel/CarouselBox.tsx | 125 ++++++++++ .../Menu/Carousel/CarouselTypeChanger.tsx | 80 +++++++ menu.js | 216 ++---------------- stateBox/useStationList.tsx | 3 +- 4 files changed, 221 insertions(+), 203 deletions(-) create mode 100644 components/Menu/Carousel/CarouselBox.tsx create mode 100644 components/Menu/Carousel/CarouselTypeChanger.tsx diff --git a/components/Menu/Carousel/CarouselBox.tsx b/components/Menu/Carousel/CarouselBox.tsx new file mode 100644 index 0000000..6f595a6 --- /dev/null +++ b/components/Menu/Carousel/CarouselBox.tsx @@ -0,0 +1,125 @@ +import Sign from "@/components/駅名表/Sign"; +import React, { useEffect, useState } from "react"; +import { AS } from "@/storageControl"; +import { useWindowDimensions, View, LayoutAnimation } from "react-native"; +import Carousel from "react-native-reanimated-carousel"; +import { SheetManager } from "react-native-actions-sheet"; +import { StationNumber } from "../StationPagination"; +import { SimpleDot } from "../SimpleDot"; +export const CarouselBox = ({ + originalStationList, + allStationData, + currentStation, + setSelectedCurrentStation, + carouselRef, + selectedCurrentStation, + navigate, +}) => { + const { height, width } = useWindowDimensions(); + const [dotButton, setDotButton] = useState(false); + const oPSign = () => { + const payload = { + currentStation: allStationData[selectedCurrentStation], + navigate, + goTo: "menu", + //@ts-ignore + useShow: () => SheetManager.show("StationDetailView", { payload }), + onExit: () => SheetManager.hide("StationDetailView"), + }; + //@ts-ignore + SheetManager.show("StationDetailView", { payload }); + }; + const oLPSign = () => { + LayoutAnimation.configureNext({ + duration: 600, + update: { type: "spring", springDamping: 0.5 }, + }); + AS.setItem( + "CarouselSettings/activeDotSettings", + !dotButton ? "true" : "false" + ); + setDotButton(!dotButton); + }; + + useEffect(() => { + AS.getItem("CarouselSettings/activeDotSettings").then((data) => { + setDotButton(data === "true"); + }); + }, []); + return ( + + { + return ( + + + + + + ); + }} + /> + + {originalStationList && + allStationData.map((d, index) => { + const active = index == selectedCurrentStation; + const numberIndex = d[0].StationNumber; + if (dotButton) { + return ( + setSelectedCurrentStation(index)} + currentStation={d} + active={active} + key={numberIndex} + /> + ); + } else { + return ( + setSelectedCurrentStation(index)} + active={active} + key={numberIndex} + /> + ); + } + })} + + + ); +}; diff --git a/components/Menu/Carousel/CarouselTypeChanger.tsx b/components/Menu/Carousel/CarouselTypeChanger.tsx new file mode 100644 index 0000000..776f4d9 --- /dev/null +++ b/components/Menu/Carousel/CarouselTypeChanger.tsx @@ -0,0 +1,80 @@ +import React, { useRef } from "react"; +import { View, TouchableOpacity, Text } from "react-native"; +import Ionicons from "react-native-vector-icons/Ionicons"; + +export const CarouselTypeChanger = ({ locationStatus, position, mapsRef }) => { + return ( + + { + if (!position) return; + const { latitude, longitude } = position.coords; + mapsRef.current.animateToRegion( + { + latitude, + longitude, + latitudeDelta: 0.05, + longitudeDelta: 0.05, + }, + 1000 + ); + }} + > + + + 現在地基準 + + + { + // お気に入りリスト更新 + }} + > + + + お気に入りリスト + + + + ); +}; diff --git a/menu.js b/menu.js index 5cb79d4..48f86a9 100644 --- a/menu.js +++ b/menu.js @@ -1,14 +1,5 @@ import React, { useRef, useState, useEffect } from "react"; -import Carousel from "react-native-reanimated-carousel"; -import { - Platform, - View, - ScrollView, - Text, - TouchableOpacity, - LayoutAnimation, - useWindowDimensions, -} from "react-native"; +import { Platform, View, ScrollView, useWindowDimensions } from "react-native"; import Constants from "expo-constants"; import * as Location from "expo-location"; import { @@ -16,27 +7,23 @@ import { ReanimatedLogLevel, } from "react-native-reanimated"; import StatusbarDetect from "./StatusbarDetect"; -import { Ionicons } from "@expo/vector-icons"; import LED_vision from "./components/発車時刻表/LED_vidion"; -import Sign from "./components/駅名表/Sign"; import { TitleBar } from "./components/Menu/TitleBar"; import { FixedContentBottom } from "./components/Menu/FixedContentBottom"; import { lineList } from "./lib/getStationList"; import useInterval from "./lib/useInterval"; import { useFavoriteStation } from "./stateBox/useFavoriteStation"; -import { SheetManager } from "react-native-actions-sheet"; import { useNavigation } from "@react-navigation/native"; import { useStationList } from "./stateBox/useStationList"; -import { StationNumber } from "./components/Menu/StationPagination"; -import { AS } from "./storageControl"; -import { SimpleDot } from "./components/Menu/SimpleDot"; import { TopMenuButton } from "@/components/Menu/TopMenuButton"; import { JRSTraInfoBox } from "@/components/Menu/JRSTraInfoBox"; import MapView from "react-native-maps"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs"; +import { CarouselBox } from "./components/Menu/Carousel/CarouselBox"; +import { CarouselTypeChanger } from "./components/Menu/Carousel/CarouselTypeChanger"; configureReanimatedLogger({ level: ReanimatedLogLevel.error, // Set the log level to error strict: true, // Reanimated runs in strict mode by default @@ -157,23 +144,6 @@ export default function Menu({ getCurrentTrain, scrollRef }) { }); }, [selectedCurrentStation]); - //全列車ダイヤリストを作成するuseEffect - const oPSign = () => { - const payload = { - currentStation: - originalStationList && - allStationData.length != 0 && - allStationData[selectedCurrentStation], - navigate: navigate, - goTo: "menu", - useShow: () => SheetManager.show("StationDetailView", { payload }), - onExit: () => SheetManager.hide("StationDetailView"), - }; - SheetManager.show("StationDetailView", { payload }); - }; - - const [dotButton, setDotButton] = useState(false); - useEffect(() => { console.log(selectedCurrentStation); if (allStationData.length == 0) return; @@ -190,23 +160,6 @@ export default function Menu({ getCurrentTrain, scrollRef }) { }; mapsRef.current.animateToRegion(mapRegion, 1000); }, [selectedCurrentStation, currentStation, allStationData, mapsRef]); - - useEffect(() => { - AS.getItem("CarouselSettings/activeDotSettings").then((data) => { - setDotButton(data === "true"); - }); - }, []); - const oLPSign = () => { - LayoutAnimation.configureNext({ - duration: 600, - update: { type: "spring", springDamping: 0.5 }, - }); - AS.setItem( - "CarouselSettings/activeDotSettings", - !dotButton ? "true" : "false" - ); - setDotButton(!dotButton); - }; return ( alert("地図をタップ")} /> - - { - if (!position) return; - const { latitude, longitude } = position.coords; - mapsRef.current.animateToRegion( - { - latitude, - longitude, - latitudeDelta: 0.05, - longitudeDelta: 0.05, - }, - 1000 - ); - }} - > - - - 現在地基準 - - - { - // お気に入りリスト更新 - }} - > - - - お気に入りリスト - - - + {allStationData.length != 0 && originalStationList.length != 0 && ( <> - - { - return ( - - - - - - ); - }} - /> - - {originalStationList && - allStationData.map((d, index) => { - const active = index == selectedCurrentStation; - const numberIndex = d[0].StationNumber; - if (dotButton) { - return ( - setSelectedCurrentStation(index)} - currentStation={d} - active={active} - index={numberIndex} - /> - ); - } else { - return ( - setSelectedCurrentStation(index)} - active={active} - index={numberIndex} - /> - ); - } - })} - - + {allStationData[selectedCurrentStation] && ( = ({ children }) => { useEffect(()=>{ if(originalStationList.length === 0) return; const stationList = - originalStationList && lineList.map((d) => originalStationList[d].map((a) => ({ StationNumber: a.StationNumber, StationName: a.Station_JP, })) ); - setStationList(stationList) + setStationList(stationList); },[originalStationList]) return ( From f922edb973bdee883eee6c2a3969dbf2287bc38b Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 13 Apr 2025 13:21:09 +0000 Subject: [PATCH 11/77] =?UTF-8?q?=E4=BD=8D=E7=BD=AE=E6=83=85=E5=A0=B1?= =?UTF-8?q?=E6=A8=A9=E9=99=90=E3=81=AE=E5=8F=96=E5=BE=97=E5=A0=B4=E6=89=80?= =?UTF-8?q?=E3=82=92=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.js | 2 + menu.js | 26 ++---------- stateBox/useTopMenu.tsx | 68 ++++++++++++++++++++++++++++++++ stateBox/useUserPosition.tsx | 76 ++++++++++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+), 23 deletions(-) create mode 100644 stateBox/useTopMenu.tsx create mode 100644 stateBox/useUserPosition.tsx diff --git a/App.js b/App.js index ded91f4..4fec0f5 100644 --- a/App.js +++ b/App.js @@ -18,6 +18,7 @@ import { TrainMenuProvider } from "./stateBox/useTrainMenu"; import { buildProvidersTree } from "./lib/providerTreeProvider"; import { StationListProvider } from "./stateBox/useStationList"; import { NotificationProvider } from "./stateBox/useNotifications"; +import { UserPositionProvider } from "./stateBox/useUserPosition"; LogBox.ignoreLogs([ "ViewPropTypes will be removed", @@ -36,6 +37,7 @@ export default function App() { const ProviderTree = buildProvidersTree([ AllTrainDiagramProvider, NotificationProvider, + UserPositionProvider, StationListProvider, FavoriteStationProvider, TrainDelayDataProvider, diff --git a/menu.js b/menu.js index 48f86a9..faf0d84 100644 --- a/menu.js +++ b/menu.js @@ -1,7 +1,6 @@ import React, { useRef, useState, useEffect } from "react"; import { Platform, View, ScrollView, useWindowDimensions } from "react-native"; import Constants from "expo-constants"; -import * as Location from "expo-location"; import { configureReanimatedLogger, ReanimatedLogLevel, @@ -13,7 +12,6 @@ import { TitleBar } from "./components/Menu/TitleBar"; import { FixedContentBottom } from "./components/Menu/FixedContentBottom"; import { lineList } from "./lib/getStationList"; -import useInterval from "./lib/useInterval"; import { useFavoriteStation } from "./stateBox/useFavoriteStation"; import { useNavigation } from "@react-navigation/native"; import { useStationList } from "./stateBox/useStationList"; @@ -24,6 +22,7 @@ import { useSafeAreaInsets } from "react-native-safe-area-context"; import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs"; import { CarouselBox } from "./components/Menu/Carousel/CarouselBox"; import { CarouselTypeChanger } from "./components/Menu/Carousel/CarouselTypeChanger"; +import { useUserPosition } from "./stateBox/useUserPosition"; configureReanimatedLogger({ level: ReanimatedLogLevel.error, // Set the log level to error strict: true, // Reanimated runs in strict mode by default @@ -54,24 +53,8 @@ export default function Menu({ getCurrentTrain, scrollRef }) { }, 10); }, []); //位置情報 - const [locationStatus, setLocationStatus] = useState(null); - useEffect(() => { - if (Platform.OS == "web") return; - Location.requestForegroundPermissionsAsync().then((data) => { - setLocationStatus( - Platform.OS == "ios" - ? data.status == "granted" - : data.android.accuracy == "fine" - ); - }); - }, []); - const [position, setPosition] = useState(undefined); - const getCurrentPosition = () => { - if (!locationStatus) return () => {}; - Location.getCurrentPositionAsync({}).then((location) => - setPosition(location) - ); - }; + const { position, locationStatus } = useUserPosition(); + useEffect(() => { if (!position) return () => {}; makeCurrentStation(position); @@ -112,9 +95,6 @@ export default function Menu({ getCurrentTrain, scrollRef }) { } }; - useEffect(getCurrentPosition, [locationStatus]); - useInterval(getCurrentPosition, 5000); - const [currentStation, setCurrentStation] = useState(undefined); //第三要素 const carouselRef = useRef(); diff --git a/stateBox/useTopMenu.tsx b/stateBox/useTopMenu.tsx new file mode 100644 index 0000000..b5b35c0 --- /dev/null +++ b/stateBox/useTopMenu.tsx @@ -0,0 +1,68 @@ +import React, { + createContext, + useContext, + useState, + useEffect, + FC, +} from "react"; +import { lineList, getStationList } from "../lib/getStationList"; + +type initialStateType = { + originalStationList: any[][]; + setOriginalStationList: React.Dispatch>; + getStationData: (id: string) => void; + stationList: any[]; +}; +const initialState = { + originalStationList: [[]], + setOriginalStationList: () => {}, + getStationData: () => {}, + stationList: [], +}; + +const TopMenuContext = createContext(initialState); +type Props = { + children: React.ReactNode; +}; +export const useTopMenu = () => { + return useContext(TopMenuContext); +}; + +export const TopMenuProvider: FC = ({ children }) => { + const [originalStationList, setOriginalStationList] = useState([]); + useEffect(() => { + getStationList().then(setOriginalStationList); + }, []); + const getStationData: (name: string) => void = (name) => { + const returnArray = []; + Object.keys(originalStationList).forEach((key) => { + originalStationList[key].forEach((station) => { + if (station.Station_JP === name) { + if (!!station.jslodApi) returnArray.push(station); + } + }); + }); + return returnArray; + }; + const [stationList, setStationList] = useState([[]]); + useEffect(()=>{ + if(originalStationList.length === 0) return; + const stationList = + originalStationList && + lineList.map((d) => + originalStationList[d].map((a) => ({ + StationNumber: a.StationNumber, + StationName: a.Station_JP, + })) + ); + setStationList(stationList) + },[originalStationList]) + + return ( + + {children} + + ); +}; diff --git a/stateBox/useUserPosition.tsx b/stateBox/useUserPosition.tsx new file mode 100644 index 0000000..2b4cb83 --- /dev/null +++ b/stateBox/useUserPosition.tsx @@ -0,0 +1,76 @@ +import React, { + createContext, + useContext, + useState, + useEffect, + FC, +} from "react"; +import { + LocationObject, + requestForegroundPermissionsAsync, + getCurrentPositionAsync, +} from "expo-location"; +import { Platform } from "react-native"; +import useInterval from "@/lib/useInterval"; + +type initialStateType = { + position: LocationObject | undefined; + getCurrentPosition: () => void; + locationStatus: boolean | null; + getLocationPermission: () => void; +}; +const initialState = { + position: undefined, + getCurrentPosition: () => {}, + locationStatus: null, + getLocationPermission: () => {}, +}; + +const UserPositionContext = createContext(initialState); +type Props = { + children: React.ReactNode; +}; +export const useUserPosition = () => { + return useContext(UserPositionContext); +}; + +export const UserPositionProvider: FC = ({ children }) => { + //位置情報 + const [locationStatus, setLocationStatus] = useState(null); + const [position, setPosition] = useState( + undefined + ); + + const getLocationPermission = async () => { + return requestForegroundPermissionsAsync().then((data) => { + setLocationStatus( + Platform.OS == "ios" + ? data.status == "granted" + : data.android.accuracy == "fine" + ); + }); + }; + const getCurrentPosition = () => { + if (!locationStatus) return () => {}; + getCurrentPositionAsync({}).then((location) => setPosition(location)); + }; + useEffect(() => { + if (Platform.OS == "web") return; + getLocationPermission(); + }, []); + useEffect(getCurrentPosition, [locationStatus]); + useInterval(getCurrentPosition, 5000); + + return ( + + {children} + + ); +}; From 3b98882d809bc03e8ef32274b016ba228742946f Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 13 Apr 2025 14:42:59 +0000 Subject: [PATCH 12/77] =?UTF-8?q?=E3=81=8A=E6=B0=97=E3=81=AB=E5=85=A5?= =?UTF-8?q?=E3=82=8A/=E7=8F=BE=E5=9C=A8=E5=9C=B0=E5=88=87=E3=82=8A?= =?UTF-8?q?=E6=9B=BF=E3=81=88=E6=A9=9F=E8=83=BD=E3=82=92=E4=BB=AE=E4=BD=9C?= =?UTF-8?q?=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Menu/Carousel/CarouselTypeChanger.tsx | 51 +++++++++++++++++-- menu.js | 18 +++++-- 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/components/Menu/Carousel/CarouselTypeChanger.tsx b/components/Menu/Carousel/CarouselTypeChanger.tsx index 776f4d9..4f5b3ac 100644 --- a/components/Menu/Carousel/CarouselTypeChanger.tsx +++ b/components/Menu/Carousel/CarouselTypeChanger.tsx @@ -2,7 +2,13 @@ import React, { useRef } from "react"; import { View, TouchableOpacity, Text } from "react-native"; import Ionicons from "react-native-vector-icons/Ionicons"; -export const CarouselTypeChanger = ({ locationStatus, position, mapsRef }) => { +export const CarouselTypeChanger = ({ + locationStatus, + position, + mapsRef, + stationListMode, + setStationListMode,setSelectedCurrentStation +}) => { return ( { alignItems: "center", flexDirection: "row", marginHorizontal: 5, - borderRadius: 30, + borderTopLeftRadius: 20, + borderTopRightRadius: 20, + borderBottomLeftRadius: stationListMode == "position" ? 0 : 20, + borderBottomRightRadius: stationListMode == "position" ? 0 : 20, }} disabled={!locationStatus} onPress={() => { @@ -28,6 +37,7 @@ export const CarouselTypeChanger = ({ locationStatus, position, mapsRef }) => { }, 1000 ); + setStationListMode("position"); }} > { 現在地基準 + { + if (!position) return; + const { latitude, longitude } = position.coords; + mapsRef.current.animateToRegion( + { + latitude, + longitude, + latitudeDelta: 0.05, + longitudeDelta: 0.05, + }, + 1000 + ); + }} + > + + { alignItems: "center", flexDirection: "row", marginHorizontal: 5, - borderRadius: 30, + borderTopLeftRadius: 20, + borderTopRightRadius: 20, + borderBottomLeftRadius: stationListMode == "favorite" ? 0 : 20, + borderBottomRightRadius: stationListMode == "favorite" ? 0 : 20, }} onPress={() => { // お気に入りリスト更新 + setStationListMode("favorite"); + setSelectedCurrentStation(0); }} > diff --git a/menu.js b/menu.js index faf0d84..8778e8c 100644 --- a/menu.js +++ b/menu.js @@ -35,6 +35,7 @@ export default function Menu({ getCurrentTrain, scrollRef }) { const { bottom, left, right, top } = useSafeAreaInsets(); const tabBarHeight = useBottomTabBarHeight(); const [mapsOpacity, setMapsOpacity] = useState(false); + const [stationListMode, setStationListMode] = useState/*<"position"|"favorite">*/("position"); const mapsRef = useRef(null); const MapHeight = height - @@ -62,7 +63,7 @@ export default function Menu({ getCurrentTrain, scrollRef }) { const makeCurrentStation = (location) => { if (!originalStationList) return () => {}; const findStationEachLine = (selectLine) => { - const searchArea = 0.002; + const searchArea = stationListMode == "position" ? 0.1 : 0.002; const _calcDistance = (from, to) => { let lat = Math.abs(from.lat - to.lat); let lng = Math.abs(from.lng - to.lng); @@ -80,7 +81,9 @@ export default function Menu({ getCurrentTrain, scrollRef }) { let returnDataBase = lineList .map((d) => findStationEachLine(originalStationList[d])) - .filter((d) => d.length > 0) + .filter((d) => { + console.log(d); + return d.length > 0}) .reduce((pre, current) => { pre.push(...current); return pre; @@ -102,10 +105,17 @@ export default function Menu({ getCurrentTrain, scrollRef }) { const [allStationData, setAllStationData] = useState([]); useEffect(() => { + if(stationListMode == "position"){ + setAllStationData( + [currentStation].filter((d) => d != undefined) + ); + }else{ setAllStationData( [currentStation, ...favoriteStation].filter((d) => d != undefined) ); - }, [currentStation, favoriteStation]); + + } + }, [currentStation, favoriteStation,stationListMode]); useEffect(() => { if (allStationData.length == 0) { setSelectedCurrentStation(0); @@ -178,7 +188,7 @@ export default function Menu({ getCurrentTrain, scrollRef }) { }} onPress={() => alert("地図をタップ")} /> - + {allStationData.length != 0 && originalStationList.length != 0 && ( <> Date: Sun, 13 Apr 2025 15:43:10 +0000 Subject: [PATCH 13/77] =?UTF-8?q?Sign=E3=82=92ID=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E3=83=99=E3=83=BC=E3=82=B9=E3=81=AB=E7=BD=AE=E3=81=8D=E6=8F=9B?= =?UTF-8?q?=E3=81=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StationDeteilView.js | 2 +- components/Menu/Carousel/CarouselBox.tsx | 2 +- components/駅名表/Sign.js | 59 ++++++++++--------- menu.js | 2 - stateBox/useFavoriteStation.tsx | 4 +- stateBox/useStationList.tsx | 22 +++++-- 6 files changed, 52 insertions(+), 39 deletions(-) diff --git a/components/ActionSheetComponents/StationDeteilView.js b/components/ActionSheetComponents/StationDeteilView.js index 48d67a3..aa8189c 100644 --- a/components/ActionSheetComponents/StationDeteilView.js +++ b/components/ActionSheetComponents/StationDeteilView.js @@ -91,7 +91,7 @@ export const StationDeteilView = (props) => { {currentStation && ( { usePDFView == "true" ? Linking.openURL(currentStation[0].StationTimeTable) diff --git a/components/Menu/Carousel/CarouselBox.tsx b/components/Menu/Carousel/CarouselBox.tsx index 6f595a6..110e66e 100644 --- a/components/Menu/Carousel/CarouselBox.tsx +++ b/components/Menu/Carousel/CarouselBox.tsx @@ -78,7 +78,7 @@ export const CarouselBox = ({ > ; + } + const [currentStationData] = useState(getStationDataFromId(stationID)); const { favoriteStation, setFavoriteStation } = useFavoriteStation(); const [nexPrePosition, setNexPrePosition] = useState(0); const { originalStationList } = useStationList(); @@ -26,48 +31,40 @@ export default function Sign(props) { useLayoutEffect(() => { const isFavorite = favoriteStation.filter((d) => { const compare = JSON.stringify(d); - const current = JSON.stringify(currentStation); - if (compare === current) { - return true; - } else { - return false; - } + const current = JSON.stringify(currentStationData); + return compare === current; }); setTestButtonStatus(isFavorite.length == 0 ? false : true); - }, [favoriteStation, currentStation]); + }, [favoriteStation, currentStationData]); useEffect(() => { const isFavorite = favoriteStation.filter((d) => { const compare = JSON.stringify(d); - const current = JSON.stringify(currentStation); - if (compare === current) { - return true; - } else { - return false; - } + const current = JSON.stringify(currentStationData); + return compare === current; }); setTestButtonStatus(isFavorite.length == 0 ? false : true); - }, [favoriteStation, currentStation]); + }, [favoriteStation, currentStationData]); useInterval(() => { - if (currentStation.length == 1) { + if (currentStationData.length == 1) { setNexPrePosition(0); return () => {}; } setNexPrePosition( - nexPrePosition + 1 == currentStation.length ? 0 : nexPrePosition + 1 + nexPrePosition + 1 == currentStationData.length ? 0 : nexPrePosition + 1 ); }, 2000); useEffect(() => { setNexPrePosition(0); - getPreNextStation(currentStation[0]); - if (currentStation.length == 1) return () => {}; - getPreNextStation(currentStation[1]); - }, [currentStation]); + getPreNextStation(currentStationData[0]); + if (currentStationData.length == 1) return () => {}; + getPreNextStation(currentStationData[1]); + }, [currentStationData]); useEffect(() => { - if (!currentStation[nexPrePosition]) return () => {}; - getPreNextStation(currentStation[nexPrePosition]); + if (!currentStationData[nexPrePosition]) return () => {}; + getPreNextStation(currentStationData[nexPrePosition]); }, [nexPrePosition]); const getPreNextStation = (now) => { const lineList = [ @@ -101,20 +98,20 @@ export default function Sign(props) { if (returnData[1]) setNexStation(returnData[1]); } }; - const isMatsuyama = currentStation[0].StationNumber == "Y55"; + const isMatsuyama = currentStationData[0].StationNumber == "Y55"; //const isMatsuyama = true; const favoliteChanger = () => { if (testButtonStatus) { const otherData = favoriteStation.filter((d) => { const compare = JSON.stringify(d); - const current = JSON.stringify(currentStation); + const current = JSON.stringify(currentStationData); return compare !== current; }); AS.setItem("favoriteStation", JSON.stringify(otherData)); setFavoriteStation(otherData); } else { let ret = favoriteStation; - ret.push(currentStation); + ret.push(currentStationData); AS.setItem("favoriteStation", JSON.stringify(ret)); setFavoriteStation(ret); } @@ -138,8 +135,12 @@ export default function Sign(props) { source={require("../../assets/StationSign.json")} /> )} - - + + {isCurrentStation ? ( - + ); } diff --git a/menu.js b/menu.js index 8778e8c..c41aa4d 100644 --- a/menu.js +++ b/menu.js @@ -82,7 +82,6 @@ export default function Menu({ getCurrentTrain, scrollRef }) { let returnDataBase = lineList .map((d) => findStationEachLine(originalStationList[d])) .filter((d) => { - console.log(d); return d.length > 0}) .reduce((pre, current) => { pre.push(...current); @@ -135,7 +134,6 @@ export default function Menu({ getCurrentTrain, scrollRef }) { }, [selectedCurrentStation]); useEffect(() => { - console.log(selectedCurrentStation); if (allStationData.length == 0) return; if (allStationData[selectedCurrentStation] == undefined) return; const { lat, lng } = diff --git a/stateBox/useFavoriteStation.tsx b/stateBox/useFavoriteStation.tsx index dbc09d2..d4f5893 100644 --- a/stateBox/useFavoriteStation.tsx +++ b/stateBox/useFavoriteStation.tsx @@ -29,10 +29,10 @@ type Props = { }; export const FavoriteStationProvider:FC = ({ children }) => { const [favoriteStation, setFavoriteStation] = useState([]); - const { getStationData } = useStationList(); + const { getStationDataFromName } = useStationList(); const lodAddMigration = () => { const migration = favoriteStation.map((d) => { - return getStationData(d[0].Station_JP); + return getStationDataFromName(d[0].Station_JP); }); setFavoriteStation(migration); }; diff --git a/stateBox/useStationList.tsx b/stateBox/useStationList.tsx index f05d8d1..cc44ce4 100644 --- a/stateBox/useStationList.tsx +++ b/stateBox/useStationList.tsx @@ -10,13 +10,15 @@ import { lineList, getStationList } from "../lib/getStationList"; type initialStateType = { originalStationList: any[][]; setOriginalStationList: React.Dispatch>; - getStationData: (id: string) => void; + getStationDataFromName: (id: string) => any[]; + getStationDataFromId: (id: string) => any[]; stationList: any[]; }; const initialState = { originalStationList: [[]], setOriginalStationList: () => {}, - getStationData: () => {}, + getStationDataFromName: () => [], + getStationDataFromId: () => [], stationList: [], }; @@ -33,7 +35,19 @@ export const StationListProvider: FC = ({ children }) => { useEffect(() => { getStationList().then(setOriginalStationList); }, []); - const getStationData: (name: string) => void = (name) => { + const getStationDataFromId: (id: string) => any[] = (id) => { + console.log("id", id); + let returnArray = []; + Object.keys(originalStationList).forEach((key) => { + originalStationList[key].forEach((station) => { + if (station.StationNumber === id) { + returnArray = [...returnArray, ...getStationDataFromName(station.Station_JP)]; + } + }); + }); + return returnArray; + }; + const getStationDataFromName: (name: string) => any[] = (name) => { const returnArray = []; Object.keys(originalStationList).forEach((key) => { originalStationList[key].forEach((station) => { @@ -59,7 +73,7 @@ export const StationListProvider: FC = ({ children }) => { return ( {children} From 6d51db98fa39ae8ca178992f179d0bcadd850dc4 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 13 Apr 2025 15:48:25 +0000 Subject: [PATCH 14/77] =?UTF-8?q?=E5=BE=AE=E8=AA=BF=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/駅名表/StationNumberMaker.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/components/駅名表/StationNumberMaker.tsx b/components/駅名表/StationNumberMaker.tsx index dbeef0e..bd38e40 100644 --- a/components/駅名表/StationNumberMaker.tsx +++ b/components/駅名表/StationNumberMaker.tsx @@ -1,10 +1,11 @@ import React from "react"; import { Text, View } from "react-native"; -import { widthPercentageToDP as wp } from "react-native-responsive-screen"; +import { useWindowDimensions } from "react-native"; import lineColorList from "../../assets/originData/lineColorList"; export const StationNumberMaker = (props) => { const { currentStation, isMatsuyama } = props; + const { width } = useWindowDimensions(); const getTop = (array: number[], index: number) => { if (array.length == 1) return 20; else if (index == 0) return 5; @@ -24,8 +25,8 @@ export const StationNumberMaker = (props) => { alignItems: "center", top: `${getTop(array, index)}%`, right: "10%", - width: wp("10%"), - height: wp("10%"), + width: (width / 100 * 10), + height: (width / 100 * 10), borderColor: lineColorList[lineID], backgroundColor: "white", borderWidth: parseInt("3%"), From 2c505c4b17b266cc39eb2de27e137f4f69abd25a Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 13 Apr 2025 16:17:15 +0000 Subject: [PATCH 15/77] =?UTF-8?q?=E8=BF=91=E3=81=8F=E3=81=AE=E9=A7=85?= =?UTF-8?q?=E3=81=AE=E6=83=85=E5=A0=B1=E3=81=8C=E3=81=A8=E3=82=8A=E3=81=82?= =?UTF-8?q?=E3=81=88=E3=81=9A=E5=87=BA=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= =?UTF-8?q?=E3=81=AA=E3=81=A3=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- menu.js | 33 ++++++++++++++++++++++----------- stateBox/useStationList.tsx | 1 - 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/menu.js b/menu.js index c41aa4d..015f5cb 100644 --- a/menu.js +++ b/menu.js @@ -35,7 +35,9 @@ export default function Menu({ getCurrentTrain, scrollRef }) { const { bottom, left, right, top } = useSafeAreaInsets(); const tabBarHeight = useBottomTabBarHeight(); const [mapsOpacity, setMapsOpacity] = useState(false); - const [stationListMode, setStationListMode] = useState/*<"position"|"favorite">*/("position"); + const [stationListMode, setStationListMode] = useState( + /*<"position"|"favorite">*/ "position" + ); const mapsRef = useRef(null); const MapHeight = height - @@ -59,11 +61,11 @@ export default function Menu({ getCurrentTrain, scrollRef }) { useEffect(() => { if (!position) return () => {}; makeCurrentStation(position); - }, [position]); + }, [position, stationListMode]); const makeCurrentStation = (location) => { if (!originalStationList) return () => {}; const findStationEachLine = (selectLine) => { - const searchArea = stationListMode == "position" ? 0.1 : 0.002; + const searchArea = stationListMode == "position" ? 0.07 : 0.002; const _calcDistance = (from, to) => { let lat = Math.abs(from.lat - to.lat); let lng = Math.abs(from.lng - to.lng); @@ -104,17 +106,17 @@ export default function Menu({ getCurrentTrain, scrollRef }) { const [allStationData, setAllStationData] = useState([]); useEffect(() => { - if(stationListMode == "position"){ + if (stationListMode == "position") { + console.log(currentStation); setAllStationData( [currentStation].filter((d) => d != undefined) ); - }else{ - setAllStationData( - [currentStation, ...favoriteStation].filter((d) => d != undefined) - ); - + } else { + setAllStationData( + [currentStation, ...favoriteStation].filter((d) => d != undefined) + ); } - }, [currentStation, favoriteStation,stationListMode]); + }, [currentStation, favoriteStation, stationListMode]); useEffect(() => { if (allStationData.length == 0) { setSelectedCurrentStation(0); @@ -186,7 +188,16 @@ export default function Menu({ getCurrentTrain, scrollRef }) { }} onPress={() => alert("地図をタップ")} /> - + {allStationData.length != 0 && originalStationList.length != 0 && ( <> = ({ children }) => { getStationList().then(setOriginalStationList); }, []); const getStationDataFromId: (id: string) => any[] = (id) => { - console.log("id", id); let returnArray = []; Object.keys(originalStationList).forEach((key) => { originalStationList[key].forEach((station) => { From 748350178de46b25de3777caddaad06de663f28f Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 13 Apr 2025 16:31:11 +0000 Subject: [PATCH 16/77] =?UTF-8?q?=E5=B0=8F=E3=81=95=E3=81=AA=E3=83=9F?= =?UTF-8?q?=E3=82=B9=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Menu/Carousel/CarouselBox.tsx | 4 ++-- menu.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/Menu/Carousel/CarouselBox.tsx b/components/Menu/Carousel/CarouselBox.tsx index 110e66e..3a54a9a 100644 --- a/components/Menu/Carousel/CarouselBox.tsx +++ b/components/Menu/Carousel/CarouselBox.tsx @@ -106,7 +106,7 @@ export const CarouselBox = ({ onPress={() => setSelectedCurrentStation(index)} currentStation={d} active={active} - key={numberIndex} + key={numberIndex + index} /> ); } else { @@ -114,7 +114,7 @@ export const CarouselBox = ({ setSelectedCurrentStation(index)} active={active} - key={numberIndex} + key={numberIndex + index} /> ); } diff --git a/menu.js b/menu.js index 015f5cb..09a7fdb 100644 --- a/menu.js +++ b/menu.js @@ -113,7 +113,7 @@ export default function Menu({ getCurrentTrain, scrollRef }) { ); } else { setAllStationData( - [currentStation, ...favoriteStation].filter((d) => d != undefined) + favoriteStation.filter((d) => d != undefined) ); } }, [currentStation, favoriteStation, stationListMode]); From 35bb460b54dd208075e67af5f9488b02dce1ac67 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 13 Apr 2025 16:54:02 +0000 Subject: [PATCH 17/77] =?UTF-8?q?CarouselBox=E3=82=B3=E3=83=B3=E3=83=9D?= =?UTF-8?q?=E3=83=BC=E3=83=8D=E3=83=B3=E3=83=88=E3=81=AErenderItem?= =?UTF-8?q?=E9=96=A2=E6=95=B0=E3=82=92=E5=88=86=E9=9B=A2=E3=81=97=E3=80=81?= =?UTF-8?q?Menu=E3=82=B3=E3=83=B3=E3=83=9D=E3=83=BC=E3=83=8D=E3=83=B3?= =?UTF-8?q?=E3=83=88=E3=81=A7=E3=81=AEcurrentStation=E3=81=AE=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E3=82=92nearPositionStation=E3=81=AB=E5=A4=89?= =?UTF-8?q?=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Menu/Carousel/CarouselBox.tsx | 81 ++++++++++++------------ menu.js | 33 ++++------ 2 files changed, 53 insertions(+), 61 deletions(-) diff --git a/components/Menu/Carousel/CarouselBox.tsx b/components/Menu/Carousel/CarouselBox.tsx index 3a54a9a..1315417 100644 --- a/components/Menu/Carousel/CarouselBox.tsx +++ b/components/Menu/Carousel/CarouselBox.tsx @@ -46,6 +46,29 @@ export const CarouselBox = ({ setDotButton(data === "true"); }); }, []); + const RenderItem = ({ item, index }) => { + return ( + + + + + + ); + }; return ( { - return ( - - - - - - ); - }} + renderItem={RenderItem} /> { const active = index == selectedCurrentStation; - const numberIndex = d[0].StationNumber; - if (dotButton) { - return ( - setSelectedCurrentStation(index)} - currentStation={d} - active={active} - key={numberIndex + index} - /> - ); - } else { - return ( - setSelectedCurrentStation(index)} - active={active} - key={numberIndex + index} - /> - ); - } + const numberKey = d[0].StationNumber + index; + return dotButton ? ( + setSelectedCurrentStation(index)} + currentStation={d} + active={active} + key={numberKey} + /> + ) : ( + setSelectedCurrentStation(index)} + active={active} + key={numberKey} + /> + ); })} diff --git a/menu.js b/menu.js index 09a7fdb..35460e5 100644 --- a/menu.js +++ b/menu.js @@ -84,7 +84,8 @@ export default function Menu({ getCurrentTrain, scrollRef }) { let returnDataBase = lineList .map((d) => findStationEachLine(originalStationList[d])) .filter((d) => { - return d.length > 0}) + return d.length > 0; + }) .reduce((pre, current) => { pre.push(...current); return pre; @@ -92,14 +93,14 @@ export default function Menu({ getCurrentTrain, scrollRef }) { if (returnDataBase.length) { let currentStation = currentStation == undefined ? [] : currentStation; if (currentStation.toString() != returnDataBase.toString()) { - setCurrentStation(returnDataBase); + setNearPositionStation(returnDataBase); } } else { - setCurrentStation(undefined); + setNearPositionStation(undefined); } }; - const [currentStation, setCurrentStation] = useState(undefined); //第三要素 + const [nearPositionStation, setNearPositionStation] = useState(undefined); //第三要素 const carouselRef = useRef(); const [selectedCurrentStation, setSelectedCurrentStation] = useState(0); @@ -107,16 +108,12 @@ export default function Menu({ getCurrentTrain, scrollRef }) { const [allStationData, setAllStationData] = useState([]); useEffect(() => { if (stationListMode == "position") { - console.log(currentStation); - setAllStationData( - [currentStation].filter((d) => d != undefined) - ); + console.log(nearPositionStation); + setAllStationData([nearPositionStation].filter((d) => d != undefined)); } else { - setAllStationData( - favoriteStation.filter((d) => d != undefined) - ); + setAllStationData(favoriteStation.filter((d) => d != undefined)); } - }, [currentStation, favoriteStation, stationListMode]); + }, [nearPositionStation, favoriteStation, stationListMode]); useEffect(() => { if (allStationData.length == 0) { setSelectedCurrentStation(0); @@ -126,7 +123,7 @@ export default function Menu({ getCurrentTrain, scrollRef }) { const count = selectedCurrentStation - 1; setSelectedCurrentStation(count); } - }, [selectedCurrentStation, currentStation, allStationData]); + }, [selectedCurrentStation, nearPositionStation, allStationData]); useEffect(() => { if (!carouselRef.current) return; carouselRef?.current.scrollTo({ @@ -136,12 +133,10 @@ export default function Menu({ getCurrentTrain, scrollRef }) { }, [selectedCurrentStation]); useEffect(() => { + if (originalStationList == undefined) return; if (allStationData.length == 0) return; if (allStationData[selectedCurrentStation] == undefined) return; - const { lat, lng } = - originalStationList && - allStationData[selectedCurrentStation] && - allStationData[selectedCurrentStation][0]; + const { lat, lng } = allStationData[selectedCurrentStation][0]; const mapRegion = { latitude: lat, longitude: lng, @@ -149,7 +144,7 @@ export default function Menu({ getCurrentTrain, scrollRef }) { longitudeDelta: 0.05, }; mapsRef.current.animateToRegion(mapRegion, 1000); - }, [selectedCurrentStation, currentStation, allStationData, mapsRef]); + }, [selectedCurrentStation, nearPositionStation, allStationData, mapsRef]); return ( Date: Sun, 13 Apr 2025 16:56:47 +0000 Subject: [PATCH 18/77] =?UTF-8?q?menu=E3=81=AE=E5=A4=89=E6=95=B0=E5=90=8D?= =?UTF-8?q?=E3=82=92=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- menu.js | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/menu.js b/menu.js index 35460e5..1392e8c 100644 --- a/menu.js +++ b/menu.js @@ -103,40 +103,40 @@ export default function Menu({ getCurrentTrain, scrollRef }) { const [nearPositionStation, setNearPositionStation] = useState(undefined); //第三要素 const carouselRef = useRef(); - const [selectedCurrentStation, setSelectedCurrentStation] = useState(0); + const [listIndex, setListIndex] = useState(0); - const [allStationData, setAllStationData] = useState([]); + const [listUpStation, setListUpStation] = useState([]); useEffect(() => { if (stationListMode == "position") { console.log(nearPositionStation); - setAllStationData([nearPositionStation].filter((d) => d != undefined)); + setListUpStation([nearPositionStation].filter((d) => d != undefined)); } else { - setAllStationData(favoriteStation.filter((d) => d != undefined)); + setListUpStation(favoriteStation.filter((d) => d != undefined)); } }, [nearPositionStation, favoriteStation, stationListMode]); useEffect(() => { - if (allStationData.length == 0) { - setSelectedCurrentStation(0); + if (listUpStation.length == 0) { + setListIndex(0); return; } - if (allStationData[selectedCurrentStation] == undefined) { - const count = selectedCurrentStation - 1; - setSelectedCurrentStation(count); + if (listUpStation[listIndex] == undefined) { + const count = listIndex - 1; + setListIndex(count); } - }, [selectedCurrentStation, nearPositionStation, allStationData]); + }, [listIndex, nearPositionStation, listUpStation]); useEffect(() => { if (!carouselRef.current) return; carouselRef?.current.scrollTo({ - count: selectedCurrentStation - carouselRef.current.getCurrentIndex(), + count: listIndex - carouselRef.current.getCurrentIndex(), animated: true, }); - }, [selectedCurrentStation]); + }, [listIndex]); useEffect(() => { if (originalStationList == undefined) return; - if (allStationData.length == 0) return; - if (allStationData[selectedCurrentStation] == undefined) return; - const { lat, lng } = allStationData[selectedCurrentStation][0]; + if (listUpStation.length == 0) return; + if (listUpStation[listIndex] == undefined) return; + const { lat, lng } = listUpStation[listIndex][0]; const mapRegion = { latitude: lat, longitude: lng, @@ -144,7 +144,7 @@ export default function Menu({ getCurrentTrain, scrollRef }) { longitudeDelta: 0.05, }; mapsRef.current.animateToRegion(mapRegion, 1000); - }, [selectedCurrentStation, nearPositionStation, allStationData, mapsRef]); + }, [listIndex, nearPositionStation, listUpStation, mapsRef]); return ( - {allStationData.length != 0 && originalStationList.length != 0 && ( + {listUpStation.length != 0 && originalStationList.length != 0 && ( <> - {allStationData[selectedCurrentStation] && ( + {listUpStation[listIndex] && ( {}} From 015e4e54edde3c6be1f84508c594fab104aebe2b Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 13 Apr 2025 17:24:35 +0000 Subject: [PATCH 19/77] =?UTF-8?q?=E7=8F=BE=E5=9C=A8=E5=9C=B0=E5=9F=BA?= =?UTF-8?q?=E6=BA=96=E3=81=AE=E5=BD=93=E8=A9=B2=E9=A7=85=E3=82=92=E8=A4=87?= =?UTF-8?q?=E6=95=B0=E8=A1=A8=E7=A4=BA=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- menu.js | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/menu.js b/menu.js index 1392e8c..9732fa4 100644 --- a/menu.js +++ b/menu.js @@ -55,9 +55,9 @@ export default function Menu({ getCurrentTrain, scrollRef }) { } }, 10); }, []); - //位置情報 - const { position, locationStatus } = useUserPosition(); + //現在地基準の駅名標リストアップ機能 + const { position, locationStatus } = useUserPosition(); useEffect(() => { if (!position) return () => {}; makeCurrentStation(position); @@ -65,7 +65,7 @@ export default function Menu({ getCurrentTrain, scrollRef }) { const makeCurrentStation = (location) => { if (!originalStationList) return () => {}; const findStationEachLine = (selectLine) => { - const searchArea = stationListMode == "position" ? 0.07 : 0.002; + const searchArea = 0.12; const _calcDistance = (from, to) => { let lat = Math.abs(from.lat - to.lat); let lng = Math.abs(from.lng - to.lng); @@ -78,11 +78,26 @@ export default function Menu({ getCurrentTrain, scrollRef }) { lng: location.coords.longitude, }) < searchArea ); + //NearStationを距離の近い順にソート + NearStation.sort((a, b) => { + return ( + _calcDistance(a, { + lat: location.coords.latitude, + lng: location.coords.longitude, + }) - + _calcDistance(b, { + lat: location.coords.latitude, + lng: location.coords.longitude, + }) + ); + }); return NearStation; }; let returnDataBase = lineList - .map((d) => findStationEachLine(originalStationList[d])) + .map((d) => { + return findStationEachLine(originalStationList[d]); + }) .filter((d) => { return d.length > 0; }) @@ -90,17 +105,16 @@ export default function Menu({ getCurrentTrain, scrollRef }) { pre.push(...current); return pre; }, []); + if (returnDataBase.length) { - let currentStation = currentStation == undefined ? [] : currentStation; - if (currentStation.toString() != returnDataBase.toString()) { - setNearPositionStation(returnDataBase); - } + const returnData = returnDataBase.map((d) => [d]); + setNearPositionStation(returnData); } else { - setNearPositionStation(undefined); + setNearPositionStation([]); } }; - const [nearPositionStation, setNearPositionStation] = useState(undefined); //第三要素 + const [nearPositionStation, setNearPositionStation] = useState([]); //第三要素 const carouselRef = useRef(); const [listIndex, setListIndex] = useState(0); @@ -108,8 +122,7 @@ export default function Menu({ getCurrentTrain, scrollRef }) { const [listUpStation, setListUpStation] = useState([]); useEffect(() => { if (stationListMode == "position") { - console.log(nearPositionStation); - setListUpStation([nearPositionStation].filter((d) => d != undefined)); + setListUpStation(nearPositionStation.filter((d) => d != undefined)); } else { setListUpStation(favoriteStation.filter((d) => d != undefined)); } From f26da93193d122e96dc6663cdff620822c69cd7c Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 13 Apr 2025 18:06:22 +0000 Subject: [PATCH 20/77] =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E3=81=AE?= =?UTF-8?q?=E6=95=B4=E7=90=86=E3=81=A8useCurrentTrain=E3=81=AE=E5=8F=96?= =?UTF-8?q?=E5=BE=97=E3=83=AB=E3=83=BC=E3=83=88=E3=81=AE=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MenuPage.js | 4 +-- components/Menu/Carousel/CarouselBox.tsx | 37 +++++++++++++--------- components/発車時刻表/LED_vidion.js | 21 ++++++------- menu.js | 39 ++++++------------------ 4 files changed, 42 insertions(+), 59 deletions(-) diff --git a/MenuPage.js b/MenuPage.js index 8c11bda..b3a20e7 100644 --- a/MenuPage.js +++ b/MenuPage.js @@ -15,7 +15,6 @@ import Setting from "./components/Settings/settings"; import { useFavoriteStation } from "./stateBox/useFavoriteStation"; import { optionData } from "./lib/stackOption"; import AllTrainDiagramView from "./components/AllTrainDiagramView"; -import { useCurrentTrain } from "./stateBox/useCurrentTrain"; import { useNavigation } from "@react-navigation/native"; import { news } from "./config/newsUpdate"; import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs"; @@ -25,7 +24,6 @@ export function MenuPage() { const { favoriteStation, setFavoriteStation } = useFavoriteStation(); const { height, width } = useWindowDimensions(); const tabBarHeight = useBottomTabBarHeight(); - const { getCurrentTrain } = useCurrentTrain(); const navigation = useNavigation(); const { addListener } = navigation; useEffect(() => { @@ -86,7 +84,7 @@ export function MenuPage() { headerTransparent: true, }} children={() => ( - + )} /> diff --git a/components/Menu/Carousel/CarouselBox.tsx b/components/Menu/Carousel/CarouselBox.tsx index 1315417..950acec 100644 --- a/components/Menu/Carousel/CarouselBox.tsx +++ b/components/Menu/Carousel/CarouselBox.tsx @@ -1,25 +1,25 @@ import Sign from "@/components/駅名表/Sign"; -import React, { useEffect, useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import { AS } from "@/storageControl"; import { useWindowDimensions, View, LayoutAnimation } from "react-native"; -import Carousel from "react-native-reanimated-carousel"; +import Carousel, { ICarouselInstance } from "react-native-reanimated-carousel"; import { SheetManager } from "react-native-actions-sheet"; import { StationNumber } from "../StationPagination"; import { SimpleDot } from "../SimpleDot"; export const CarouselBox = ({ originalStationList, - allStationData, - currentStation, - setSelectedCurrentStation, - carouselRef, - selectedCurrentStation, + listUpStation, + nearPositionStation, + setListIndex, + listIndex, navigate, }) => { + const carouselRef = useRef(null); const { height, width } = useWindowDimensions(); const [dotButton, setDotButton] = useState(false); const oPSign = () => { const payload = { - currentStation: allStationData[selectedCurrentStation], + currentStation: listUpStation[listIndex], navigate, goTo: "menu", //@ts-ignore @@ -46,6 +46,13 @@ export const CarouselBox = ({ setDotButton(data === "true"); }); }, []); + useEffect(() => { + if (!carouselRef.current) return; + carouselRef?.current.scrollTo({ + count: listIndex - carouselRef.current.getCurrentIndex(), + animated: true, + }); + }, [listIndex]); const RenderItem = ({ item, index }) => { return ( @@ -73,7 +80,7 @@ export const CarouselBox = ({ {originalStationList && - allStationData.map((d, index) => { - const active = index == selectedCurrentStation; + listUpStation.map((d, index) => { + const active = index == listIndex; const numberKey = d[0].StationNumber + index; return dotButton ? ( setSelectedCurrentStation(index)} + onPress={() => setListIndex(index)} currentStation={d} active={active} key={numberKey} /> ) : ( setSelectedCurrentStation(index)} + onPress={() => setListIndex(index)} active={active} key={numberKey} /> diff --git a/components/発車時刻表/LED_vidion.js b/components/発車時刻表/LED_vidion.js index 3b4e86f..2ebce12 100644 --- a/components/発車時刻表/LED_vidion.js +++ b/components/発車時刻表/LED_vidion.js @@ -42,44 +42,43 @@ import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram"; * 9062D 四国まんなか千年ものがたり(臨時?) */ export default function LED_vision(props) { - const { station, getCurrentTrain, navigate, openStationACFromEachTrainInfo } = - props; - const { currentTrain } = useCurrentTrain(); + const { station, navigate, openStationACFromEachTrainInfo } = props; + const { getCurrentTrain, 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: trainDiagram } = useAllTrainDiagram(); + const { allTrainDiagram } = useAllTrainDiagram(); useEffect(() => { AS.getItem("LEDSettings/trainIDSwitch").then((data) => { setTrainIDSwitch(data === "true"); }); AS.getItem("LEDSettings/trainDescriptionSwitch").then((data) => { - setTrainDescriptionSwitch(data == "true"); + setTrainDescriptionSwitch(data === "true"); }); AS.getItem("LEDSettings/finalSwitch").then((data) => { - setFinalSwitch(data == "true"); + setFinalSwitch(data === "true"); }); }, []); useEffect(() => { // 現在の駅に停車するダイヤを作成する副作用[列車ダイヤと現在駅情報] - if (!trainDiagram) { + if (!allTrainDiagram) { setStationDiagram({}); return; } let returnData = {}; - Object.keys(trainDiagram).forEach((key) => { - if (trainDiagram[key].match(station[0].Station_JP + ",")) { - returnData[key] = trainDiagram[key]; + 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))); - }, [trainDiagram, station]); + }, [allTrainDiagram, station]); const [trainTimeAndNumber, setTrainTimeAndNumber] = useState(null); diff --git a/menu.js b/menu.js index 9732fa4..393a305 100644 --- a/menu.js +++ b/menu.js @@ -27,7 +27,7 @@ configureReanimatedLogger({ level: ReanimatedLogLevel.error, // Set the log level to error strict: true, // Reanimated runs in strict mode by default }); -export default function Menu({ getCurrentTrain, scrollRef }) { +export default function Menu({scrollRef }) { const { navigate, addListener, isFocused } = useNavigation(); const { favoriteStation } = useFavoriteStation(); const { originalStationList } = useStationList(); @@ -95,28 +95,17 @@ export default function Menu({ getCurrentTrain, scrollRef }) { }; let returnDataBase = lineList - .map((d) => { - return findStationEachLine(originalStationList[d]); - }) - .filter((d) => { - return d.length > 0; - }) + .map((d) => findStationEachLine(originalStationList[d])) + .filter((d) => d.length > 0) .reduce((pre, current) => { pre.push(...current); return pre; - }, []); - - if (returnDataBase.length) { - const returnData = returnDataBase.map((d) => [d]); - setNearPositionStation(returnData); - } else { - setNearPositionStation([]); - } + }, []).map((d) => [d]); + setNearPositionStation(returnDataBase.length ? returnDataBase : []); }; const [nearPositionStation, setNearPositionStation] = useState([]); //第三要素 - const carouselRef = useRef(); const [listIndex, setListIndex] = useState(0); const [listUpStation, setListUpStation] = useState([]); @@ -137,14 +126,6 @@ export default function Menu({ getCurrentTrain, scrollRef }) { setListIndex(count); } }, [listIndex, nearPositionStation, listUpStation]); - useEffect(() => { - if (!carouselRef.current) return; - carouselRef?.current.scrollTo({ - count: listIndex - carouselRef.current.getCurrentIndex(), - animated: true, - }); - }, [listIndex]); - useEffect(() => { if (originalStationList == undefined) return; if (listUpStation.length == 0) return; @@ -211,18 +192,16 @@ export default function Menu({ getCurrentTrain, scrollRef }) { {listUpStation[listIndex] && ( {}} /> From 427e06967c8614e21c2a4531e292ed94ec9fb491 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 13 Apr 2025 19:16:58 +0000 Subject: [PATCH 21/77] =?UTF-8?q?LED=E3=81=ABkey=E3=82=92=E4=BB=98?= =?UTF-8?q?=E4=B8=8E=E3=81=97=E3=81=A6=E3=83=87=E3=83=BC=E3=82=BF=E3=81=AE?= =?UTF-8?q?=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/発車時刻表/EachData.tsx | 25 ++++++++------- .../LED_Vision_Component/Header.js | 4 +-- components/発車時刻表/LED_vidion.js | 31 ++++++++++--------- 3 files changed, 32 insertions(+), 28 deletions(-) diff --git a/components/発車時刻表/EachData.tsx b/components/発車時刻表/EachData.tsx index 84c47e4..c3dce10 100644 --- a/components/発車時刻表/EachData.tsx +++ b/components/発車時刻表/EachData.tsx @@ -122,21 +122,21 @@ export const EachData: FC = (props) => { = (props) => { flexDirection: "row", }} onPress={() => openTrainInfo(d)} + key={ d.train + "-eachData" } > = (props) => { /> )} {trainDescriptionSwitch && !!train.info && ( - + )} ); diff --git a/components/発車時刻表/LED_Vision_Component/Header.js b/components/発車時刻表/LED_Vision_Component/Header.js index 392ed13..274b9c8 100644 --- a/components/発車時刻表/LED_Vision_Component/Header.js +++ b/components/発車時刻表/LED_Vision_Component/Header.js @@ -3,8 +3,8 @@ import { useCurrentTrain } from "../../../stateBox/useCurrentTrain"; import LottieView from "lottie-react-native"; import { Ionicons } from "@expo/vector-icons"; -export const Header = ({ getCurrentTrain }) => { - const { currentTrainLoading, setCurrentTrainLoading } = useCurrentTrain(); +export const Header = () => { + const { currentTrainLoading, setCurrentTrainLoading,getCurrentTrain } = useCurrentTrain(); return ( areaStationID.includes(s.StationNumber))); }, [allTrainDiagram, station]); - const [trainTimeAndNumber, setTrainTimeAndNumber] = useState(null); + /* +{lastStation: "当駅止", time: "12:34", train: "1234M"} + */ + const [trainTimeAndNumber, setTrainTimeAndNumber] = useState([]); useEffect(() => { //現在の駅に停車する列車から時刻を切り出してLEDベースにフォーマット @@ -141,16 +144,15 @@ export default function LED_vision(props) { }; const timeFiltering = (d) => { - const date = new Date(); - const newDate = new Date(); - let data = d.time.split(":"); + const date = dayjs(); + const newDate = 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; - date.setHours(parseInt(data[0])); - date.setMinutes(parseInt(data[1]) + parseInt(delay)); - return !(newDate > date); + date.hour(parseInt(h)).minute(parseInt(m) + parseInt(delay)); + return !(newDate.isAfter(date)); }; const [areaString, setAreaString] = useState(""); @@ -182,18 +184,19 @@ export default function LED_vision(props) { } setAreaStringLength(areaInfo.length); }, [areaInfo]); - + const { width } = useWindowDimensions(); + const adjustedWidth = width * 0.98; return ( -
+
{selectedTrain.map((d) => ( Date: Sun, 13 Apr 2025 19:46:15 +0000 Subject: [PATCH 22/77] =?UTF-8?q?=E3=83=9E=E3=83=83=E3=83=97=E3=81=AE?= =?UTF-8?q?=E7=A7=BB=E5=8B=95=E6=A9=9F=E8=83=BD=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Menu/Carousel/CarouselTypeChanger.tsx | 37 ++++++++------ menu.js | 51 ++++++++++++++----- 2 files changed, 58 insertions(+), 30 deletions(-) diff --git a/components/Menu/Carousel/CarouselTypeChanger.tsx b/components/Menu/Carousel/CarouselTypeChanger.tsx index 4f5b3ac..a41b8da 100644 --- a/components/Menu/Carousel/CarouselTypeChanger.tsx +++ b/components/Menu/Carousel/CarouselTypeChanger.tsx @@ -1,5 +1,5 @@ import React, { useRef } from "react"; -import { View, TouchableOpacity, Text } from "react-native"; +import { View, TouchableOpacity, Text, LayoutAnimation } from "react-native"; import Ionicons from "react-native-vector-icons/Ionicons"; export const CarouselTypeChanger = ({ @@ -7,8 +7,24 @@ export const CarouselTypeChanger = ({ position, mapsRef, stationListMode, - setStationListMode,setSelectedCurrentStation + setStationListMode, + setSelectedCurrentStation, + setMapMode, }) => { + const returnToDefaultMode = ()=>{ + LayoutAnimation.configureNext({ + duration: 300, + create: { + type: LayoutAnimation.Types.easeInEaseOut, + property: LayoutAnimation.Properties.opacity, + }, + update: { + type: LayoutAnimation.Types.easeInEaseOut, + property: LayoutAnimation.Properties.opacity, + }, + }); + setMapMode(false); + } return ( { if (!position) return; + returnToDefaultMode(); const { latitude, longitude } = position.coords; mapsRef.current.animateToRegion( { @@ -66,20 +83,7 @@ export const CarouselTypeChanger = ({ marginHorizontal: 5, borderRadius: 50, }} - disabled={true} - onPress={() => { - if (!position) return; - const { latitude, longitude } = position.coords; - mapsRef.current.animateToRegion( - { - latitude, - longitude, - latitudeDelta: 0.05, - longitudeDelta: 0.05, - }, - 1000 - ); - }} + onPress={() => returnToDefaultMode()} > { + returnToDefaultMode(); // お気に入りリスト更新 setStationListMode("favorite"); setSelectedCurrentStation(0); diff --git a/menu.js b/menu.js index 393a305..0214584 100644 --- a/menu.js +++ b/menu.js @@ -1,5 +1,5 @@ import React, { useRef, useState, useEffect } from "react"; -import { Platform, View, ScrollView, useWindowDimensions } from "react-native"; +import { Platform, View, ScrollView, useWindowDimensions, LayoutAnimation } from "react-native"; import Constants from "expo-constants"; import { configureReanimatedLogger, @@ -17,7 +17,7 @@ import { useNavigation } from "@react-navigation/native"; import { useStationList } from "./stateBox/useStationList"; import { TopMenuButton } from "@/components/Menu/TopMenuButton"; import { JRSTraInfoBox } from "@/components/Menu/JRSTraInfoBox"; -import MapView from "react-native-maps"; +import MapView, { Marker } from "react-native-maps"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs"; import { CarouselBox } from "./components/Menu/Carousel/CarouselBox"; @@ -27,14 +27,14 @@ configureReanimatedLogger({ level: ReanimatedLogLevel.error, // Set the log level to error strict: true, // Reanimated runs in strict mode by default }); -export default function Menu({scrollRef }) { +export default function Menu({ scrollRef }) { const { navigate, addListener, isFocused } = useNavigation(); const { favoriteStation } = useFavoriteStation(); const { originalStationList } = useStationList(); const { height, width } = useWindowDimensions(); const { bottom, left, right, top } = useSafeAreaInsets(); + const [mapMode, setMapMode] = useState(false); const tabBarHeight = useBottomTabBarHeight(); - const [mapsOpacity, setMapsOpacity] = useState(false); const [stationListMode, setStationListMode] = useState( /*<"position"|"favorite">*/ "position" ); @@ -45,6 +45,7 @@ export default function Menu({scrollRef }) { (Platform.OS == "android" ? Constants.statusBarHeight : 0) - 100 - ((((width / 100) * 80) / 20) * 9 + 10 + 30); + const MapFullHeight = height - tabBarHeight + (Platform.OS == "android" ? Constants.statusBarHeight : 0) - 100; useEffect(() => { setTimeout(() => { if (scrollRef.current) { @@ -95,12 +96,13 @@ export default function Menu({scrollRef }) { }; let returnDataBase = lineList - .map((d) => findStationEachLine(originalStationList[d])) + .map((d) => findStationEachLine(originalStationList[d])) .filter((d) => d.length > 0) .reduce((pre, current) => { pre.push(...current); return pre; - }, []).map((d) => [d]); + }, []) + .map((d) => [d]); setNearPositionStation(returnDataBase.length ? returnDataBase : []); }; @@ -154,15 +156,11 @@ export default function Menu({scrollRef }) { snapToStart={false} snapToEnd={false} decelerationRate={"normal"} - onScroll={(d) => { - const scrollY = d.nativeEvent.contentOffset.y + 100; - setMapsOpacity(scrollY < MapHeight); - }} snapToOffsets={[MapHeight - 80]} > alert("地図をタップ")} - /> + onTouchStart={() => { + LayoutAnimation.configureNext({ + duration: 300, + create: { + type: LayoutAnimation.Types.easeInEaseOut, + property: LayoutAnimation.Properties.opacity, + }, + update: { + type: LayoutAnimation.Types.easeInEaseOut, + property: LayoutAnimation.Properties.opacity, + }, + }); + setMapMode(true); + }} + > + {listUpStation.map(([{ lat, lng, StationNumber }], index) => ( + + ))} + {listUpStation.length != 0 && originalStationList.length != 0 && ( @@ -194,7 +217,7 @@ export default function Menu({scrollRef }) { originalStationList, listUpStation, nearPositionStation, - setListIndex , + setListIndex, listIndex, navigate, }} From fa758c144f5558de7ec18c48fb76f84a79e296f0 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Mon, 14 Apr 2025 18:52:21 +0000 Subject: [PATCH 23/77] =?UTF-8?q?=E3=82=B9=E3=82=AF=E3=83=AD=E3=83=BC?= =?UTF-8?q?=E3=83=AB=E3=81=AE=E6=8C=99=E5=8B=95=E3=81=8C=E3=81=8A=E3=81=8B?= =?UTF-8?q?=E3=81=97=E3=81=8B=E3=81=A3=E3=81=9F=E3=83=90=E3=82=B0=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MenuPage.js | 26 +++--- .../Menu/Carousel/CarouselTypeChanger.tsx | 14 +-- menu.js | 88 ++++++++++++++++--- 3 files changed, 91 insertions(+), 37 deletions(-) diff --git a/MenuPage.js b/MenuPage.js index b3a20e7..e9f16b4 100644 --- a/MenuPage.js +++ b/MenuPage.js @@ -1,4 +1,4 @@ -import React, { useEffect, useRef } from "react"; +import React, { useEffect, useRef,useState } from "react"; import { createStackNavigator } from "@react-navigation/stack"; import { useWindowDimensions, Platform } from "react-native"; import Constants from "expo-constants"; @@ -50,16 +50,20 @@ export function MenuPage() { }, []); const scrollRef = useRef(null); - const MapHeight = - height - - tabBarHeight + - (Platform.OS == "android" ? Constants.statusBarHeight : 0) - - 100 - - ((((width / 100) * 80) / 20) * 9 + 10 + 30); + const [mapHeight,setMapHeight] = useState(0); + useEffect(()=>{ + const MapHeight = + height - + tabBarHeight + + (Platform.OS == "android" ? Constants.statusBarHeight : 0) - + 100 - + ((((width / 100) * 80) / 20) * 9 + 10 + 30); + setMapHeight(MapHeight); + }, [height, tabBarHeight, width]); useEffect(() => { const unsubscribe = addListener("tabPress", (e) => { scrollRef.current.scrollTo({ - y: MapHeight - 80, + y: mapHeight - 80, animated: true, }); AS.getItem("favoriteStation") @@ -73,7 +77,7 @@ export function MenuPage() { }); return unsubscribe; - }, [navigation]); + }, [navigation, mapHeight]); return ( ( - - )} + children={() => } /> { if (!position) return; returnToDefaultMode(); - const { latitude, longitude } = position.coords; - mapsRef.current.animateToRegion( - { - latitude, - longitude, - latitudeDelta: 0.05, - longitudeDelta: 0.05, - }, - 1000 - ); setStationListMode("position"); }} > @@ -83,7 +73,7 @@ export const CarouselTypeChanger = ({ marginHorizontal: 5, borderRadius: 50, }} - onPress={() => returnToDefaultMode()} + onPressIn={() => returnToDefaultMode()} > { + scrollRef.current.scrollTo({ + y: mapHeight > 80 ?mapHeight - 80 :0, + animated: bool, + }); + }; + const goToMap = () => { + scrollRef.current.scrollTo({ + y: 0, + animated: true, + }); + }; useEffect(() => { - setTimeout(() => { - if (scrollRef.current) { - scrollRef.current.scrollTo({ - y: MapHeight - 80, - animated: false, - }); - } + setTimeout(()=>{ + returnToTop(false); }, 10); - }, []); - + }, [mapHeight]); + const returnToDefaultMode = () => { + LayoutAnimation.configureNext({ + duration: 300, + create: { + type: LayoutAnimation.Types.easeInEaseOut, + property: LayoutAnimation.Properties.opacity, + }, + update: { + type: LayoutAnimation.Types.easeInEaseOut, + property: LayoutAnimation.Properties.opacity, + }, + }); + setMapMode(false); + }; //現在地基準の駅名標リストアップ機能 const { position, locationStatus } = useUserPosition(); useEffect(() => { @@ -125,6 +155,7 @@ export default function Menu({ scrollRef }) { } if (listUpStation[listIndex] == undefined) { const count = listIndex - 1; + setMapMode(false); setListIndex(count); } }, [listIndex, nearPositionStation, listUpStation]); @@ -139,8 +170,10 @@ export default function Menu({ scrollRef }) { latitudeDelta: 0.05, longitudeDelta: 0.05, }; + if (mapMode) return; mapsRef.current.animateToRegion(mapRegion, 1000); }, [listIndex, nearPositionStation, listUpStation, mapsRef]); + return ( returnToDefaultMode()} > {listUpStation.map(([{ lat, lng, StationNumber }], index) => ( @@ -196,6 +231,33 @@ export default function Menu({ scrollRef }) { longitude: parseFloat(lng), }} image={require("@/assets/reccha-small.png")} + onPress={() => { + setMapMode(false); + setListIndex(index); + if (mapsRef.current) { + mapsRef.current.animateToRegion( + { + latitude: parseFloat(lat), + longitude: parseFloat(lng), + latitudeDelta: 0.05, + longitudeDelta: 0.05, + }, + 1000 + ); + } + LayoutAnimation.configureNext({ + duration: 300, + create: { + type: LayoutAnimation.Types.easeInEaseOut, + property: LayoutAnimation.Properties.opacity, + }, + update: { + type: LayoutAnimation.Types.easeInEaseOut, + property: LayoutAnimation.Properties.opacity, + }, + }); + returnToTop(); + }} /> ))} @@ -238,4 +300,4 @@ export default function Menu({ scrollRef }) { ); -} +} \ No newline at end of file From 85de99e32df45bd8db9a5134dd61371680f0b401 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Tue, 15 Apr 2025 07:37:14 +0000 Subject: [PATCH 24/77] =?UTF-8?q?LED=E7=99=BA=E8=BB=8A=E6=A8=99=E3=81=8C?= =?UTF-8?q?=E6=AD=A3=E5=B8=B8=E3=81=AB=E5=8B=95=E3=81=84=E3=81=A6=E3=81=84?= =?UTF-8?q?=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F=E5=95=8F=E9=A1=8C=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/発車時刻表/LED_vidion.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/components/発車時刻表/LED_vidion.js b/components/発車時刻表/LED_vidion.js index ae2c906..420a9e6 100644 --- a/components/発車時刻表/LED_vidion.js +++ b/components/発車時刻表/LED_vidion.js @@ -145,14 +145,12 @@ export default function LED_vision(props) { const timeFiltering = (d) => { const date = dayjs(); - const newDate = 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; - - date.hour(parseInt(h)).minute(parseInt(m) + parseInt(delay)); - return !(newDate.isAfter(date)); + const db = date.hour(parseInt(h)).minute(parseInt(m) + parseInt(delay)); + return !(date.isAfter(db)); }; const [areaString, setAreaString] = useState(""); From b3cc5b6ede1611c775e341bdd0a10ef98437e0dd Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Fri, 18 Apr 2025 09:51:36 +0000 Subject: [PATCH 25/77] =?UTF-8?q?=E5=9C=B0=E5=9B=B3=E3=81=AE=E4=B8=8B?= =?UTF-8?q?=E9=83=A8=E5=86=85=E5=AE=B9=E3=82=92absolute=E3=81=AB=E3=81=97?= =?UTF-8?q?=E3=81=A6=E6=A9=9F=E8=83=BD=E5=88=87=E3=82=8A=E6=9B=BF=E3=81=88?= =?UTF-8?q?=E3=82=92=E3=82=B9=E3=82=AF=E3=83=AD=E3=83=BC=E3=83=AB=E3=81=A7?= =?UTF-8?q?=E7=99=BA=E5=8B=95=E3=81=97=E3=81=AA=E3=81=84=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MenuPage.js | 26 +++++- .../Menu/Carousel/CarouselTypeChanger.tsx | 19 ++++- menu.js | 80 ++++++++++++------- 3 files changed, 88 insertions(+), 37 deletions(-) diff --git a/MenuPage.js b/MenuPage.js index e9f16b4..a815a2e 100644 --- a/MenuPage.js +++ b/MenuPage.js @@ -1,4 +1,4 @@ -import React, { useEffect, useRef,useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import { createStackNavigator } from "@react-navigation/stack"; import { useWindowDimensions, Platform } from "react-native"; import Constants from "expo-constants"; @@ -50,8 +50,9 @@ export function MenuPage() { }, []); const scrollRef = useRef(null); - const [mapHeight,setMapHeight] = useState(0); - useEffect(()=>{ + const [mapMode, setMapMode] = useState(false); + const [mapHeight, setMapHeight] = useState(0); + useEffect(() => { const MapHeight = height - tabBarHeight + @@ -60,12 +61,21 @@ export function MenuPage() { ((((width / 100) * 80) / 20) * 9 + 10 + 30); setMapHeight(MapHeight); }, [height, tabBarHeight, width]); + const [MapFullHeight, setMapFullHeight] = useState(0); + useEffect(() => { + const MapFullHeight = + height - + tabBarHeight + + (Platform.OS == "android" ? Constants.statusBarHeight : 0); + setMapFullHeight(MapFullHeight); + }, [height, tabBarHeight, width]); useEffect(() => { const unsubscribe = addListener("tabPress", (e) => { scrollRef.current.scrollTo({ y: mapHeight - 80, animated: true, }); + setMapMode(false); AS.getItem("favoriteStation") .then((d) => { const returnData = JSON.parse(d); @@ -87,7 +97,15 @@ export function MenuPage() { gestureEnabled: true, headerTransparent: true, }} - children={() => } + children={() => ( + + )} /> { + const tabBarHeight = useBottomTabBarHeight(); const returnToDefaultMode = ()=>{ LayoutAnimation.configureNext({ duration: 300, @@ -26,7 +29,7 @@ export const CarouselTypeChanger = ({ setMapMode(false); } return ( - + { + if (!position) return; + returnToDefaultMode(); + setStationListMode("position"); + }} onPress={() => { if (!position) return; returnToDefaultMode(); @@ -76,7 +85,7 @@ export const CarouselTypeChanger = ({ onPressIn={() => returnToDefaultMode()} > { + returnToDefaultMode(); + // お気に入りリスト更新 + setStationListMode("favorite"); + setSelectedCurrentStation(0); + }} onPress={() => { returnToDefaultMode(); // お気に入りリスト更新 diff --git a/menu.js b/menu.js index 50a1e3e..b02d605 100644 --- a/menu.js +++ b/menu.js @@ -33,32 +33,20 @@ configureReanimatedLogger({ level: ReanimatedLogLevel.error, // Set the log level to error strict: true, // Reanimated runs in strict mode by default }); -export default function Menu({ scrollRef, mapHeight }) { +export default function Menu({ scrollRef, mapHeight, MapFullHeight, mapMode, setMapMode }) { const { navigate, addListener, isFocused } = useNavigation(); const { favoriteStation } = useFavoriteStation(); const { originalStationList } = useStationList(); const { height, width } = useWindowDimensions(); const { bottom, left, right, top } = useSafeAreaInsets(); - const [mapMode, setMapMode] = useState(false); const tabBarHeight = useBottomTabBarHeight(); const [stationListMode, setStationListMode] = useState( /*<"position"|"favorite">*/ "position" ); const mapsRef = useRef(null); - const MapHeight = - height - - tabBarHeight + - (Platform.OS == "android" ? Constants.statusBarHeight : 0) - - 100 - - ((((width / 100) * 80) / 20) * 9 + 10 + 30); - const MapFullHeight = - height - - tabBarHeight + - (Platform.OS == "android" ? Constants.statusBarHeight : 0) - - 100; const returnToTop = (bool = true) => { scrollRef.current.scrollTo({ - y: mapHeight > 80 ?mapHeight - 80 :0, + y: mapHeight > 80 ? mapHeight - 80 : 0, animated: bool, }); }; @@ -69,11 +57,12 @@ export default function Menu({ scrollRef, mapHeight }) { }); }; useEffect(() => { - setTimeout(()=>{ + setTimeout(() => { returnToTop(false); }, 10); }, [mapHeight]); - const returnToDefaultMode = () => { + const [scrollStartPosition, setScrollStartPosition] = useState(0); + const onScrollBeginDrag = (e) => { LayoutAnimation.configureNext({ duration: 300, create: { @@ -85,6 +74,7 @@ export default function Menu({ scrollRef, mapHeight }) { property: LayoutAnimation.Properties.opacity, }, }); + setScrollStartPosition(e.nativeEvent.contentOffset.y); setMapMode(false); }; //現在地基準の駅名標リストアップ機能 @@ -189,12 +179,22 @@ export default function Menu({ scrollRef, mapHeight }) { snapToStart={false} snapToEnd={false} decelerationRate={"normal"} - snapToOffsets={[MapHeight - 80]} - onScrollBeginDrag={() => returnToDefaultMode()} + snapToOffsets={[mapHeight - 80]} + onScrollBeginDrag={onScrollBeginDrag} + onScrollEndDrag={(e) => { + console.log(e.nativeEvent.velocity); + if (e.nativeEvent.contentOffset.y < mapHeight - 80) { + if (scrollStartPosition > e.nativeEvent.contentOffset.y) { + goToMap(); + } else { + returnToTop(); + } + } + }} > ))} - + {!mapMode && ( + + )} + {listUpStation.length != 0 && originalStationList.length != 0 && ( <> + {mapMode && ( + + )} ); -} \ No newline at end of file +} From fbcded3d23685ec9988b595ff6eb35b1bf72ea9d Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Fri, 18 Apr 2025 15:39:58 +0000 Subject: [PATCH 26/77] =?UTF-8?q?=E5=88=97=E8=BB=8A=E3=81=8C=E5=87=BA?= =?UTF-8?q?=E7=99=BA=E3=81=97=E3=81=A6=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F?= =?UTF-8?q?=E3=82=89LED=E3=81=8B=E3=82=89=E6=B6=88=E3=81=88=E3=81=AA?= =?UTF-8?q?=E3=81=84=E3=82=88=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3=E3=80=81?= =?UTF-8?q?=E5=87=BA=E7=99=BA=E3=81=97=E3=81=A6=E3=81=9F=E3=82=89=E7=8E=87?= =?UTF-8?q?=E5=85=88=E3=81=97=E3=81=A6=E6=B6=88=E3=81=88=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/発車時刻表/LED_vidion.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/components/発車時刻表/LED_vidion.js b/components/発車時刻表/LED_vidion.js index 420a9e6..085b4f2 100644 --- a/components/発車時刻表/LED_vidion.js +++ b/components/発車時刻表/LED_vidion.js @@ -11,6 +11,7 @@ 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"; /** * @@ -144,6 +145,15 @@ export default function LED_vision(props) { }; const timeFiltering = (d) => { + 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){ + 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) From 8c17a5b3daa104b9b8f066454437dcfcede86709 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 20 Apr 2025 05:31:30 +0000 Subject: [PATCH 27/77] =?UTF-8?q?=E5=88=97=E8=BB=8A=E3=81=AE=E8=A1=A8?= =?UTF-8?q?=E7=A4=BA=E6=9D=A1=E4=BB=B6=E3=81=AE=E5=8E=B3=E5=AF=86=E5=8C=96?= =?UTF-8?q?=E3=80=81=E3=81=8A=E3=82=88=E3=81=B3=E5=87=BA=E7=99=BA=E4=BF=83?= =?UTF-8?q?=E9=80=B2=E8=A1=A8=E7=A4=BA=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/発車時刻表/EachData.tsx | 22 +++++++++++ components/発車時刻表/LED_vidion.js | 50 ++++++++++++++++-------- 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/components/発車時刻表/EachData.tsx b/components/発車時刻表/EachData.tsx index c3dce10..f636d48 100644 --- a/components/発車時刻表/EachData.tsx +++ b/components/発車時刻表/EachData.tsx @@ -16,6 +16,8 @@ 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"; type Props = { d: { @@ -117,6 +119,22 @@ export const EachData: FC = (props) => { const [descInput, setDescInput] = useState(""); const [stationInput, setStationInput] = useState(""); const [stationNumberInput, setStationNumberInput] = useState(""); + + const [isShow, setIsShow] = useState(true); + const [isDepartureNow, setIsDepartureNow] = useState(false); + useEffect(()=>{ + const currentTime = dayjs(); + const trainTime = currentTime.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); + }) + useInterval(()=>{ + if (isDepartureNow) { + setIsShow(!isShow); + + } + }, 800); return ( <> = (props) => { marginHorizontal: "3%", backgroundColor: "#000", flexDirection: "row", + opacity: isShow ? 1 : 0.5, }} onPress={() => openTrainInfo(d)} key={ d.train + "-eachData" } @@ -162,6 +181,9 @@ export const EachData: FC = (props) => { + {!!isDepartureNow && ( + + )} {trainDescriptionSwitch && ( {}; if (!currentTrain) return () => {}; const data = trainTimeAndNumber - .filter((d) => currentTrain.map((m) => m.num).includes(d.train)) + //.filter((d) => currentTrain.map((m) => m.num).includes(d.train)) .filter(timeFiltering) .filter((d) => !!finalSwitch || d.lastStation != "当駅止"); setSelectedTrain(data); @@ -145,22 +145,40 @@ export default function LED_vision(props) { }; const timeFiltering = (d) => { - 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){ - return true; - } - else if(station[0].Station_JP == PrePos){ + + 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 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(""); From c41c61bba792ccf6ac48c7abef5fd0bfc8274019 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Tue, 6 May 2025 11:53:45 +0000 Subject: [PATCH 28/77] =?UTF-8?q?=E5=AE=87=E5=A4=9A=E6=B4=A5=E3=81=AB?= =?UTF-8?q?=E8=BF=91=E3=81=A5=E3=81=84=E3=81=9F=E3=82=89=E3=82=AF=E3=83=A9?= =?UTF-8?q?=E3=83=83=E3=82=B7=E3=83=A5=E3=81=99=E3=82=8B=E5=95=8F=E9=A1=8C?= =?UTF-8?q?=E3=80=81=E7=8F=BE=E5=9C=A8=E5=9C=B0=E3=81=AE=E3=83=AA=E3=82=B9?= =?UTF-8?q?=E3=83=88=E3=82=A2=E3=83=83=E3=83=97=E6=A9=9F=E8=83=BD=E3=81=8C?= =?UTF-8?q?=E3=81=A1=E3=82=83=E3=82=93=E3=81=A8=E6=95=B4=E7=90=86=E3=81=95?= =?UTF-8?q?=E3=82=8C=E3=81=A6=E3=81=84=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F?= =?UTF-8?q?=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/発車時刻表/EachData.tsx | 7 +++++-- menu.js | 25 ++++++++++++++++++++----- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/components/発車時刻表/EachData.tsx b/components/発車時刻表/EachData.tsx index f636d48..2fb5686 100644 --- a/components/発車時刻表/EachData.tsx +++ b/components/発車時刻表/EachData.tsx @@ -128,7 +128,10 @@ export const EachData: FC = (props) => { const diff = trainTime.diff(currentTime, "minute"); if (diff < 2) setIsDepartureNow(true); else setIsDepartureNow(false); - }) + return()=>{ + setIsDepartureNow(false); + } + }, [d.time]); useInterval(()=>{ if (isDepartureNow) { setIsShow(!isShow); @@ -182,7 +185,7 @@ export const EachData: FC = (props) => { {!!isDepartureNow && ( - + )} {trainDescriptionSwitch && ( findStationEachLine(originalStationList[d])) .filter((d) => d.length > 0) .reduce((pre, current) => { pre.push(...current); return pre; - }, []) - .map((d) => [d]); - setNearPositionStation(returnDataBase.length ? returnDataBase : []); + }, []); + if (_stList.length == 0) setNearPositionStation([]); + else { + let returnData = []; + _stList.forEach((d, index, array) => { + const stationName = d.Station_JP; + if (returnData.findIndex((d) => d[0].Station_JP == stationName) != -1) return; + returnData.push(array.filter((d2) => d2.Station_JP == stationName)); + }); + returnData.forEach((d) => console.log(d)); + setNearPositionStation(returnData); + } }; const [nearPositionStation, setNearPositionStation] = useState([]); //第三要素 From 7ca4cf95e6b6b3b75b767f0c0735b867bc916d5e Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Tue, 6 May 2025 13:59:13 +0000 Subject: [PATCH 29/77] =?UTF-8?q?=E3=83=86=E3=82=AD=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=81=AE=E7=82=B9=E6=BB=85=E3=82=92=E7=A7=BB=E5=8B=95=E3=81=97?= =?UTF-8?q?=E3=81=9F=E3=81=A8=E3=81=8D=E3=81=AB=E3=82=AD=E3=83=A3=E3=83=B3?= =?UTF-8?q?=E3=82=BB=E3=83=AB=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/発車時刻表/EachData.tsx | 1 + menu.js | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/components/発車時刻表/EachData.tsx b/components/発車時刻表/EachData.tsx index 2fb5686..eadce46 100644 --- a/components/発車時刻表/EachData.tsx +++ b/components/発車時刻表/EachData.tsx @@ -130,6 +130,7 @@ export const EachData: FC = (props) => { else setIsDepartureNow(false); return()=>{ setIsDepartureNow(false); + setIsShow(true); } }, [d.time]); useInterval(()=>{ diff --git a/menu.js b/menu.js index a714611..b07ec58 100644 --- a/menu.js +++ b/menu.js @@ -136,7 +136,6 @@ export default function Menu({ if (returnData.findIndex((d) => d[0].Station_JP == stationName) != -1) return; returnData.push(array.filter((d2) => d2.Station_JP == stationName)); }); - returnData.forEach((d) => console.log(d)); setNearPositionStation(returnData); } }; From 6a58263e9422e8077959fcc7a030276c35d8257b Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Tue, 6 May 2025 16:27:42 +0000 Subject: [PATCH 30/77] =?UTF-8?q?=E6=9C=80=E5=BE=8C=E3=81=AE=E9=A7=85?= =?UTF-8?q?=E3=83=AA=E3=82=B9=E3=83=88=E9=81=B8=E6=8A=9E=E3=82=92=E7=B6=AD?= =?UTF-8?q?=E6=8C=81=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E5=A4=89?= =?UTF-8?q?=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Menu/Carousel/CarouselTypeChanger.tsx | 7 +++++++ menu.js | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/components/Menu/Carousel/CarouselTypeChanger.tsx b/components/Menu/Carousel/CarouselTypeChanger.tsx index 6c9cecf..c2a0850 100644 --- a/components/Menu/Carousel/CarouselTypeChanger.tsx +++ b/components/Menu/Carousel/CarouselTypeChanger.tsx @@ -1,3 +1,4 @@ +import { AS } from "@/storageControl"; import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs"; import React, { useEffect, useRef } from "react"; import { View, TouchableOpacity, Text, LayoutAnimation } from "react-native"; @@ -49,11 +50,15 @@ export const CarouselTypeChanger = ({ if (!position) return; returnToDefaultMode(); setStationListMode("position"); + AS.setItem("stationListMode", "position"); + setSelectedCurrentStation(0); }} onPress={() => { if (!position) return; returnToDefaultMode(); setStationListMode("position"); + AS.setItem("stationListMode", "position"); + setSelectedCurrentStation(0); }} > { returnToDefaultMode(); // お気に入りリスト更新 setStationListMode("favorite"); + AS.setItem("stationListMode", "favorite"); setSelectedCurrentStation(0); }} > diff --git a/menu.js b/menu.js index b07ec58..3a222f1 100644 --- a/menu.js +++ b/menu.js @@ -29,6 +29,7 @@ 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"; configureReanimatedLogger({ level: ReanimatedLogLevel.error, // Set the log level to error strict: true, // Reanimated runs in strict mode by default @@ -49,6 +50,13 @@ export default function Menu({ const [stationListMode, setStationListMode] = useState( /*<"position"|"favorite">*/ "position" ); + useEffect(()=>{ + AS.getItem("stationListMode").then((res) => { + setStationListMode(res); + }).catch((e) => { + // AS.setItem("stationListMode", "position"); + }); + }, []); const mapsRef = useRef(null); const returnToTop = (bool = true) => { scrollRef.current.scrollTo({ From 73ed5480c1b515137c560de1b22e4365d1856618 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sat, 17 May 2025 10:16:35 +0000 Subject: [PATCH 31/77] =?UTF-8?q?wp=E3=82=92=E5=89=8A=E9=99=A4=E3=81=97?= =?UTF-8?q?=E3=81=A6=E9=85=8D=E7=BD=AE=E3=82=92=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StationDeteilView.js | 8 +- components/駅名表/NextPreStationLine.tsx | 79 ++++++----- components/駅名表/Sign.js | 125 +++++++++--------- menu.js | 3 + 4 files changed, 116 insertions(+), 99 deletions(-) diff --git a/components/ActionSheetComponents/StationDeteilView.js b/components/ActionSheetComponents/StationDeteilView.js index aa8189c..17ce175 100644 --- a/components/ActionSheetComponents/StationDeteilView.js +++ b/components/ActionSheetComponents/StationDeteilView.js @@ -14,7 +14,6 @@ import ActionSheet, { SheetManager } from "react-native-actions-sheet"; import Sign from "../../components/駅名表/Sign"; import { TicketBox } from "../atom/TicketBox"; -import { widthPercentageToDP as wp } from "react-native-responsive-screen"; import { getPDFViewURL } from "../../lib/getPdfViewURL"; import { useBusAndTrainData } from "../../stateBox/useBusAndTrainData"; import { AS } from "../../storageControl"; @@ -27,13 +26,14 @@ import { StationTimeTableButton } from "./StationDeteilView/StationTimeTableButt export const StationDeteilView = (props) => { if (!props.payload) return <>; const { currentStation, navigate, onExit, goTo, useShow } = props.payload; + const { width } = useWindowDimensions(); const { busAndTrainData } = useBusAndTrainData(); const [trainBus, setTrainBus] = useState(); useEffect(() => { if (!currentStation) return () => {}; - const data = busAndTrainData.filter((d) => - d.name === currentStation[0].Station_JP + const data = busAndTrainData.filter( + (d) => d.name === currentStation[0].Station_JP ); if (data.length == 0) { setTrainBus(); @@ -89,7 +89,7 @@ export const StationDeteilView = (props) => { {currentStation && ( - + { diff --git a/components/駅名表/NextPreStationLine.tsx b/components/駅名表/NextPreStationLine.tsx index 27843c3..269c79d 100644 --- a/components/駅名表/NextPreStationLine.tsx +++ b/components/駅名表/NextPreStationLine.tsx @@ -1,9 +1,22 @@ import React, { CSSProperties, FC } from "react"; -import { widthPercentageToDP as wp } from "react-native-responsive-screen"; -import { Platform, Text, TextStyle, View, ViewStyle } from "react-native"; +import { + Platform, + Text, + TextStyle, + useWindowDimensions, + View, + ViewStyle, +} from "react-native"; import { StationName } from "./StationName"; import lineColorList from "../../assets/originData/lineColorList"; export const NextPreStationLine = ({ nexStation, preStation, isMatsuyama }) => { + const 下枠フレーム: ViewStyle = { + flex: 1, + flexDirection: "row", + alignContent: "center", + alignItems: "center", + }; + return ( @@ -49,12 +62,40 @@ type FCimport = { children: string; }; const BottomSideArrow: FC = ({ isMatsuyama, children }) => { + const 下枠左右マーク: TextStyle = { + fontWeight: "bold", + fontSize: parseInt("20%"), + color: "white", + paddingHorizontal: 5, + textAlignVertical: "center", + }; return !isMatsuyama && {children}; }; const BottomStationNumberView: FC = ({ isMatsuyama, children }) => { + const { width } = useWindowDimensions(); const lineID = children.slice(0, 1); const lineName = children.slice(1); + const 下枠駅ナンバー: ViewStyle = { + alignContent: "center", + alignItems: "center", + width: width * 0.08, + height: width * 0.08, + margin: width * 0.01, + backgroundColor: "white", + borderWidth: parseInt("3%"), + borderRadius: parseInt("100%"), + }; + const 下枠駅ナンバーB: ViewStyle = { + alignContent: "center", + alignItems: "center", + width: width * 0.07, + height: width * 0.07, + margin: width * 0.02, + backgroundColor: "white", + borderWidth: parseInt("3%"), + borderRadius: parseInt("100%"), + }; return ( = ({ isMatsuyama, children }) => { ); }; - -const 下枠フレーム: ViewStyle = { - flex: 1, - flexDirection: "row", - alignContent: "center", - alignItems: "center", -}; -const 下枠左右マーク: TextStyle = { - fontWeight: "bold", - fontSize: parseInt("20%"), - color: "white", - paddingHorizontal: 5, - textAlignVertical: "center", -}; -const 下枠駅ナンバー: ViewStyle = { - alignContent: "center", - alignItems: "center", - width: wp("8%"), - height: wp("8%"), - margin: wp("1%"), - backgroundColor: "white", - borderWidth: parseInt("3%"), - borderRadius: parseInt("100%"), -}; -const 下枠駅ナンバーB: ViewStyle = { - alignContent: "center", - alignItems: "center", - width: wp("7%"), - height: wp("7%"), - margin: wp("2%"), - backgroundColor: "white", - borderWidth: parseInt("3%"), - borderRadius: parseInt("100%"), -}; diff --git a/components/駅名表/Sign.js b/components/駅名表/Sign.js index eb1b182..f7a3929 100644 --- a/components/駅名表/Sign.js +++ b/components/駅名表/Sign.js @@ -1,6 +1,10 @@ import React, { useRef, useState, useEffect, useLayoutEffect } from "react"; -import { View, Text, TouchableOpacity } from "react-native"; -import { widthPercentageToDP as wp } from "react-native-responsive-screen"; +import { + View, + Text, + TouchableOpacity, + useWindowDimensions, +} from "react-native"; import { MaterialCommunityIcons } from "@expo/vector-icons"; import LottieView from "lottie-react-native"; import { useInterval } from "../../lib/useInterval"; @@ -16,6 +20,8 @@ import { useStationList } from "../../stateBox/useStationList"; export default function Sign(props) { const { oP, oLP, isCurrentStation = false, stationID } = props; + + const { width, height } = useWindowDimensions(); const { getStationDataFromId } = useStationList(); if (!stationID) { return <>; @@ -117,6 +123,62 @@ export default function Sign(props) { } setTestButtonStatus(!testButtonStatus); }; + + const styleSheet = { + 外枠: { + width: width * 0.8, + height: ((width * 0.8) / 20) * 9, + borderColor: "#0099CC", + borderWidth: 1, + backgroundColor: "white", + }, + 外枠B: { + width: width * 0.8, + height: ((width * 0.8) / 20) * 9, + borderWidth: 0, + }, + 下帯: { + position: "absolute", + bottom: "8%", + left: "0%", + width: "100%", + height: "27%", + backgroundColor: "#0099CC", + }, + 下帯B: { + position: "absolute", + bottom: "0%", + left: "0%", + width: "100%", + height: "26%", + backgroundColor: "#454545", + }, + JRStyle: { + position: "absolute", + top: "2%", + left: "2%", + fontWeight: "bold", + fontSize: parseInt("25%"), + color: "#0099CC", + }, + 下帯内容: { + position: "absolute", + bottom: "8%", + height: "27%", + width: "100%", + alignItems: "center", + flexDirection: "column", + }, + 下帯内容B: { + position: "absolute", + bottom: "0%", + height: "26%", + width: "100%", + alignItems: "center", + flexDirection: "column", + }, + }; + return ( ); } - -const styleSheet = { - 外枠: { - width: wp("80%"), - height: (wp("80%") / 20) * 9, - borderColor: "#0099CC", - borderWidth: 1, - backgroundColor: "white", - }, - 外枠B: { - width: wp("80%"), - height: (wp("80%") / 20) * 9, - borderWidth: 0, - }, - 下帯: { - position: "absolute", - bottom: "8%", - left: "0%", - width: "100%", - height: "27%", - backgroundColor: "#0099CC", - }, - 下帯B: { - position: "absolute", - bottom: "0%", - left: "0%", - width: "100%", - height: "26%", - backgroundColor: "#454545", - }, - JRStyle: { - position: "absolute", - top: "2%", - left: "2%", - fontWeight: "bold", - fontSize: parseInt("25%"), - color: "#0099CC", - }, - 下帯内容: { - position: "absolute", - bottom: "8%", - height: "27%", - width: "100%", - alignItems: "center", - flexDirection: "column", - }, - 下帯内容B: { - position: "absolute", - bottom: "0%", - height: "26%", - width: "100%", - alignItems: "center", - flexDirection: "column", - }, -}; diff --git a/menu.js b/menu.js index 3a222f1..1e9bd93 100644 --- a/menu.js +++ b/menu.js @@ -57,6 +57,9 @@ export default function Menu({ // AS.setItem("stationListMode", "position"); }); }, []); + useEffect(()=>{ + alert(`height:${height}, width:${width}, bottom:${bottom}, left:${left}, right:${right}, top:${top}, tabBarHeight:${tabBarHeight}`); + }, [height, width, bottom, left, right, top, tabBarHeight]) const mapsRef = useRef(null); const returnToTop = (bool = true) => { scrollRef.current.scrollTo({ From 2f65cd6a6f2a358826684ba53043be56b3e321d6 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Mon, 19 May 2025 06:21:08 +0000 Subject: [PATCH 32/77] =?UTF-8?q?=E5=AE=9A=E7=BE=A9=E5=BF=98=E3=82=8C?= =?UTF-8?q?=E3=83=90=E3=82=B0=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/ActionSheetComponents/StationDeteilView.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/components/ActionSheetComponents/StationDeteilView.js b/components/ActionSheetComponents/StationDeteilView.js index 17ce175..1423b5b 100644 --- a/components/ActionSheetComponents/StationDeteilView.js +++ b/components/ActionSheetComponents/StationDeteilView.js @@ -2,18 +2,14 @@ import React, { useState, useEffect } from "react"; import { View, Linking, - Text, - TouchableOpacity, BackHandler, Platform, + useWindowDimensions, } from "react-native"; -import AutoHeightImage from "react-native-auto-height-image"; -import { FontAwesome, Foundation, Ionicons } from "@expo/vector-icons"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import ActionSheet, { SheetManager } from "react-native-actions-sheet"; import Sign from "../../components/駅名表/Sign"; -import { TicketBox } from "../atom/TicketBox"; import { getPDFViewURL } from "../../lib/getPdfViewURL"; import { useBusAndTrainData } from "../../stateBox/useBusAndTrainData"; import { AS } from "../../storageControl"; From 59082c78735905889a95da37adb5d73a9f94310c Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sat, 24 May 2025 06:29:17 +0000 Subject: [PATCH 33/77] =?UTF-8?q?=E5=B0=8F=E3=81=95=E3=81=AA=E5=A4=89?= =?UTF-8?q?=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StationDeteilView.js | 129 +++++++++--------- 1 file changed, 65 insertions(+), 64 deletions(-) diff --git a/components/ActionSheetComponents/StationDeteilView.js b/components/ActionSheetComponents/StationDeteilView.js index 1423b5b..a75c2e2 100644 --- a/components/ActionSheetComponents/StationDeteilView.js +++ b/components/ActionSheetComponents/StationDeteilView.js @@ -85,73 +85,74 @@ export const StationDeteilView = (props) => { {currentStation && ( - - { - usePDFView == "true" - ? Linking.openURL(currentStation[0].StationTimeTable) - : navigate("howto", { - info, + <> + + { + usePDFView == "true" + ? Linking.openURL(currentStation[0].StationTimeTable) + : navigate("howto", { + info, + goTo, + useShow, + }); + onExit(); + }} + oLP={() => + Linking.openURL(currentStation[0].StationTimeTable) + } + /> + + {currentStation[0].JrHpUrl && + currentStation[0].StationNumber != "M12" && ( + <駅構内図 //児島例外/ + navigate={navigate} + goTo={goTo} + useShow={useShow} + address={currentStation[0].JrHpUrl} + onExit={onExit} + /> + )} + + {!currentStation[0].JrHpUrl || ( + + )} + {!currentStation[0].StationTimeTable || ( + + )} + {!currentStation[0].StationMap || ( + + )} + {!trainBus || ( + { + navigate("howto", { + info: trainBus.address, goTo, useShow, }); - onExit(); - }} - oLP={() => Linking.openURL(currentStation[0].StationTimeTable)} - /> - - )} - {currentStation && - currentStation[0].JrHpUrl && - currentStation[0].StationNumber != "M12" && ( - <駅構内図 //児島例外/ - navigate={navigate} - goTo={goTo} - useShow={useShow} - address={currentStation[0].JrHpUrl} - onExit={onExit} - /> - )} - {currentStation && ( - - {!currentStation[0].JrHpUrl || ( - - )} - {!currentStation[0].StationTimeTable || ( - - )} - {!currentStation[0].StationMap || ( - - )} - {!trainBus || ( - { - navigate("howto", { - info: trainBus.address, - goTo, - useShow, - }); - onExit(); - }} - /> - )} - + onExit(); + }} + /> + )} + + )} From d6b701bdb13c5398520a0cfa2b5e2668aa6bb264 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Tue, 3 Jun 2025 13:37:04 +0000 Subject: [PATCH 34/77] =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=AA=E8=A6=81?= =?UTF-8?q?=E7=B4=A0=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- menu.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/menu.js b/menu.js index 1e9bd93..3a222f1 100644 --- a/menu.js +++ b/menu.js @@ -57,9 +57,6 @@ export default function Menu({ // AS.setItem("stationListMode", "position"); }); }, []); - useEffect(()=>{ - alert(`height:${height}, width:${width}, bottom:${bottom}, left:${left}, right:${right}, top:${top}, tabBarHeight:${tabBarHeight}`); - }, [height, width, bottom, left, right, top, tabBarHeight]) const mapsRef = useRef(null); const returnToTop = (bool = true) => { scrollRef.current.scrollTo({ From 0d595c7f67b194fa4184d6856ba3401f9fc79a13 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Tue, 10 Jun 2025 13:18:52 +0000 Subject: [PATCH 35/77] =?UTF-8?q?=E5=B0=8F=E4=BF=AE=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MenuPage.js | 2 +- components/発車時刻表/EachData.tsx | 2 +- menu.js | 24 ++++++++++-------------- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/MenuPage.js b/MenuPage.js index a815a2e..de4f199 100644 --- a/MenuPage.js +++ b/MenuPage.js @@ -50,7 +50,7 @@ export function MenuPage() { }, []); const scrollRef = useRef(null); - const [mapMode, setMapMode] = useState(false); + const [mapMode, setMapMode] = useState(false); const [mapHeight, setMapHeight] = useState(0); useEffect(() => { const MapHeight = diff --git a/components/発車時刻表/EachData.tsx b/components/発車時刻表/EachData.tsx index eadce46..664fd8e 100644 --- a/components/発車時刻表/EachData.tsx +++ b/components/発車時刻表/EachData.tsx @@ -132,7 +132,7 @@ export const EachData: FC = (props) => { setIsDepartureNow(false); setIsShow(true); } - }, [d.time]); + }, [d.time,currentTrainData]); useInterval(()=>{ if (isDepartureNow) { setIsShow(!isShow); diff --git a/menu.js b/menu.js index 3a222f1..ffff6f5 100644 --- a/menu.js +++ b/menu.js @@ -34,13 +34,8 @@ configureReanimatedLogger({ level: ReanimatedLogLevel.error, // Set the log level to error strict: true, // Reanimated runs in strict mode by default }); -export default function Menu({ - scrollRef, - mapHeight, - MapFullHeight, - mapMode, - setMapMode, -}) { +export default function Menu(props) { + const { scrollRef, mapHeight, MapFullHeight, mapMode, setMapMode } = props; const { navigate, addListener, isFocused } = useNavigation(); const { favoriteStation } = useFavoriteStation(); const { originalStationList } = useStationList(); @@ -50,12 +45,12 @@ export default function Menu({ const [stationListMode, setStationListMode] = useState( /*<"position"|"favorite">*/ "position" ); - useEffect(()=>{ - AS.getItem("stationListMode").then((res) => { - setStationListMode(res); - }).catch((e) => { - // AS.setItem("stationListMode", "position"); - }); + useEffect(() => { + AS.getItem("stationListMode") + .then((res) => setStationListMode(res)) + .catch((e) => { + // AS.setItem("stationListMode", "position"); + }); }, []); const mapsRef = useRef(null); const returnToTop = (bool = true) => { @@ -141,7 +136,8 @@ export default function Menu({ let returnData = []; _stList.forEach((d, index, array) => { const stationName = d.Station_JP; - if (returnData.findIndex((d) => d[0].Station_JP == stationName) != -1) return; + if (returnData.findIndex((d) => d[0].Station_JP == stationName) != -1) + return; returnData.push(array.filter((d2) => d2.Station_JP == stationName)); }); setNearPositionStation(returnData); From 52ca9d03a82ea1ac7e95b20f648a8cdf3365b0ab Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Tue, 10 Jun 2025 13:59:38 +0000 Subject: [PATCH 36/77] =?UTF-8?q?=E8=B7=AF=E7=B7=9A=E3=82=92=E8=B7=A8?= =?UTF-8?q?=E3=81=90=E4=BD=8D=E7=BD=AE=E3=81=AB=E5=B1=85=E3=82=8B=E3=81=A8?= =?UTF-8?q?=E8=B7=AF=E7=B7=9A=E9=A0=86=E3=81=AB=E5=80=99=E8=A3=9C=E3=81=8C?= =?UTF-8?q?=E4=B8=A6=E3=82=93=E3=81=A7=E3=81=97=E3=81=BE=E3=81=86=E5=95=8F?= =?UTF-8?q?=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- menu.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/menu.js b/menu.js index ffff6f5..2413050 100644 --- a/menu.js +++ b/menu.js @@ -140,6 +140,24 @@ export default function Menu(props) { return; returnData.push(array.filter((d2) => d2.Station_JP == stationName)); }); + //returnDataを距離の近い順にソート + returnData.sort((a, b) => { + const _calcDistance = (from, to) => { + let lat = Math.abs(from.lat - to.lat); + let lng = Math.abs(from.lng - to.lng); + return Math.sqrt(lat * lat + lng * lng); + }; + return ( + _calcDistance(a[0], { + lat: location.coords.latitude, + lng: location.coords.longitude, + }) - + _calcDistance(b[0], { + lat: location.coords.latitude, + lng: location.coords.longitude, + }) + ); + }); setNearPositionStation(returnData); } }; From c52cb1c91fc0b816278f31ea0d56d5d794a9ec7c Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Tue, 10 Jun 2025 14:08:41 +0000 Subject: [PATCH 37/77] =?UTF-8?q?=E6=A4=9C=E7=B4=A2=E7=AF=84=E5=9B=B2?= =?UTF-8?q?=E3=82=92=E7=B8=AE=E5=B0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- menu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menu.js b/menu.js index 2413050..73a2ade 100644 --- a/menu.js +++ b/menu.js @@ -95,7 +95,7 @@ export default function Menu(props) { const makeCurrentStation = (location) => { if (!originalStationList) return () => {}; const findStationEachLine = (selectLine) => { - const searchArea = 0.12; + const searchArea = 0.055; //検索範囲 const _calcDistance = (from, to) => { let lat = Math.abs(from.lat - to.lat); let lng = Math.abs(from.lng - to.lng); From aefbf68401c271f1dcf79233b1d5a2484d776071 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Tue, 10 Jun 2025 14:17:23 +0000 Subject: [PATCH 38/77] =?UTF-8?q?LED=E3=82=92=E4=BB=A5=E5=89=8D=E3=81=AE?= =?UTF-8?q?=E4=BB=95=E6=A7=98=E3=81=AB=E6=88=BB=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/発車時刻表/LED_vidion.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/発車時刻表/LED_vidion.js b/components/発車時刻表/LED_vidion.js index bc351d2..14502fd 100644 --- a/components/発車時刻表/LED_vidion.js +++ b/components/発車時刻表/LED_vidion.js @@ -98,7 +98,7 @@ export default function LED_vision(props) { if (!trainTimeAndNumber) return () => {}; if (!currentTrain) return () => {}; const data = trainTimeAndNumber - //.filter((d) => currentTrain.map((m) => m.num).includes(d.train)) + .filter((d) => currentTrain.map((m) => m.num).includes(d.train)) //現在の列車に絞る[ToDo] .filter(timeFiltering) .filter((d) => !!finalSwitch || d.lastStation != "当駅止"); setSelectedTrain(data); From af30d1cbb0ffac53805f28107b3564535219e541 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Tue, 10 Jun 2025 14:26:15 +0000 Subject: [PATCH 39/77] =?UTF-8?q?css=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Menu/Carousel/CarouselTypeChanger.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/components/Menu/Carousel/CarouselTypeChanger.tsx b/components/Menu/Carousel/CarouselTypeChanger.tsx index c2a0850..11f13af 100644 --- a/components/Menu/Carousel/CarouselTypeChanger.tsx +++ b/components/Menu/Carousel/CarouselTypeChanger.tsx @@ -34,15 +34,15 @@ export const CarouselTypeChanger = ({ { returnToDefaultMode(); From c43778c3c53e257c029d5e6a17e6d024bcec16fc Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Tue, 10 Jun 2025 14:36:50 +0000 Subject: [PATCH 40/77] =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=AA=E8=A6=81?= =?UTF-8?q?=E7=B4=A0=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Settings/FavoriteSettings.js | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/components/Settings/FavoriteSettings.js b/components/Settings/FavoriteSettings.js index 9a08d43..f0049ac 100644 --- a/components/Settings/FavoriteSettings.js +++ b/components/Settings/FavoriteSettings.js @@ -2,7 +2,6 @@ import React from "react"; import { View, Text, TouchableOpacity, ScrollView } from "react-native"; import { useNavigation } from "@react-navigation/native"; import { useFavoriteStation } from "../../stateBox/useFavoriteStation"; -import { CheckBox } from "react-native-elements"; import { FavoriteSettingsItem } from "./FavoliteSettings/FavoiliteSettingsItem"; import { SheetHeaderItem } from "@/components/atom/SheetHeaderItem"; @@ -38,21 +37,3 @@ export const FavoriteSettings = () => { ); }; - -const SimpleSwitch = ({ bool, setBool, str }) => ( - - setBool(bool == "true" ? "false" : "true")} - containerStyle={{ - flex: 1, - backgroundColor: "#00000000", - borderColor: "white", - alignContent: "center", - }} - textStyle={{ fontSize: 20, fontWeight: "normal" }} - title={str} - /> - -); From 6ad46c0e632c6fd1448cf743b8eadab2e5d8b216 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Tue, 10 Jun 2025 16:19:43 +0000 Subject: [PATCH 41/77] =?UTF-8?q?=E3=81=8A=E6=B0=97=E3=81=AB=E5=85=A5?= =?UTF-8?q?=E3=82=8A=E4=B8=80=E8=A6=A7=E3=81=AE=E3=83=89=E3=83=A9=E3=83=83?= =?UTF-8?q?=E3=82=B0=E4=B8=A6=E3=81=B3=E6=9B=BF=E3=81=88=E6=A9=9F=E8=83=BD?= =?UTF-8?q?=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FavoliteSettings/FavoiliteSettingsItem.js | 77 +++---------------- components/Settings/FavoriteSettings.js | 70 +++++++++++++---- 2 files changed, 69 insertions(+), 78 deletions(-) diff --git a/components/Settings/FavoliteSettings/FavoiliteSettingsItem.js b/components/Settings/FavoliteSettings/FavoiliteSettingsItem.js index a5f926c..51ba766 100644 --- a/components/Settings/FavoliteSettings/FavoiliteSettingsItem.js +++ b/components/Settings/FavoliteSettings/FavoiliteSettingsItem.js @@ -2,14 +2,10 @@ import React, { useEffect, useState } from "react"; import Icon from "react-native-vector-icons/Entypo"; import { View, Text, TouchableOpacity, LayoutAnimation } from "react-native"; import lineColorList from "../../../assets/originData/lineColorList"; +import Ionicons from "react-native-vector-icons/Ionicons"; import { AS } from "../../../storageControl"; -export const FavoriteSettingsItem = ({ - currentStation, - setFavoriteStation, - index, - array, -}) => { +export const FavoriteSettingsItem = ({ currentStation }) => { const lineIDs = []; const EachIDs = []; console.log(currentStation); @@ -19,27 +15,6 @@ export const FavoriteSettingsItem = ({ lineIDs.push(textArray.filter((s) => "A" < s && s < "Z").join("")); EachIDs.push(textArray.filter((s) => "0" <= s && s <= "9").join("")); }); - const [head, setHead] = useState(false); - const [tail, setTail] = useState(false); - useEffect(() => { - switch (true) { - case array.length == 1: - setHead(true); - setTail(true); - break; - case index == 0: - setHead(true); - setTail(false); - break; - case index == array.length - 1: - setHead(false); - setTail(true); - break; - default: - setHead(false); - setTail(false); - } - }, [array]); return ( @@ -47,7 +22,7 @@ export const FavoriteSettingsItem = ({ style={{ width: 35, position: "relative", - marginHorizontal: 15, + marginHorizontal: 10, flexDirection: "row", height: "101%", }} @@ -91,43 +66,15 @@ export const FavoriteSettingsItem = ({ > {currentStation[0].Station_JP} - { - console.log("up"); - LayoutAnimation.configureNext( - LayoutAnimation.Presets.easeInEaseOut - ); - const removedStation = [...array].filter((d, i) => { - if (i == index) return false; - return true; - }); - removedStation.splice(index - 1, 0, currentStation); - setFavoriteStation(removedStation); - - AS.setItem("favoriteStation", JSON.stringify(removedStation)); - }} - > - {head ? null : } - - { - console.log("down"); - LayoutAnimation.configureNext( - LayoutAnimation.Presets.easeInEaseOut - ); - const removedStation = [...array].filter((d, i) => { - if (i == index) return false; - return true; - }); - removedStation.splice(index + 1, 0, currentStation); - setFavoriteStation(removedStation); - AS.setItem("favoriteStation", JSON.stringify(removedStation)); - }} - > - {tail ? null : } - + + + ); diff --git a/components/Settings/FavoriteSettings.js b/components/Settings/FavoriteSettings.js index f0049ac..5c60747 100644 --- a/components/Settings/FavoriteSettings.js +++ b/components/Settings/FavoriteSettings.js @@ -1,30 +1,57 @@ -import React from "react"; -import { View, Text, TouchableOpacity, ScrollView } from "react-native"; +import React, { useCallback } from "react"; +import { View, Text, StyleSheet } from "react-native"; +import Animated, { useAnimatedRef } from "react-native-reanimated"; import { useNavigation } from "@react-navigation/native"; +import Sortable from "react-native-sortables"; import { useFavoriteStation } from "../../stateBox/useFavoriteStation"; import { FavoriteSettingsItem } from "./FavoliteSettings/FavoiliteSettingsItem"; import { SheetHeaderItem } from "@/components/atom/SheetHeaderItem"; export const FavoriteSettings = () => { const { favoriteStation, setFavoriteStation } = useFavoriteStation(); + const scrollableRef = useAnimatedRef(); const { goBack } = useNavigation(); + const renderItem = useCallback((props) => { + const { item, index } = props; + return ( + + ); + }, []); return ( - - {favoriteStation.map((currentStation, index, array) => ( - - ))} - + + { + const newFavoriteStation = newOrder.indexToKey.map((item,index,array)=>{ + let returnData = []; + favoriteStation.forEach((station) => { + if (station[0].StationNumber === item) returnData = station; + }); + return returnData; + }); + setFavoriteStation(newFavoriteStation); + }} + keyExtractor={(item) => item[0].StationNumber} + /> + { ); }; + +const styles = StyleSheet.create({ + card: { + alignItems: "center", + backgroundColor: "#36877F", + borderRadius: 10, + height: 100, + justifyContent: "center", + }, + contentContainer: { + padding: 10, + }, + text: { + color: "white", + fontWeight: "bold", + }, +}); From 45b41dcef0c3f910412fbb9ccaf93ac7f24f970e Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Wed, 11 Jun 2025 09:58:06 +0000 Subject: [PATCH 42/77] =?UTF-8?q?=E6=96=B0=E3=81=97=E3=81=84=E3=83=87?= =?UTF-8?q?=E3=82=B6=E3=82=A4=E3=83=B3=E3=82=92=E6=9A=AB=E5=AE=9A=E7=9A=84?= =?UTF-8?q?=E3=81=AB=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/webViewInjectjavascript.ts | 76 +++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/lib/webViewInjectjavascript.ts b/lib/webViewInjectjavascript.ts index 492d280..0409e6b 100644 --- a/lib/webViewInjectjavascript.ts +++ b/lib/webViewInjectjavascript.ts @@ -1248,17 +1248,90 @@ export const injectJavascriptData: InjectJavascriptData = ( const returnText2 = (ToData ? ToData+"行 " : ToData)+ TrainNumber; 行き先情報.innerText = ""; 行き先情報.insertAdjacentHTML('beforebegin', "

" + returnText1 + "

"); - 行き先情報.insertAdjacentHTML('beforebegin', "

" + (ToData ? ToData + "行 " : ToData) + "

" + TrainNumber + (JRF ? "":"レ") + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + (ToData ? ToData + "行 " : ToData) + "

" + TrainNumber + (JRF ? "":"レ") + "

"); 行き先情報.insertAdjacentHTML('beforebegin', "

" + (hasProblem ? "‼️停止中‼️" : "") + "

"); } `; const textInsert = ` + + +const setNewTrainItem = (element)=>{ + element.style.borderColor = 'white'; + element.style.borderWidth = '2px'; + element.style.borderStyle = 'solid'; + element.style.borderRadius = '10%'; + element.style.backgroundColor = 'rgba(255, 255, 255, 0.8)'; + element.style.boxShadow = '0 0 4px rgba(0, 0, 0, 0.2)'; + element.style.margin = '2px'; + + element.style.display = 'flex'; + element.style.flexDirection = 'column'; + element.style.alignItems = 'center'; + element.style.justifyContent = 'center'; + element.style.width = '52px'; + element.style.height = '80px'; + element.getElementsByTagName("p")[0].style.textAlign = "center"; + element.getElementsByTagName("p")[0].style.fontSize = '8px'; + element.getElementsByTagName("img")[0].style.float = 'unset'; +} //列番付与 const setStrings = () =>{ try { const elements = document.querySelectorAll('#disp > div > div > div[onclick]'); + const elementBaseBase = document.querySelectorAll('[id^="stationBlock"]'); + elementBaseBase.forEach(e=>{ //それぞれの駅ブロック横一列 + e.style.display = 'flex'; + e.style.height = "unset"; + e.style.flexDirection = 'row'; + //e.style.alignItems = "left"; + e.style.justifyContent = 'center'; + const x = e.querySelectorAll(':scope > div');//配下のdiv要素を選択 + //x[0] 登りブロック x[2] 下りブロック x[1] 駅ブロック + const aaa = (x2,pos) => { + x2.style.display = 'flex'; + x2.style.flexDirection = 'row'; + if(pos == "right"){ + x2.style.alignItems = 'flex-start'; + x2.style.justifyContent = 'flex-start'; + }else if(pos == "left"){ + x2.style.alignItems = 'flex-end'; + x2.style.justifyContent = 'flex-end'; + } + x2.style.flexWrap = 'wrap'; + x2.style.width = '100%'; + x2.style.height = "100%"; + + } + const aaa2 = (x2) => { + x2.style.display = 'flex'; + x2.style.flexDirection = 'row'; + x2.style.alignItems = 'center'; + x2.style.justifyContent = 'center'; + x2.style.flexWrap = 'wrap'; + x2.style.width = '100%'; + x2.style.height = "unset"; + const x3 = x2.querySelectorAll(":scope > div"); + x3.forEach(i=>{ + i.style.position = "unset"; + i.style.display = "flex"; + i.style.flexDirection = "column"; + i.style.flex = "1"; + i.style.backgroundColor = "#00000000"; + i.querySelectorAll(":scope > *").forEach(j=>{ + j.style.width = "100%"; + j.style.textAlign = "center"; + j.style.margin = "5px"; + j.style.padding = "5px"; + }); + }); + } + aaa(x[0],"left"); + aaa2(x[1]); + aaa(x[2],"right"); + + }); for (let element of elements) { if(element.getAttribute('offclick')){ continue; } element.setAttribute('offclick',element.getAttribute('onclick')) @@ -1289,6 +1362,7 @@ const setStrings = () =>{ } ` : ""} nameReplace(列車名データ,列番データ,行き先情報,hasProblem); + setNewTrainItem(element); } try{ for(let d of document.getElementById('disp').childNodes){ From a305aa72028c2d4d40c53f0fad2c1fb991bc9d9e Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Wed, 11 Jun 2025 12:06:55 +0000 Subject: [PATCH 43/77] =?UTF-8?q?=E3=82=AF=E3=83=AA=E3=83=83=E3=82=AF?= =?UTF-8?q?=E3=82=A2=E3=83=8B=E3=83=A1=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0=E3=80=81=E9=80=B2=E8=A1=8C=E6=96=B9?= =?UTF-8?q?=E5=90=91=E3=81=AB=E5=90=88=E3=82=8F=E3=81=9B=E3=81=9F=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E3=81=AE=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/webViewInjectjavascript.ts | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/webViewInjectjavascript.ts b/lib/webViewInjectjavascript.ts index 0409e6b..2bacd30 100644 --- a/lib/webViewInjectjavascript.ts +++ b/lib/webViewInjectjavascript.ts @@ -1247,9 +1247,10 @@ export const injectJavascriptData: InjectJavascriptData = ( const returnText1 = (isWanman ? "ワンマン " : "") + trainName + viaData; const returnText2 = (ToData ? ToData+"行 " : ToData)+ TrainNumber; 行き先情報.innerText = ""; - 行き先情報.insertAdjacentHTML('beforebegin', "

" + returnText1 + "

"); - 行き先情報.insertAdjacentHTML('beforebegin', "

" + (ToData ? ToData + "行 " : ToData) + "

" + TrainNumber + (JRF ? "":"レ") + "

"); - 行き先情報.insertAdjacentHTML('beforebegin', "

" + (hasProblem ? "‼️停止中‼️" : "") + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + returnText1 + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + (ToData ? ToData + "行 " : ToData) + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + TrainNumber + (JRF ? "":"レ") + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + (hasProblem ? "‼️停止中‼️" : "") + "

"); } `; @@ -1265,16 +1266,27 @@ const setNewTrainItem = (element)=>{ element.style.backgroundColor = 'rgba(255, 255, 255, 0.8)'; element.style.boxShadow = '0 0 4px rgba(0, 0, 0, 0.2)'; element.style.margin = '2px'; - element.style.display = 'flex'; - element.style.flexDirection = 'column'; element.style.alignItems = 'center'; - element.style.justifyContent = 'center'; + element.style.justifyContent = 'flex-end'; element.style.width = '52px'; element.style.height = '80px'; - element.getElementsByTagName("p")[0].style.textAlign = "center"; - element.getElementsByTagName("p")[0].style.fontSize = '8px'; element.getElementsByTagName("img")[0].style.float = 'unset'; + element.style.webkitTapHighlightColor = 'rgba(0, 0, 0, 0)'; + element.style.transition = 'transform 0.1s ease-in-out'; + element.addEventListener('touchstart', () => element.style.transform = 'scale(0.8)'); + element.addEventListener('touchend', () => element.style.transform = 'scale(1)'); + if(element.getAttribute("style").includes("left")){ + // borderを使って五角形を生成 下り + element.style.borderRadius = '20% 20% 80% 80%'; + element.style.flexDirection = 'column-reverse'; + } + else if(element.getAttribute("style").includes("right")){ + // borderを使って五角形を生成 上り + element.style.borderRadius = '80% 80% 20% 20%'; + element.style.flexDirection = 'column'; + } + } //列番付与 const setStrings = () =>{ From c0f7a9b931d877fb893d2cc308a02e6806c46c6c Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Wed, 11 Jun 2025 12:44:52 +0000 Subject: [PATCH 44/77] =?UTF-8?q?=E3=83=86=E3=82=AD=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=81=AE=E3=83=AC=E3=82=A4=E3=82=A2=E3=82=A6=E3=83=88=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/webViewInjectjavascript.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/webViewInjectjavascript.ts b/lib/webViewInjectjavascript.ts index 2bacd30..a2e8260 100644 --- a/lib/webViewInjectjavascript.ts +++ b/lib/webViewInjectjavascript.ts @@ -52,7 +52,7 @@ export const injectJavascriptData: InjectJavascriptData = ( const trainIcon = ` const setStationIcon = (setIconElem,img,hasProblem) =>{ const position = setIconElem.getAttribute("style").includes("left"); - setIconElem.insertAdjacentHTML('beforebegin', ""); + setIconElem.insertAdjacentHTML('beforebegin', ""); setIconElem.remove(); } @@ -1247,8 +1247,8 @@ export const injectJavascriptData: InjectJavascriptData = ( const returnText1 = (isWanman ? "ワンマン " : "") + trainName + viaData; const returnText2 = (ToData ? ToData+"行 " : ToData)+ TrainNumber; 行き先情報.innerText = ""; + 行き先情報.insertAdjacentHTML('beforebegin', "

" + (ToData ? ToData + "行 " : ToData) + "

"); 行き先情報.insertAdjacentHTML('beforebegin', "

" + returnText1 + "

"); - 行き先情報.insertAdjacentHTML('beforebegin', "

" + (ToData ? ToData + "行 " : ToData) + "

"); 行き先情報.insertAdjacentHTML('beforebegin', "

" + TrainNumber + (JRF ? "":"レ") + "

"); 行き先情報.insertAdjacentHTML('beforebegin', "

" + (hasProblem ? "‼️停止中‼️" : "") + "

"); } @@ -1268,9 +1268,10 @@ const setNewTrainItem = (element)=>{ element.style.margin = '2px'; element.style.display = 'flex'; element.style.alignItems = 'center'; - element.style.justifyContent = 'flex-end'; - element.style.width = '52px'; - element.style.height = '80px'; + element.style.justifyContent = 'center'; + element.style.width = '4.5em'; + element.style.minHeight = '80px'; + element.style.height = '100%'; element.getElementsByTagName("img")[0].style.float = 'unset'; element.style.webkitTapHighlightColor = 'rgba(0, 0, 0, 0)'; element.style.transition = 'transform 0.1s ease-in-out'; From a7ccb0b41fa99f9173d582f6b89d33449e02ac3b Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Wed, 11 Jun 2025 12:47:57 +0000 Subject: [PATCH 45/77] =?UTF-8?q?threw=E3=81=AE=E5=8B=95=E4=BD=9C=E6=9D=A1?= =?UTF-8?q?=E4=BB=B6=E3=82=92=E3=81=8A=E3=81=BE=E3=81=91=E3=81=A7=E5=A4=89?= =?UTF-8?q?=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/ActionSheetComponents/EachTrainInfoCore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/ActionSheetComponents/EachTrainInfoCore.js b/components/ActionSheetComponents/EachTrainInfoCore.js index c419bb7..c6f7cc0 100644 --- a/components/ActionSheetComponents/EachTrainInfoCore.js +++ b/components/ActionSheetComponents/EachTrainInfoCore.js @@ -170,12 +170,12 @@ export const EachTrainInfoCore = ({ const position = points.findIndex((d) => d == true); let isThrew = false; if (position == -1) return () => {}; + setShowThrew(true); if (trainDataWidhThrough[position].split(",")[1] == "通過") { LayoutAnimation.configureNext({ duration: 400, update: { type: "easeInEaseOut", springDamping: 0.6 }, }); - setShowThrew(true); isThrew = true; } if (position < 5) { From c8356fad2f691e23952de122b209fda3c39c0c9d Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Wed, 11 Jun 2025 12:52:37 +0000 Subject: [PATCH 46/77] =?UTF-8?q?=E3=83=87=E3=83=BC=E3=82=BF=E3=81=8C?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E3=81=95=E3=82=8C=E3=81=A6=E3=81=84=E3=81=AA?= =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=9F=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Settings/FavoriteSettings.js | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/components/Settings/FavoriteSettings.js b/components/Settings/FavoriteSettings.js index 5c60747..99ed924 100644 --- a/components/Settings/FavoriteSettings.js +++ b/components/Settings/FavoriteSettings.js @@ -6,6 +6,7 @@ import Sortable from "react-native-sortables"; import { useFavoriteStation } from "../../stateBox/useFavoriteStation"; import { FavoriteSettingsItem } from "./FavoliteSettings/FavoiliteSettingsItem"; import { SheetHeaderItem } from "@/components/atom/SheetHeaderItem"; +import { AS } from "@/storageControl"; export const FavoriteSettings = () => { const { favoriteStation, setFavoriteStation } = useFavoriteStation(); @@ -14,10 +15,7 @@ export const FavoriteSettings = () => { const renderItem = useCallback((props) => { const { item, index } = props; return ( - + ); }, []); return ( @@ -40,14 +38,17 @@ export const FavoriteSettings = () => { scrollableRef={scrollableRef} // required for auto scroll snapOffsetY={0} onDragEnd={(newOrder) => { - const newFavoriteStation = newOrder.indexToKey.map((item,index,array)=>{ - let returnData = []; - favoriteStation.forEach((station) => { - if (station[0].StationNumber === item) returnData = station; - }); - return returnData; - }); + const newFavoriteStation = newOrder.indexToKey.map( + (item, index, array) => { + let returnData = []; + favoriteStation.forEach((station) => { + if (station[0].StationNumber === item) returnData = station; + }); + return returnData; + } + ); setFavoriteStation(newFavoriteStation); + AS.setItem("favoriteStation", JSON.stringify(newFavoriteStation)); }} keyExtractor={(item) => item[0].StationNumber} /> From dfc2fa5c891dfe83049cc36977faa418a84c4b45 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Wed, 11 Jun 2025 13:21:40 +0000 Subject: [PATCH 47/77] =?UTF-8?q?=E3=82=A2=E3=82=A4=E3=82=B3=E3=83=B3?= =?UTF-8?q?=E3=81=AE=E5=8F=96=E5=BE=97=E3=81=8C=E3=82=AD=E3=83=A3=E3=83=83?= =?UTF-8?q?=E3=82=B7=E3=83=A5=E5=84=AA=E5=85=88=E3=81=95=E3=82=8C=E3=81=A1?= =?UTF-8?q?=E3=82=83=E3=81=86=E7=8A=B6=E6=85=8B=E3=81=AB=E3=81=AA=E3=81=A3?= =?UTF-8?q?=E3=81=A6=E3=81=84=E3=81=9F=E3=81=AE=E3=81=A7=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/custom-train-data.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/components/custom-train-data.ts b/components/custom-train-data.ts index 3cf8526..59c049a 100644 --- a/components/custom-train-data.ts +++ b/components/custom-train-data.ts @@ -1,5 +1,6 @@ import dayjs from "dayjs"; export const customTrainDataDetector = (TrainNumber: string) => { + const trainGetText = `?trainNum=${TrainNumber}&month=${dayjs().format("M")}&day=${dayjs().format("D")}`; switch (TrainNumber) { //しおかぜメイン //8000 ノーマル @@ -49,7 +50,7 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "しおかぜ", - trainIcon: `https://n8n.haruk.in/webhook/anpanman-pictures.png?trainNum=${TrainNumber}`, + trainIcon: `https://n8n.haruk.in/webhook/anpanman-pictures.png${trainGetText}`, infoUrl: "https://www.jr-eki.com/aptrain/naani/yosan/train.html", trainNumDistance: 0, info: "いしづちと併結 / アンパンマン列車で運転", @@ -114,7 +115,7 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "いしづち", - trainIcon: `https://n8n.haruk.in/webhook/anpanman-pictures.png?trainNum=${TrainNumber}`, + trainIcon: `https://n8n.haruk.in/webhook/anpanman-pictures.png${trainGetText}`, infoUrl: "https://www.jr-eki.com/aptrain/naani/yosan/train.html", trainNumDistance: 1000, info: "しおかぜと併結 / アンパンマン列車で運転", @@ -173,7 +174,7 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "いしづち", - trainIcon: `https://n8n.haruk.in/webhook/anpanman-pictures.png?trainNum=${TrainNumber}`, + trainIcon: `https://n8n.haruk.in/webhook/anpanman-pictures.png${trainGetText}`, infoUrl: "https://www.jr-eki.com/aptrain/naani/yosan/train.html", trainNumDistance: 940, info: "アンパンマン列車で運転", @@ -247,7 +248,7 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "南風", - trainIcon: `https://n8n.haruk.in/webhook/anpanman-pictures.png?trainNum=${TrainNumber}`, + trainIcon: `https://n8n.haruk.in/webhook/anpanman-pictures.png${trainGetText}`, infoUrl: "https://www.jr-eki.com/aptrain/naani/dosan/train.html", trainNumDistance: 30, info: "アンパンマン列車で運転", @@ -587,7 +588,7 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "宇和海", - trainIcon: `https://n8n.haruk.in/webhook/anpanman-pictures.png?trainNum=${TrainNumber}`, + trainIcon: `https://n8n.haruk.in/webhook/anpanman-pictures.png${trainGetText}`, infoUrl: "https://www.jr-eki.com/aptrain/naani/yosan/train.html", trainNumDistance: 1050, info: "アンパン列車で運転", @@ -621,7 +622,7 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "あしずり", - trainIcon: `https://n8n.haruk.in/webhook/anpanman-pictures.png?trainNum=${TrainNumber}`, + trainIcon: `https://n8n.haruk.in/webhook/anpanman-pictures.png${trainGetText}`, infoUrl: "https://www.jr-eki.com/aptrain/naani/first-generation/jikoku.html", trainNumDistance: 2070, From 7b4badb9b078abb74ce7e38e815fb65199197345 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Wed, 11 Jun 2025 13:47:37 +0000 Subject: [PATCH 48/77] =?UTF-8?q?injectJavascript=E3=81=AB=E5=A4=89?= =?UTF-8?q?=E5=8C=96=E6=9D=A1=E4=BB=B6=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/webViewInjectjavascript.ts | 128 ++++++++++++++++++--------------- 1 file changed, 70 insertions(+), 58 deletions(-) diff --git a/lib/webViewInjectjavascript.ts b/lib/webViewInjectjavascript.ts index a2e8260..3645b7f 100644 --- a/lib/webViewInjectjavascript.ts +++ b/lib/webViewInjectjavascript.ts @@ -2,13 +2,15 @@ type InjectJavascriptData = ( a: string, b: string, c: string, - d: string + d: string, + e: string ) => string; export const injectJavascriptData: InjectJavascriptData = ( mapSwitch, iconSetting, stationMenu, - trainMenu + trainMenu, + uiSetting ) => { // 一番上のメニュー非表示 地図スイッチによって切り替え const topMenu = @@ -1247,11 +1249,17 @@ export const injectJavascriptData: InjectJavascriptData = ( const returnText1 = (isWanman ? "ワンマン " : "") + trainName + viaData; const returnText2 = (ToData ? ToData+"行 " : ToData)+ TrainNumber; 行き先情報.innerText = ""; - 行き先情報.insertAdjacentHTML('beforebegin', "

" + (ToData ? ToData + "行 " : ToData) + "

"); - 行き先情報.insertAdjacentHTML('beforebegin', "

" + returnText1 + "

"); - 行き先情報.insertAdjacentHTML('beforebegin', "

" + TrainNumber + (JRF ? "":"レ") + "

"); - 行き先情報.insertAdjacentHTML('beforebegin', "

" + (hasProblem ? "‼️停止中‼️" : "") + "

"); - } + ${uiSetting === "tokyo" ? ` + 行き先情報.insertAdjacentHTML('beforebegin', "

" + (ToData ? ToData + "行 " : ToData) + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + returnText1 + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + TrainNumber + (JRF ? "":"レ") + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + (hasProblem ? "‼️停止中‼️" : "") + "

"); + `: ` + 行き先情報.insertAdjacentHTML('beforebegin', "

" + returnText1 + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + (ToData ? ToData + "行 " : ToData) + "

" + TrainNumber + (JRF ? "":"レ") + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + (hasProblem ? "‼️停止中‼️" : "") + "

"); + `} + } `; const textInsert = @@ -1293,58 +1301,62 @@ const setNewTrainItem = (element)=>{ const setStrings = () =>{ try { const elements = document.querySelectorAll('#disp > div > div > div[onclick]'); - const elementBaseBase = document.querySelectorAll('[id^="stationBlock"]'); - elementBaseBase.forEach(e=>{ //それぞれの駅ブロック横一列 - e.style.display = 'flex'; - e.style.height = "unset"; - e.style.flexDirection = 'row'; - //e.style.alignItems = "left"; - e.style.justifyContent = 'center'; - const x = e.querySelectorAll(':scope > div');//配下のdiv要素を選択 - //x[0] 登りブロック x[2] 下りブロック x[1] 駅ブロック - const aaa = (x2,pos) => { - x2.style.display = 'flex'; - x2.style.flexDirection = 'row'; - if(pos == "right"){ - x2.style.alignItems = 'flex-start'; - x2.style.justifyContent = 'flex-start'; - }else if(pos == "left"){ - x2.style.alignItems = 'flex-end'; - x2.style.justifyContent = 'flex-end'; + const setNewTrainItemUI = ()=>{ + const elementBaseBase = document.querySelectorAll('[id^="stationBlock"]'); + elementBaseBase.forEach(e=>{ //それぞれの駅ブロック横一列 + e.style.display = 'flex'; + e.style.height = "unset"; + e.style.flexDirection = 'row'; + //e.style.alignItems = "left"; + e.style.justifyContent = 'center'; + const x = e.querySelectorAll(':scope > div');//配下のdiv要素を選択 + //x[0] 登りブロック x[2] 下りブロック x[1] 駅ブロック + const aaa = (x2,pos) => { + x2.style.display = 'flex'; + x2.style.flexDirection = 'row'; + if(pos == "right"){ + x2.style.alignItems = 'flex-start'; + x2.style.justifyContent = 'flex-start'; + }else if(pos == "left"){ + x2.style.alignItems = 'flex-end'; + x2.style.justifyContent = 'flex-end'; + } + x2.style.flexWrap = 'wrap'; + x2.style.width = '100%'; + x2.style.height = "100%"; + } - x2.style.flexWrap = 'wrap'; - x2.style.width = '100%'; - x2.style.height = "100%"; - - } - const aaa2 = (x2) => { - x2.style.display = 'flex'; - x2.style.flexDirection = 'row'; - x2.style.alignItems = 'center'; - x2.style.justifyContent = 'center'; - x2.style.flexWrap = 'wrap'; - x2.style.width = '100%'; - x2.style.height = "unset"; - const x3 = x2.querySelectorAll(":scope > div"); - x3.forEach(i=>{ - i.style.position = "unset"; - i.style.display = "flex"; - i.style.flexDirection = "column"; - i.style.flex = "1"; - i.style.backgroundColor = "#00000000"; - i.querySelectorAll(":scope > *").forEach(j=>{ - j.style.width = "100%"; - j.style.textAlign = "center"; - j.style.margin = "5px"; - j.style.padding = "5px"; + const aaa2 = (x2) => { + x2.style.display = 'flex'; + x2.style.flexDirection = 'row'; + x2.style.alignItems = 'center'; + x2.style.justifyContent = 'center'; + x2.style.flexWrap = 'wrap'; + x2.style.width = '100%'; + x2.style.height = "unset"; + const x3 = x2.querySelectorAll(":scope > div"); + x3.forEach(i=>{ + i.style.position = "unset"; + i.style.display = "flex"; + i.style.flexDirection = "column"; + i.style.flex = "1"; + i.style.backgroundColor = "#00000000"; + i.querySelectorAll(":scope > *").forEach(j=>{ + j.style.width = "100%"; + j.style.textAlign = "center"; + j.style.margin = "5px"; + j.style.padding = "5px"; + }); }); - }); - } - aaa(x[0],"left"); - aaa2(x[1]); - aaa(x[2],"right"); - - }); + } + aaa(x[0],"left"); + aaa2(x[1]); + aaa(x[2],"right"); + + }); + } + + ${uiSetting === "tokyo" ? `setNewTrainItemUI();`: ``} for (let element of elements) { if(element.getAttribute('offclick')){ continue; } element.setAttribute('offclick',element.getAttribute('onclick')) @@ -1375,7 +1387,7 @@ const setStrings = () =>{ } ` : ""} nameReplace(列車名データ,列番データ,行き先情報,hasProblem); - setNewTrainItem(element); + ${uiSetting === "tokyo" ? `setNewTrainItem(element);`: ``} } try{ for(let d of document.getElementById('disp').childNodes){ From b5b9558136f02741e7ba472e09b244bf055a294b Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Wed, 11 Jun 2025 14:18:00 +0000 Subject: [PATCH 49/77] =?UTF-8?q?=E8=A8=AD=E5=AE=9A=E6=A9=9F=E8=83=BD?= =?UTF-8?q?=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/configuration/layout_default.jpg | Bin 0 -> 31145 bytes assets/configuration/layout_tokyo.jpg | Bin 0 -> 27640 bytes components/Settings/LayoutSettings.js | 13 +++++++++++++ components/Settings/settings.js | 5 +++++ components/atom/SwitchArea.js | 6 ++++-- stateBox/useTrainMenu.js | 12 +++++++++++- 6 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 assets/configuration/layout_default.jpg create mode 100644 assets/configuration/layout_tokyo.jpg diff --git a/assets/configuration/layout_default.jpg b/assets/configuration/layout_default.jpg new file mode 100644 index 0000000000000000000000000000000000000000..58d99d9c228d9d74d65317d59bd6e362b9d41fed GIT binary patch literal 31145 zcmdpe2Ut_vwr&vHwr-jzQnpkHO?n3vA{~SzgpLww=)HrLYCu3hx>5p3NDz<~no93d zLJz$|=tcU&efHLU&OP_MbHDe!`@VMV%>_`3g}`11L}S6eoXxU>m^c-)R8g!O0#VbVo>3>W-L{px|#p z!cup{rG$jPA3oWR#{j>oK2Ui8pg5`ad)?z9fC7N>)T!^ElkN1$=gj#tXHK6!bK%^% zv*#~exOC~_g^L$2U!nf>@)fEp7cc&L?N=%qS~@zqOIPWyU!%QFO-o1noe2fyNuASY zemQgI7uw4gFVp^)x8qL$s`IB(PNh&%umVm|QBYD*9M=MvPnt=2(%SFeKen^y&Yw9= zaq1V!3n%BHzXB*Izc>EE#dD`lojZH(M6OdOGMqg}MSbf$tso7n*gfsXE>Zb~bl2#G z#C4#~u5Mkwu-$(e9rNb>XJNDJ>~N1~1)VoI6kzVL5@21uFE!mKY#IM{ONyU&1^n%{ zl&4P4Do~y1?nGthF8xAz=5N>hep9NmF1G|lMDMxgpQF|WKX#6aeqYepMRSdwRS5F* z^A}n=9d_aS*$|*9-lT@OxbEez=r*fq+t|C>gG9@W9sp@G}=OUTJ zksUJkc|Z@a^-un{dPx#N!Gg^zc{sPWM((lf=mfU$WtE#Iq|Tv@(a6RmJEtOnhlNYJ zyG;Co+0@f-E>g=9bIU-QNKa&i!0bUYR=W4HS<{F8I@C~BN1+jLe)JOE+LTBIWCb#{ zIiT%%m+Sg5K*{hWs^q$A#R$Ht6RGQtwJ6VNU=Xd?Z!(F1`lL&nyEq*-``TAB+vFmP zp@xq98C4IB5&XQR1+ntpj4LoTEjEer84Ul>%3w$pYsHtMNIk(;9inaNJbanh^N}2e zm=^+?a1V#JwGh6w$ZKrTKNLz@*O^MR<>#^2OWw?LZ)bP`^Gf>C?sxFciKP>RTlyv{ zj3|a{8+UDJAna*<3rrSC(7gC?&%$tb#Q{vxHhQ2HW`#nMBbh)X_SRqIc@RFGyyh!zbW zY1ur6geB3n@M%PhOGjzbkyrXWfMsH)LUGH_duHkNNygDu#k{Dfo>wq!1DmMG?ARdz zzbTh(*Sq|W{_GHdUk?pdsjIufM?^YM&xm;xJcqX{C)M{X_!p9Q9WmJ>IP0YbR;-Wj zEtFgQ+;+!Y(+Z0# zbB_^as3@qR4PJ{=RaA`eFH;e69GIZ| zj4^#(bb)C%eXs{tTVl|!CicZ)7?m@=E06|F4%B>B2KK5 zG1nE20P>Hx2_n-#BI{{7&J|kxb6Z#LEG{&@*;0v7fuu}&8V@nH9FmPXpjWEla`^gJ5Q}l7u*f$dzyX1uH$x1uDT@TtEu;9i9*q0 z1LhM@NNgphO1`vJ+|a=h?Kym9*QtllZxt_sd-pE1c+W!3MX?~mggCA#I#6zR*d~ql z!MS}|kuVXD5K8n5zEvhfYoP{h4U4UqiE0cBFA$GA;%gPf=~bp<_3cIVn9>(L>yiTf zITRr~`fP?s-_p#4kBe2UB!YQCh!?Yt>pB-etKDpBF&K1(|z7wpR?vXt^VfJ}hXK+IxoEkYOJ4i6PB+SrM%Kg4>8&+G{L9_}m+MR`9FuG~*g0i_m< zMm_enn8?0UtWrt4`?B5kCA*y`H_h`RI>Uj2Y~kv3AK^FSWxe18OIVBh;I3cTZN?U; z^hA)DaK7&rbeN!pX{;r?f_Kw6%_Qoertg0p-Fh~kII_smvxFvnW24r!fu4ETn( z?F?{@@)(V3YV?t+(Gq*pWtO5jU{T|M!^bfMOB2*<;ZaaJh6*jHF%f3Y|1m1Of6BB> z>qBVh1RY(x0s<>)kRjHBUmG!2oNX{G>b{?^^Yy{hN-7R&!VPmLky5Kn$l{%Q$U7ZE zh;rF_i4TkQMD=_uR5vjnwiAi;WoY19-Bpuex%=bsotFREHQp8d>@o>zglsv(1@sQq zKw7X7Gm_e9lftnlTev6W+d#d3E3;auIPig%*Mx~RDRst<1?o8b()X=P%Mj6{5x{=+ z2m61IxGP%oNkv|erATG>haF{2g0)JF;PDM$p6OoC_bERursbsa{LWL4$WK~`H(D+c zZnf@#&2J_V-lCN&gF3%b|u5dj{A1*bI_muUAgO z+Ng}*|eP%xX2NU#FpBZqkJ5YrflH4 zomf1ZWUFwih8N>Av&7peJe7jEiksbvfz5suCQZuZvDI%p&VfudkkvY>hFR?A^S<1L zOKsFj>cs?@2j^j(*pcyi8i~LKgN^Er(sitn8LAJVjRs?fHvLA$J0q>wvXDHKEk4g2 zESTxd(mLxECUIx8+d(FZr3#ZW$Y=T>8A4CA?Jo2n$Zvtb->U33e$kYKI=rzbLk}11 zcMhhGEGn+X+R2@27;Ro2uIcL(>4P*Z(y1>p-xn_5S~aslO?jJ1KfY93bblyX_TvWE zL%fM`J7~qIdOdHSM(Api4U+lZ&4nC;LFq8h#u-#wl;8Y>sbupfVN9aIO8Cz5?S)B` zS=s^*%pvp`U~ye$k>$|D<0XVN;Oy@x>3|8Iu5PeT#kKUN9q5Os7-8KD6h~O37j~*v4LZ$5M zZmAyzX-YvQAkyyWRq9%8MQ6EeYrh<3wCuvpo$2@z4EZ%cnfc%AYd@~~F)58%r@%9x zQrQhT#DK)|-a1zr8%LmEEx9WS(hN#k6&F7SobrXV{hX@aPMv0)4_P<{#B$g7tlRpI ze$4!h@*(!l-#EWSr0Oi5iNto78S2AE1Pup!*3hCrp27feM5{>T%6txy%5Y);O?d5} z*I-g(u@>~DJ>HRcZ9eUse}jA`f@~pXT^5oQ4`1%2fgGi6$J(Saw|cZUqu+)*VGy#* zCcQ~g9UkjWMvuE}(*bl=7>5?r5UX_)om3x5gAJLi+s z5qj?vpJyAT?WS5L=L)eYf zXLFd)P9;5cpDb1uOb!^Z%5sa$D(R|Ip~-^4u-9vCq0J#7*aFUdRwhc;MNUG^>xH^L zYIF~3K9wVKM*>gx29b6i)>Bzw+{~d{{uJlXj8`;4Sd)44^83b$OW_FO9$0ep(z?Z2rYU2%Ok*rBsR_L+~Nk|=$7G`j+bc~M(zT575#qiLljqkE=8>Qey&h-meCz? zdl>(P-iTHgU`ciXgVj&N7GfjNNlxpG8Ig!j6t^l%I!83zxn(lLSg^fiTmblm^3&gp z%)k5l>yKGiz>hIj8AaTsb_?(%*w)EnIWXTL%3rZAK%}2Nf-~DNc;|Iqte?$6 zqh+r}U;eIV*JHM0Kv81)G_!touvV{Vq;!6)+3oz06^Ek>6Evqr#M2r*t{jKxbAoj(_pmyR|f-9#*rp@t4dqRJLKJ%<^J~qvW$L znvaja9TK#?L~B#fif#~&sox@Rc`((~6%1Gm=kcbGupJK0*yj15d;J-y_T=q4Xf%0f zL=6uFGnEnn6nrjEe(wj%kB_<9m5py2$rc z_6kPrTNXY}`HQoA*rS(W4+@a-AE%WIw5UJBN`P;@rFVA&6HMSPj1H9aCRVRuw0)+R zJr)k=cHswz_03%g_t*Lj`qhX#{ofKoCNT1}evjGBk+C7$lFSX9b2Iq4>?Z94g;r;A zVE?ke<>{HIqPbB+mXTusdPlwHp|y0AU5W+x8zF;q42bfO4;i|!I_fI?$)pGtoqCkk zh4DJPTKERk&M3MEjO3k{3pM2GvYAAMcD1mXA<^ZjTLV;b>p4bw5AnuRVgVTJfiYD7 z7?9#2cO(0TCYa4MkiaYGSnUE^!}zy3`UE!@S1t1_TXs(X;Qo7O!U+u0>4Dc@`?-1NnAS{0#XlvUDm*>HPf zt#k!0p@F4~Jjy;tyO1Q6ZsKS5Li}SBw z2)zEvAM25Q@hQqIVGo-=WO}Y0~$?kU4(QTan>b|q z$-KxYrp|cFdbb1fZFD`mTb}1WrR)KATHc21+gd=>PtJpQl?nXbN55I3pW`lgJ}ve= zMd}fBJ?&%6fmgNiPtIf*`x?yOK+bicO8fx5+0p#A2XE- zT)`@}`@`x_)`xNly9U4hb2ZBSsYSW}=SsZdzkUo*i0G6;5j?)sYHndFH~Jb+AdrxF zNP+iToO_!#eSISwvDcaDLYRcQrdVQg;!w~dNfW&3mZW5)yC1K?+m>9YXa{XyreZ*p za9)z0&xd_J&+5=xBcx1X>%JM2Q3EiIzd{bLxa?FUaVtFV?dTz_-sy=jUVz@0DWF1= z6~9NA)lUO{E<%LUg36sUm1xxGf6RoVF8@HDHe8l=gdgo;1E#oTYT`^ru*G*Ne)IYV zqwq(O*`b;xYUF+2;gt8J{SyqrYD# zbr7KB6A3t*7ib#UxbkpuZI@|52Eg#&T2-5}mw?iE-q@SI(#uBP?}>ZuZ??*>)o|iT z10!~WZxV_93)A2uLi^@zCyJnW>whl&A4e%w<~0o2KJi_Kc+3q*%Tv`B{x1LX`QRtT zd7z`U+RTxge_|=Zcha`LgDLUVzhC42T|dkxz{+KlqrYlW)OYW@mV&=)NP7%GT=`u~ zOy8BO^n?=jca{IUsy+m;{Bt#&x|(Zprs><-J|y|qf1*aCKehO`b^kx-0RT`c{M1*t z%|BJ$pD+~Te-R^pzDWPnB|zrHadetRui|3N+T=ExcChMk{g%6jR2huFu<`;U;BnUQ zf7Z0W9sj!bc#IF*8Cc=W%{usl6c6ff6}yTlS-$_ORnmgIP;L&OKKEbrZ2h)ZH)fO; zd4kP;KG!R7YU;r2FEAM%dIFQ(4+dPf@%-2A6OnuCbrG>?y27ZcT>OL77%v=dd%l3% zf1M$GMc>y4KL9xWwBuiM`p2{9$FhY>tLm&#LE?4v5s$kVu)1(}84WUR|O3 z3lT?$21><#U-1;_)*>xT@61>Y2c*7{q}EmzWx-<-n@i*F>9Oc(b8F((d+W~OY*9?a zUitP!-no%9hmbZy?U!L6!+_nJ-wGe`haZJKgyeS_Wc#yMq8Y<$>y80#KwnZ&2{X=} z&y9yRw7>ex)Oz~2#w(r$WvGt!(w0CMFH8i3zbs3xLgllzJEcb#MV-EJJqz4P=m1dB zL;g`Ezn3ZO!3!_L)kF$fOnnnI7MK@&5USSuIFNccTd|#;rh_TNF4cLQxQbC#(cH*1a#2-}rz*A1qvz3nO?6pcw+( zM)y<@FTaFthO2}Y&;v0YL>9&{d=&dGsoQ;Ns3aeHg%p{EM-SSv;oX^8PDinaB#Q{x z8bt%86N`0Miiaci>qZ)0R>0@Aojn4l)3R|btB0tC9)RlEDCWvpL4B>Iy9w0>* zR)P}hU}tH@K5u}WrZdaLoJL2-Ge6H;QvUL^kTQ9{!Z8MyKbPc*{tW3Qcg#3e%f>8z zd#g^6-h6FYZQ{=S^zBldKxoOlomT9YjTE#>yb{aGDp>K$2rIdxq$JAidc(F8mj`bC z9CR{C+d<|Su!cDX93Z3ja^R^FEIcHICEHUF9DQ6P}q zXG@Grh*gWoYQGJfu}wv4Bvxo@bV9YgVE&QGwpsj%rXS*_TrI_Ct{Si^LZ0&?d;1J$QHP0aGQc=p$16n=3uDEGHCGj zHYo=?h}VeHntcXJnJbP^@yVE*e4+G0#X1bLr3EqyH#JsmEFER*)c>+IP8#ArET^c( z?J%fSUZVRbdZ)Luz4pY3?oF*ch1ljXN{*G8gNm8F?&)if@je^T-9KxP#23d?r!mb1 z3Z+_P5aY1AGB>>(Qdt?2NvW}^pt+@x!E{+JjZ|<+;A#^>KkELzJ)!}ujLFG+iua^` zP^(*psbAOhy>a!v56}2s-3!|w>&n9bv&pe2z~ML!@!{OX;cEj(l|x>N@_t`Sl$TpIZZNOaB^dI3?2JLbND* zZjt1=XpH(S(AiT=u$=^j8qIiZOB~)2iGjiNMBEd^@O=J!DYYBM8tp$c1qen z4YTP}9@#T;+dlrH1r4X|Blj=ToC>DtuJ3JzlBuw6**eG2BN_k|7K&aN_l)4N;#^2_3*qAFBSXwwjh zlXSDd+ps#x_3pSnE=Jqg&_N}_$c!++FUa0gMA>D}ySc2qmt}Bf)I2%{ z9B$EYV6ma}ZcjH<=Y6An&Tk^fO;EbKDU1BYW(?_P`l*=%A6Ga(lbxnuc3i(jtnXh|=tSa?m_8nGcr=FBI*ETc8D%$rIfoGbb~AKt zHjrTBVuMq^!7D;rX-1F=+v}B6*2xl!jJ{tl2~Lwcnb@D38_Bff>#me;b}8w?x$^2_ zuo-BBqcaJ&UUuCXlOs`7$kwnYXpGl2OumfH#9Hbr*2amS zc!Aj7h9zak{#s1X0VC-8G?Sg9J~309KJY=PYi z$)^rOIJgY6&}9tOMr;)oa<*gP^owS3L1Smc-8>8~C&NpPtYcXU132M)C&5KcEO zE_s9edyAs-3wF*ZCc@GMsLLd`QAY}!A^?EgKOOE)4*s0qN&J{p{Q%>M&1ENG{KGLO zBZKbMk$VbC2SUoprk;qm;aANnpbNZ)NCd`=twT6{q0Cq;CvjmSglIW0ceasxz#ETb z5=kCIHf?|x{iomgn}vQ*Z0t|wHDfafolumkpKC0zlLI}?I2RnjFFB9#u?*Zf?ZnON zAv7a(Fj6Mx$nHgFQay8nKY74j5}Ifp-DZz78<~r{R%wyxvRX!VL6LPGtJ%^L5&pfq z=<6o8Ui8&Bz#hcg;t+}hI>6H!gQ2xyA+wlt*0{D2qK01)aR_T>w;8J~bp!6=5Mdi* zp&+%%{bkDSaP($BnsCGMN79DsqBkSo9=q9YT2eia~l~Og?FZ+5{vwgHqkD$c% zh@{6%gZINF%C^uN{d#@u)esagJ*Uge=kcClnQ`L8bXnKqILB+~rFiZ+jA0G0=C~>A z?$@=rs#1M}zE0!oq-64V6u4m$1blwgo>NfPJdW~$kIO-c@n**W+?UQk zl-I#p{i&n^1gN+scb8QCTT>4CV`syI1yx(5>n(&spED2DvLrKQ?s(f`HofKYhSh5c zDtwT*J%;Tp(e{F!i|EqiW)o2#DUA}4i{EnH@V+fay-EINPp6bE#98aW%+i-rWHlDf z+iB`8+(|Q^Lf@xvvctU^qOIh!%x}Oc+AYbZnBu9lK4h*%v7us#gN$?&eB}1`m zI|!tgmuSQZ{?!!)xFX&A*O#llQgYnQCncg6<9Jy%`X#$5wocmxA%Fw-n)@0hb3aTr z4D4lJI|j4{yjb+0zn8OD$1H5h=u%uxoBqHPLc;mz!dA-yru!T9Q;|x~%;|K)v!XBf zEH)Sk?7ld@SWLAe=cG+a@|xcPE&@|`F(5RP9HV=r=gymjKWm8tMd(l z(-Hjfed4iLWM{gp`10#*fy3w&?ss9BP9+UsQDc2=fhcUD&_YX}%7e!SGSE9mN9AXy zur#dGyEVY~Red0iMpkOU*nbg9k`oY+AJM-OyD=MqtI z<`rliy?1M0j$OrVQ4WF-#I8)0JEmc#+Lp3U(vSe3= zox%pH&RjR!u~a&Z$DgGhxIu^-s?Rl@Y<1r~9(cKKNaEdsB476CsA6W>x{=`p&Q43o zh8YYMB{~hACXs`M3ARktF!vg^pqse&(RJ`TUh1-sZhTP{0!HB0jsT3 zKs)@>CT0$d_TGMPIdCm;`WnWEaeGw5u8}XkKF^!+c8~4*D28cAPS(|QF4^6UY5v}b z$i2m!7M1L6#y#Szd0{eb@520e_C%Q~GQ6yV!DTm3aWp_+0s?_(`ixPiP4C@u``~7b z>1yLEt$Caq^ffN=!om^PsvtN>2~%RBRE9a)m1ZPwPk|+aL6;2*tW(mI+`54u^gpOL z&kQ=O!*qBsqcRauwj9VdvWgC9s-oL{032W_K|$A5Dfhn1U##9~$d<%M7cqMIv`h7@ za#TJ;o~d*!9jrYI+;t4dm;vGAc*RPtRDtzemhSIfULTURGwz~qtTkC{ObM;Nunly9 z3?;k+Tu+w~Kv`If0Ly@G#Y9*^u^LX~O5A&}eL2(B{Uj*W@cFRHZBmu%65wDzX4`G? z^kAM`rdr+`qNMM)Xz7=_(j?s!`Z{VU3*}ClXs2|$WTf*uFJ|xT{#g6!hpx3fJQYRl zsW+n^W^uVZg~N6DX_d(Ypj#hYvyyDDi-o6s&t?Q1;9P)XkAqt zXi(Ci9GLGp6N0W9-U0e^&jrUcV091GdztP9WLRADN~23WpEIPQbgwo^l8mGSBeh|P zcFFtVieQ~5GBB(xzk(&cs85NMWBbluWNi)TT)&MqO3D@?(LHQqNPAzp9QIfj;V(9~ zYuRHZW~IPKGxd!7y;*u0yFTYAQk*31ITMsgu@>ud!I~44^>Be18mDKyX4nq*cDM5Y z(hIhhbd>~5Us+o5CHn45+UH}Q{MAPM1N{Rch{IC{;jh27~o=VZ1OB+qp}0Rf56=&pSYCPdL@7YtB13Ek`Aa8m7ysmR%pEG>ZejV7r7Y)Gk0$RvCgsF6$8@Y6 z)x*^$*iEBXn&(#9e6Pw;hQj*}y*eDghI5OV?=3D`&*)|h(dddFjM9fJX>UHN8TCLD zOh#Rr`RRZoWWJH2^1uu@O!d9==f9x|a7ob66?=6-1yLsShaGx$>zulQ zC66K2yvH?ImKWIh+a)0wPOMvJZf%|5$WG#XX6x!sVJ9<;z-t__jltEIyXs|Np`j%MI=-9Uh;%(ZDz5TbIi8t=_tOkC0P(F7nu??#;hr=1Ph;VE&`x@||Eg|W5H?@tvz*Vg*$Sq!6&A)P60k%PHA)gWXDg#XW|L^BLIm9J2;q>JpDi>|odnxTZ)i zlSnr1{X0TmuK~M{RCG{*=G-9X1}Un{dv!M!2CsQ*DKb-hl(@N5Vl&pAj&UE0Wbdx4 z`7BcF)^L>!zbau+-ppoT)lJhqPgZ|&+P?FzX6F8$qG49OWf$Wh^SG8KR^Jj6E2+9u zNg8B2z#$aG5$mvZGI*Awcsy|)q+(y4CI5x0++&#A5~1F>J-c%Z5UQEK94gH@7rjUD zkyyYkxd@RdN6LBm!rb*!!>5;dfZm zqRvEDpTBt$xeXQjRYiBmpNhxdx-ZLEh9tLtoS zct_oYl$gm2uOd_|SG7f`6Z*k&|7~Kf@9jF9feiS9RsL< z7H*w9@eU5krZljo&n0HJ!Z%9rS`iNi>^4{Z1iW!!LmJeT6*_WCY=#}RVHn%gI0mfq z9I^9|<@u!RFdnaL=V72KQ97CFl5co(IJCcBG`YesopmX^tQ++fB|QjNzL#fQ7Eo5^ zfySW66H;%)#yj>VUzr8FWIyLG+_AMcdP8Ryhl}C`7tYpKs3u`OHMU3X+q2HTo9HuW zMBgqj1X)0^HH@@dYqBe*tfEYWv^R14Z02+JHkfz?e#xb+UN!tZaH<~{qm7cGHajlP zO0cPR8gBF6Wn%`Z#XM!JVvBV;Xvtuj=}wQo2(4Ek>Mjhuv0aPt(!TZpMVh@JX5>dPtQd!|q-_^)o78i~)=pYTUrXgQ2S)N5BpOG3j!NXa4ifZ=VD z=WPF@R;xRmtt*+AgCe!3bvib$OVa?$vfr=}1Y$i)!FDQtl~A%~^x z2D5#{c<&rP{r*-#!#(LP2@D<@)m_I%q-*RgTULZZK*mwNRLY}=zloF|0}>=o8t9*O zf^%G2>AI=63418T1e@*YCv#>!zFy=mBGOw@wAon@FwX>JgSJh7X-0NOuNzk_Q6`LG zTDxKUX-Z;)w=!xBVXL+dPL+Z^ZkjGeUQr%C7%uu#t}AyBBT8%ol1Yp6Io84lCdI|5 z2Q_CzWoHsqIDF$Ri*QPqvSv(3NODh<`7S8?;s@Q4m6G#(x{0@Y4Z@n^SCwe|FjbjH zR@3pIFgqAsBSF5?oW%UwN27I7RANVxnlo}4n|M1x2r9<8oP(*jGBD(~A}Db9{)W3; zrfGp4|1|d3EZOp>+pn%N6?Mo$Ex;ZyvHUjjY%Nj|G89VhU{tdi(G*ZJ6^D>6!sCHM z_U0OisTdAYbbeF05pgYjrE#l62J%5gq)X^J98tNhJY{Rpqd|ni@~LF3CL$8x*VGMl z*Dggq{Lq@G=47k*u!q277aM;ah|w=BPE}H!&Nc(G?#PxFPoXE}@B7?aIGeWE_n>d8 z$LGEFqi*GeW57}%IeuM#g=&UcPdMQV%i=dpiwpeqv9L&nn=5GH%9(;?=L7zk7`wsFU z#5di|O&CIuf-Zv6`+}{n+MJ{_Jv3+Zu) z+$Pw$>J(js7PLHHG~_V0ClJEMMP+mm55y5(V{oI8NJT}G2Wi=3L^gsBw87t!&;RPJ zrK71+u`pkDqI#G$%8dr9cIKveSfWyi1t`i0@8Z}|hM_2+h`Vz%p1F6JYGWT!<(;3H zESo?ldwNSV!M-qKD(Hcr5e8>F7$qOPn{9LMFriGgy&&bYYJD@EiU}lz;)hCrT)!@w()n#ErEhmcvpx$F(_-h0 z;5ij#>pbRuRCy;5xZ-T>l*SHZO8=6tIYJVzBp|Q8?Cwdh-21bG8u(9khl%A2>E$F^#nr{>Ri(5|PoX8$kz8q)NCql^nO;D$ zDdo*53Il>+UK_p}ha1Ocu z*GKjzEiim#K*gt9O7+5?*TNj;ecX-t8Alp+c5Mbj)`%kPLJ#T7k*QVz{3Osietch*fHQ}1G?A2G_-AM4f3aXk18PX zb@L=ny_iw z7>T63F5T80a;AOa+>DwEO&mKsK{F&Izr=svb1KAU$yfPK zvZ}94ublzWF0Mm;Puh1Ltyh=za%IxZ8N=m6^puUMSF2eNj8h4oC~i&~Q67>lcp9O( zV(MgW2RE8!<)Rr*6@_R9hzi0Klc}3h<7yzElDeC{w=-Mx z`!7>Njsk2h7Nsv^WE!x%`gHiXEz4YlSb9(~do;H;9b?E$9>+{bb>qfk2H#inxTLXH zx^?#=4JG!oAtj&sGbRRT{9_slxNd*0{t2~Z*I=8(h>doJ73zeA*)&T;&Sk0Y3-(>s# z+92#gQbNv6rP3kIBzDx~A_dLLuDmzl9xH7FG4VSpE_mgjGhX_>feaOur#nm1NiKzS zX>?uaggW=N7IbF##HLM2Ww;S!iDE6Pnb#Jju*Ku4?v`Zu%>q`|ZE^b@jmWN{5eno~ zd^yL&Jp6qgL7&5KySZ%4HZ#Mwld2s#`sHNoE%(0i@~pgFQJ-#a=g>SFv1m#HT7_{I zZAhDI4Cf?amO_W7DA#ONK9DR69$I>0lKVt+zSt+Y`)6|+-N%{dTA14-O$|O&(s95` z20RA5xk3i|w?pRR3f&~~JnM(5a`bZxh8-dFJk^ZCAe})^$BQv9%Zu_>VkNWbkse}l zJWt?WGBCZheWuH)(m3<@3o~8!U#TW0h$%H6R=K8}KvP5cOTpJaf(H=xRE9QYMLn6g z#0ZI~eC23hZU|0Ot*(}QP@W_D(Du%y?hiImjdmQg10_MHa|H+fAui zy-s|R>C9?~HXqB)q^f?~v2uM(blory+O&Z-3EUiB7;`f6XieE(xGY<5@1;7v=>cT0 z)3-5IEDjl0L@i$hDK&f^_>wbCl9}!Mr90VFV~#~3T#xVDA$wTZH~UR;C?28_A^^S1o zo9v3jUS|7pMW^C0^%(;t^vkn$)OP45iE`r1GPz;5gs1_v<6sBTcIHK=d zs&p}h0n);F#dpewv&}8qIZuu_+;{ifr#}tqf875V692cMG&`N9%eqs8i3Bg2#wNO} z>buDGtYm5uB6XCtIh&DrPxz7rK`tVk2$DOGaoa>3aMmSeS0%EUipX`T?xxhS4exjx zm7})+tF5i=1&80BQ2ZxBKi2+tR<9A~sz)T=MA`o!lWP9V?08`LBeNs*Kg#p3j{G|_ zfhU(l%AfozCIAK&b(u3oJ_0BCzU+oSNY2$iQ-8G+ex&}+{%cPEc$Q8EB;-X;{9gLCqr2JF~Dm=2lVkL?Rfdmtk@ervSP3NCvl2@$MG+Pe+R1s z-052WOO<~@{-1Zjqr(TL;<@fO{6-4XDfc?t7ld{z;W;fcTPeR@W?aq?Na~e(RpqGP z3HbL;#X71nzc$@8?;IRn97_v|PDI_l7DMoqOFnBZ9}{eH}iTH}Z~I##}~h;8U_9 zsoE#LFt2!f;M(d!X_B3?R2Pw_*bG!t*H9hf@Tha^`x7#^74Hyi6Mv`L8n>ln^Kw*_ zGhih!yb`W$v@#WD6_I)<;CRU5R!v$ctHoARfK zj9Os5t@@Ro_#5!u%{eS%>-x&gPNtGH`$+ymupBR^lC*t!MS#3iT2LI$mpBZ+mECB! zTd6K?{Z3D+By|GQJ~09W7rA?Ahb%nqeRM-?0p z`x#$iP%g@(p$H~mLXmDExufO-!)41p?rM6gBS;_H)l{f=P+S~Ixqs~Cief6R)uGMy z#vrDgD=EP;p?Ci)SY!Rr2HoQq8-FRHs7nmt3#~_YX@ixMJll}o9;khf-{@AB*1O9O z;aijjE`#TW@_d4w4G1S;R65EzQBe3vhTmu?l%^>^Ys<2P@;Nmo{NV!c+T>#4bj0d5 zyTiC~r^g9ynH`d#aLH}8;P%`8iIeGYJ*u%svsO_U|H17_x2$_lY|Hv)IjnI;kjc)% zcR+boR7{D7%3~(wofR3W7H5yOjd1NB2zo|agW;-|g ztckiOYnG=%9zT*7xsnExF2lF)p{rR{x^89^b9I3!2*Uuvkg(*lJP;b_o#l@N@kP&uavjT{xwZw%(IaKYeWd=k)<3o|5@PL;u zwWw|$HIS_gbE3IAsU-Xjc};Bh$0WtyQU|gHD{nOlb0FcNUs;#(@6AA_OCpyA$gsJq zD5(K-!HmAELm#*K10I~eKRE*?DmJm~OYW#Qk&vT^n8(X%nAI(9#;HN2?3qN_t?RQ> zJWjG6pYBfYtBY(Cv-Ws0t|PM|)QnN8&3ZbZ3Fw3FlEl1NSVFYOc3cfeLq)V}xH&{O zMLyU+-l5y$sF%@lBX%;;8T2^AU_T7n*Er~LFq?kA7NWS8Cw#_Fz1_Z)eCEeB2VZZGySzhJvS8zhjuD{8%ITTdoLt>Z=H;fi*MK3^!PuA1>4a z?BXzP9*Nhl%?AAFD7VZyJ)f=v7P6HgLB><#JJ+%ydVFM2}l<11ZaLqaD*o1kV)7 zqy8`b(+TW}Zc($J#gk(>(N_r>&g4Fj^|Dfe2n zkl60q$AH>Po=ZNab1Z+bdrfhe#Cw3N)=7JMXvtMioPQHIaaMX;R$%k$AKa7yM{RKd zx}#{VPe+9`lZee``9B(Z?hjtF5tJ?*75-^pmSg16I@adv6Z@`?cad z=pRvrNjnYZJQ8sfVtO-Id-dhUK&G1uYLPf)Jh)Qk2gYD!~o&nH_jB-+?;Mc>G9)2XlEhsRie{O+@O&Qa30ijPT3g zrIc!D%hJ*RYVW?In#%S^fn%Q$(LqGIjG`cYP>OUNL8OKNA+&%JYG~4H#4;!W2?h+k z450)P5(H_XDpf#0NCJe=d*~p&{_>l9)p_f8?|b*%wcdKaH|za%);asEb=KKyuf0#Q zzu(W-$z)2cpFeKuPQt+ZfmGXDwjr{e7Y@ji2urgw_P6#_6&NGENR{*d!~vmwb3j7> z1qbA46oZY-0SLNPugkenvZ>st5#H1<={$(D7#>3{0Fo$Qo(3Mx>_(!K9ugF$`wI0i zY2zWt^!yf&d#Xi+DP`R2;e+xN4SIM=$ek0IG^A3(s>r8m(?I^JQI~*#^5pSh)FWE~p|xEj z8UE*2>Wa8;?C@O$#1KkfRA{qXbf_JNF}L@P3t8UXxnmaO<$PlLcxJ2E4L=%V)-Em` zXZ15Gwpqm~Vk?aTTP7(O42w2=uI)dStweP##V`Fdu0W6Sc_Z7Svx%QVwFi~pkS+ni z6Z%~W^MG0^{}YbybIK`Ddi_o z4xog_jjnio?<^MqaY88%?%`4rQbU`sB{=XY<_LJk=6(t^>ssj~Bnmh*Gg|iPbt|1( zs-qx|W)G%>cId|!qp7faGMcHt(b%CpXe*47YJMUQvO8TzrFGIjM%4Ur^>?IQMO5S{ z)yF5ka{WXpvB>lT002}r(zc$Y5nO`7zBZQ!^Yfn#>q_dIbdkvo)R36g2^TZU0thq_ zern^mBP%7}2AD~R<*Du-%FK){@4P02{si3^c9$%*w$|_9^?62qX&?D22kNrrDLlIm zbf5(nIG(yVpknQ|d9?1hDFYXPj#Vic_1&D+vC3f_!#NSW6pfg{_wz&#$#{Fsl~gON zSn)&db@;}<4I8oRE^oWBx#2=02S*d`B$QF>PJ(y~2x5!d2gD%|YeFd3*_MIK;Y8~( zUUhuj+~5KBa#i*eG6TPC1?=^g%k=L7(Gyh}HpyK*K&Qp5K8wV&QuN>Q-9SPcTG<+I z_frOUfgq#`NZ`tJ&NJ=QXz*3f66?H1L0jSJdp$~%$?A76G$qY7)-!q$oz>4U>z&z2 zIU@SEw)jua^YXUEbUD0PhTwkBaY28PzSK&zZd_0+PLRZqy)qoc?*iP2x#rw7TTR#! zbL*}^_T~_TOpLxoIW4AguhCrdaelCKS;g|YLx}>&i&V8a5kP?7BA@QGjg&7k0rij% zRud&=Qd`=+yvM+PVy=O+4Il_}dq7wS;!8F-s~S*sPE%eqr}MK$N0Rg8vgeishf>$R zRV6)tp;=ngk@P{Gv#v;IQ5F~dSYLx)J>j{`C%M{;CsDX&(@Mb0lIJsbv4T=>mv~f* z)>8cLz_Lh2<5Y$|h*y_av1_TW`Zw^&8Y=8$CQM$Z&8qm~td5Sj<>1XOkfXVP)JMeF zsF7+ZPgomWIl4r)2@Nz^d9>Df>fG_bOI7hl+&iEzNt_0SGW_tG3ry%DC_Dj@>2b(% zSrzvuP%5$at3BEB-MzT>clUzDF;$y_Kj7=uy%bi)!@;g|GP?;8I*Mr%(`W&AdB<)a z$#|MpqHg3d*M07E^L!c4^?4ItPc45}msX5+*$5(pxf$BFhtSu$4|5VuBgyn{%Ul;X zeP$KLKQuvOA2{oOs>4)>BwqF2@=4Z$1r?5^N=ywtewTex+&1F{LHxXfA{3U{ivTKC zMu*7*E)IETXcrXW8FbGEDbs@Aob7NW{()xI{!b%CPDv-M!`#Dvw|qi$OQN|~wMS~* z@yNwnP8L~WvfMR&W%Xe0NC58&?&gxBS=oJ<@`hR43AZ>GO?ypQs!3D~PSi#S>cNq; zQ3!(ieZ;?eQu;y1cr7-@Qvb!AFpoEq4$rkv4k08)`=I%CdJ5YCNk~&-hqcCwmlnz; zC-u-~3vP0=?`M*YU6A+gPhSnk^CcbVk6LpMhFD&|Xeiz;-J_$bO&XHa{k61>KqzdH zQ!;5bY_v;WCS7WzJ!XET!!B}v{UP;BIpWyetQ)H|9H)-bW( zad|lrNN^h)2Z&r9-UzzirHC(`r#C%Th7kb|$S&<=BHfjoyR4P(*O5j0DSG`c2Q6^; zfr_l;kDDH)gK1aQozArzyyni4!w2?wY9iNMTUJ9lh(sMnyOI)CeSo&I^3WUy)!!u` zHqvj^@G|^|9fJoIH!b~YU`XW{;H-nWmz#9`dGl-cObRnes+pc)m?81$Jm1;l`9VR08xAK)m~V&Mo;=o`{!l_Z>Z z@zYfDmHSc0_-&SwG9EVh-l)F@ufZ+v=C_ws#Bye%M4~PYrk=QW$U?H6uT-#~+)Q55 z`9;$F-I_Oki$kcTpjl>$8 z-vfHISafBn{Zto@6$DwvYerBvyPzc9!jYD*%HfX{eGuU#ar4}Y8=8i8c65da* zK%tziWlq3*&k^v*Bo}nk86sH{uHj22*(C}EDaw1umv9^y;bt5^d#iseWR-&IUShY; z&8X7ZqQ4%0r#8}j*RWEt04&@xwAf)4`#{1Sz4P>yWra4~XZHwPztZGJP=&bfrfe`j zLvp!MC^HKAGK`as52g-s#J@R*OxOWMnnPYpQhE|`+VvG?=pI z@>9m!<}>9~b&Ih^R3b&B< z4DOHUZQ3Vc6p1FojUP{M)aR4OeH4Y+eBWo1Ly-JlxFr{CW}Kq)tSwUE3f`(gKdn(? z@B-dtxl+RB-95g3dfs5*vlh;kva=JZgW~5+TLuGm1DH8E<5Cj-IyWIYR7Z!3*gGC? zKiqN1EwWs=*iU@dL_1^|*B9C_plE1#gcmT1Z<=Lw=N9V_kE z5PU>`ET?gAsph?@s<2xbYY%B85ls>l){cBoOuMFja?j|h_mW|!`UUsU+~OT;hYLHs z*jsTN4(Sz!lO`N?Tp}7v$?n)NI}@9mS)(2YoDw_LoFv_D)Al!|X=!@D#-5A$a7E2z zF=8DJ;`=b}aq1PZ*cgKZVpm|%^-ReNV(gy#c1+*gfAQj`%xn`WGz_#fJ*9ChQZr}! zWVX+#?$$Fp5xjKtaTBnxk*=6VjMjPWN?!apr0XY)^d`im*c^{@S>yZJ?Tn0~L$F9x z+lMk$6qoOT)(n@H1TP~ei08Ml-cn70ezF@fF8gguQ$w)-uw%gI!uN+P>Rf#LZd#`0 z4|g^Q#H>5mby(Yr7by#c`buyZH?p$JLpD94 zOb%IY`%qp3WjtU8ZQXjE0J6i38hhsxO>tjZ&+D zO-`RHHGx*Jy>4?@yx;1mW-0?hv?wY9;Z9D2g5;3;AG@pSmJ(>Rhxs4f-=JU9D~q(R zO1g%ej&W-ds12vJGpF+&j1W*>1HgXds~`L=oa5hiFHLwlUYkx;Jbz3~MTMNRiK?LS zr@(h%%I}yC?yAVy-MFn|Dq}l>Xd{b9{dh_-mBjBqQ86sWCw0U4hV)v)N{hWO#b#|T1%{caCWR0?{ zMi0%#rD4FB&3h8TZuN7=nq!^W#?})Y-poe`Mv~;>cscVI>ALz7*Vka;>Ig1`BKGxG z*%&GAZg8WRx0143T33V|xgsd&O+2v`CE>JCx=)t}d12xouEz-j_%cyZF$%&RP_mE7 zs@Rd_VjF|W3i|q$8mbT25Uj2G?h;9nTdM~02%MEpG7QxVWTkg^iH5y zF6`$Qj>fuI-J!ycuCTl!MHNPWs5e7Z!{lv^bC#Wq%&kz*gJo$;{N+4S?eyshJWAl@ycnI9L7CiFFy zc0#npV=|CY>>nxCGYcDo1HB0xD$4h64$N_v4ii)_d+8*@LnPBgO1Z%?SliVFgT~#c zAF*cby+1XIy7{L(!(T7gAc6T-sBpxt#N5)KgT(5CAxH-mYvIAdn1NY1% zwMQ|n5^s&D>B=i8+(XjP{mzSi5i?S<93_JMYfD-sA8UM$vUcnKQt?3Pa@@p4^X??Z z9gXeZ(Uy&M6Y~&+K?(%t(I5QEiWy=dE-v|o%AxL7p0<@VEln^fP-5*_?s&J< zyoPf;4BfvNIq=JA4-DXC5dDxPkdH}G{I>6f^<^=U5Ky@oRIj^T|6NjPq3V2Tk37!s)2P4`U=aN!dFVb?JJNsGnz(BKW8sw%_mJPNnh5Aw~?N988&MN0ix?JZ@EyCptRNeb? zMEqZwB0qKR$|piV1FQu7Xu3;5uq(abk+SJ!>O?eipY{lBFt=eGx8$65 zJ-QKGr&1uXlMSzFE$kymjjpJ+g9{E`)&XZ#Lm$Vk!w*@)tb5|JCHXJ>l4Y`TgPUBK z@BT5=cm-?knNU#6M9X3L4;qaX(02B7i{85O<-ha=*{bhr!Nt%ID8U|&i+l-HR{DYa zqH+#%j)|9REm9ih&AF+tok~`-FTIv|L_-NV!y5s;@vL;xDj}|URPDe#(JCSnGtt=U z*qP6s*jM=hQBRf`#V)qhKWKF$NeFbm$S6|Y%Ct7{7knL8HQ7VW_sxW|mL>*v?xE^qx(=?U9A;LTjN8caj1 z0`}Ea42}-;r_VV5BG zOI*+`SXvS;O)*`is&4=iKqvdvcB`;=9nl$8DtHZasnNs+KF_O#pSO~kEw^3N1_Jh& z(OMoJg{--q@SBCCJfBt7yYCG8`P11#>n@;`L#F(+`KogB##S)`ysG}L{;795PXQ0JN)i}orK^1EXLbL#s@8^Ie#RzuKIB5HF?Kgu>vAv4EC(Y4m{kj03i9_GvMe_Amw2d1QGmhUBvx<3^f zOYc|)J)9jO-g3e-bG0L&o2yFP{17woF0WhVIVv*bvwkA4n`6xwbBRT&E%idiTh^($ zey7uQ#jd`cRIofwv=*S6MNWD|Zx@%IQ~Tr)f77)nvUf|0OyFEH{-BnoPTg@ZgFPxw z%FSHvJQIiwXE|Rc@y8(j>n??yQt2XfO6VYbsDfs5Q9*W{rKWyP8>Qs*uEC-~=%toJ zmT0eves}&}(TLh}-JRI#-5Sbs$&tFToLjqnYc6%Aw@*Yw|E3FC+YkVe+onW-=GSWY z2+Dbb#vJU6QCv;oRd1$ei5_okO(>7X5`NnTH4&`Bt7&h^1ShW<(VW5$8+fhnw5M2^Xy;Z5^avSx9uXGRDh*_4jF3$>QDeLhP++ zk{biFJgZn^Um+u3!5htQPnpfH-6}3L27m&iR%>z`-$jQJJlfp{%B~Fx%2_k=HpD3k zJ3mNnpNJUQb#rmHX=WW5a@vqa88?m{rLr6`8YGXjJ7R(reUWS%hb+l{hb)C|obtD; zgU#Itj&d(a9(!o;ew!U}L-#p*Vx#&?#w@ur3&w@YRghxTR$!sD||QeF~M)VbA<2*CRje>7Q)iw z?$=M)e$9XX$BP}s)D|?dfpQA`gY`{wiT;uH6H6PC-GX`LMH7CUA#6iM$(yK!{=D&D zIZFCi`>JZBN1>LbVv%pQ9nx;?L%}YhwVL@_f&R;24!wigjRZL$vwlm3w5;Ks;#wKE z#XdS*cgy`kULC>Tr9U;oK>H*pv9EpEZ>2o2Cn>W_RYuJ$?UXv_i-I4Sa@J?N1hED#RXpMpe$0CT>Q-)#vmj=;g*`A8*W{^d2tqc^y6_q2zWLU2b*w{ z$3RLutwZvy`_$lll5)B;wRK0HLUrKMi#*do>=S?t0(-AJJwyh;tPw@(VTUYo^nlNa z3}ICNT0}EQOA`q6Bob3$_(fmjSQ62G!Mm2Ga@zoqMV3$F`nWy{Ww*lBTveO&#?kyA zW$OyCme0XTUBf$iN2J>d zM0@KdZgk_`>ve~O2$?^WeLYQ?sV6LY{C^wVf8hn2>RgLn%_(Ln$s?={`})z0#?t$2nu5 ztFM?*Q+H%!m}WF=Bqwi~tiFP$^}X(I>TB$OrKS#nMwE|7U)_3mLsLt5rV@)j0+gqv zjt(wdjr7d+fEsTi$_D#GHK-xaBCGL*o~p`$ina6DK6;3h;Nnz3aH$xh2a&KZoa(#A zEIdT2e?ijsoJc^d>Cn{prwW6VEnEN0#ZQbbUZ_RuC#j(*6A%J_ej9xuBlu0PzGBIaLx98Z zDT0n~3H!}3ObF-WZZr#0YYm@8m^Crkz_CLX+ZQ)N zeZ?3Bsu2#YM`misek&E%e)+3XN&NCnsT}$G$baql z!?%@F{rgDxrn%aOFd5RDg{s}3XbB50GcJPlnudArdJB=O`wc&EH;cB*@W{&#DYK~u zrE4_n0b(9L8hhKb5(j(d9bwTJBX26yH{orS{Gaq#NMfe|MYlt~A%dqn$mft{q<#1b zeCSv3rAm+xP|z9Cv6|JIKJPq#%I8xoJ4~!m-xSY4)i;+DG#QDvra7_n#- zE!gOZJF82;4VBPgn{GA8tXgyQ?%a++e7|t}fh}C;0GvE~03F*eT(KO<{no72R;|^? z40VNv-rv=r)qVox*|frKK84tns)>hip8DRp?Vr1QNqwn+A?TE>u#H$3-v;2fqa!z( z8$F)={=HFZT@c#5zrHWDz~OMnBBPcaD!Lvjv+}rai?D1W_^owvD04pGkfo+J3yyIe zo)V!HOsW-3sY%lXIcrWo|K1u>Nr6WTZuYK47waeQHSD1Gu++Wg#$D)G*$2b#jqyRz zh2sZ12dE9iyU>JmquMt+wFz6bt|6vdV&}d!e(#(vd52nv;(uOldT|X+CL<{3ZFaj zJamiQpK$QlI5uHZzvXRD&LjAG|BjG$j=DKch<1Mc;f4o~S9xT=@g;b$0GrOISn*1^ zH;dL8`jt>-6@d`<%OgC`Z+w!TDz8i!(3^vJ=O1)kx{v(9JRn51N)qQvNB;0ns*1TS ze9fPb{+2)SPpXO?+w%QbQ?&EaDsoObcbetE*C%Mg#vFc^sJR|b@qQxr-}zL7)ly6- z{v?V3>CM*~`;sT|k6<|L{vR?NGg;>I|8%lB`KCJ}cbvR?*Q!!X9>BGqiSYQNPo90Z ui@$@X->he?Kl(}OKf6rp*7;MwEqB^z|uGX literal 0 HcmV?d00001 diff --git a/assets/configuration/layout_tokyo.jpg b/assets/configuration/layout_tokyo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a0c06bb25ab2f59669e5536d89994f390b6661f0 GIT binary patch literal 27640 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 IX6Mbn0Y>-~{Qv*} literal 0 HcmV?d00001 diff --git a/components/Settings/LayoutSettings.js b/components/Settings/LayoutSettings.js index 4020857..07e1780 100644 --- a/components/Settings/LayoutSettings.js +++ b/components/Settings/LayoutSettings.js @@ -18,6 +18,8 @@ export const LayoutSettings = ({ setUsePDFView, trainMenu, setTrainMenu, + uiSetting, + setUiSetting, trainPosition, setTrainPosition, headerSize, @@ -38,6 +40,17 @@ export const LayoutSettings = ({ falseText={"本家\n(文字アイコン)"} trueText={"オリジナル\n(車種アイコン)"} /> + { AS.getItem("iconSwitch").then(setIconSetting); AS.getItem("mapSwitch").then(setMapSwitch); @@ -48,6 +49,7 @@ export default function Setting(props) { AS.getItem("trainPositionSwitch").then(setTrainPosition); AS.getItem("headerSize").then(setHeaderSize); AS.getItem("startPage").then(setStartPage); + AS.getItem("uiSetting").then(setUiSetting); }, []); const testNFC = async () => { //const result = await ExpoFelicaReader.scan(); @@ -63,6 +65,7 @@ export default function Setting(props) { AS.setItem("trainPositionSwitch", trainPosition.toString()), AS.setItem("headerSize", headerSize), AS.setItem("startPage", startPage.toString()), + AS.setItem("uiSetting", uiSetting), ]).then(() => Updates.reloadAsync()); }; return ( @@ -114,6 +117,8 @@ export default function Setting(props) { setTrainMenu={setTrainMenu} trainPosition={trainPosition} setTrainPosition={setTrainPosition} + uiSetting={uiSetting} + setUiSetting={setUiSetting} testNFC={testNFC} updateAndReload={updateAndReload} headerSize={headerSize} diff --git a/components/atom/SwitchArea.js b/components/atom/SwitchArea.js index 245a708..74e39d0 100644 --- a/components/atom/SwitchArea.js +++ b/components/atom/SwitchArea.js @@ -8,6 +8,8 @@ export const SwitchArea = ({ trueImage, falseText, trueText, + falseValue = false, + trueValue = true, children, }) => { return ( @@ -37,7 +39,7 @@ export const SwitchArea = ({ bool={bool} setBool={setBool} color="red" - value={false} + value={falseValue} image={falseImage} subText={falseText} /> @@ -45,7 +47,7 @@ export const SwitchArea = ({ bool={bool} setBool={setBool} color="red" - value={true} + value={trueValue} image={trueImage} subText={trueText} /> diff --git a/stateBox/useTrainMenu.js b/stateBox/useTrainMenu.js index fca06d7..c4d8467 100644 --- a/stateBox/useTrainMenu.js +++ b/stateBox/useTrainMenu.js @@ -16,6 +16,8 @@ const initialState = { setMapSwitch: () => {}, stationMenu: undefined, setStationMenu: () => {}, + uiSetting: undefined, + setUiSetting: () => {}, LoadError: false, setLoadError: () => {}, trainInfo: { @@ -58,12 +60,16 @@ export const TrainMenuProvider = ({ children }) => { //駅情報画面用 const [trainMenu, setTrainMenu] = useState("true"); + //GUIデザインベース + const [uiSetting, setUiSetting] = useState("tokyo"); + //地図表示テキスト const injectJavascript = injectJavascriptData( mapSwitch, iconSetting, stationMenu, - trainMenu + trainMenu, + uiSetting ); useEffect(() => { @@ -75,6 +81,8 @@ export const TrainMenuProvider = ({ children }) => { ASCore({ k: "stationSwitch", s: setStationMenu, d: "true", u: true }); //列車メニュースイッチ ASCore({ k: "trainSwitch", s: setTrainMenu, d: "true", u: true }); + //GUIデザインベーススイッチ + ASCore({ k: "uiSetting", s: setUiSetting, d: "tokyo", u: true }); }, []); return ( @@ -90,6 +98,8 @@ export const TrainMenuProvider = ({ children }) => { setMapSwitch, stationMenu, setStationMenu, + uiSetting, + setUiSetting, LoadError, setLoadError, trainInfo, From 8e7ccba5cc6b9c3dfe27c15d29f7331ca55e8ca4 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Thu, 12 Jun 2025 08:54:39 +0000 Subject: [PATCH 50/77] =?UTF-8?q?=E3=83=87=E3=82=B6=E3=82=A4=E3=83=B3?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/webViewInjectjavascript.ts | 53 +++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/lib/webViewInjectjavascript.ts b/lib/webViewInjectjavascript.ts index 3645b7f..897b297 100644 --- a/lib/webViewInjectjavascript.ts +++ b/lib/webViewInjectjavascript.ts @@ -54,7 +54,7 @@ export const injectJavascriptData: InjectJavascriptData = ( const trainIcon = ` const setStationIcon = (setIconElem,img,hasProblem) =>{ const position = setIconElem.getAttribute("style").includes("left"); - setIconElem.insertAdjacentHTML('beforebegin', ""); + setIconElem.insertAdjacentHTML('beforebegin', ""); setIconElem.remove(); } @@ -1041,6 +1041,15 @@ export const injectJavascriptData: InjectJavascriptData = ( else if(列番データ.indexOf("R") != -1){ trainName = "回送"; } + else if(列番データ.indexOf("E") != -1){ + trainName = "回送"; + } + else if(列番データ.indexOf("A") != -1){ + trainName = "回送"; + } + else if(列番データ.indexOf("B") != -1){ + trainName = "回送"; + } else if(列番データ.indexOf("S") != -1){ trainName = "臨時列車"; } @@ -1251,8 +1260,10 @@ export const injectJavascriptData: InjectJavascriptData = ( 行き先情報.innerText = ""; ${uiSetting === "tokyo" ? ` 行き先情報.insertAdjacentHTML('beforebegin', "

" + (ToData ? ToData + "行 " : ToData) + "

"); - 行き先情報.insertAdjacentHTML('beforebegin', "

" + returnText1 + "

"); - 行き先情報.insertAdjacentHTML('beforebegin', "

" + TrainNumber + (JRF ? "":"レ") + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + (isWanman ? "ワンマン " : "") + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + trainName + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + viaData + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + TrainNumber + (JRF ? "":"レ") + "

"); 行き先情報.insertAdjacentHTML('beforebegin', "

" + (hasProblem ? "‼️停止中‼️" : "") + "

"); `: ` 行き先情報.insertAdjacentHTML('beforebegin', "

" + returnText1 + "

"); @@ -1266,13 +1277,35 @@ export const injectJavascriptData: InjectJavascriptData = ( ` -const setNewTrainItem = (element)=>{ - element.style.borderColor = 'white'; +const setNewTrainItem = (element,hasProblem)=>{ + 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 { + element.style.borderColor = 'white'; + } element.style.borderWidth = '2px'; element.style.borderStyle = 'solid'; element.style.borderRadius = '10%'; - element.style.backgroundColor = 'rgba(255, 255, 255, 0.8)'; - element.style.boxShadow = '0 0 4px rgba(0, 0, 0, 0.2)'; + var 列番データ = element.getAttribute('offclick').split('"')[1]; + switch(true){ + case 列番データ.indexOf("H") != -1: + case 列番データ.indexOf("R") != -1: + case 列番データ.indexOf("E") != -1: + case 列番データ.indexOf("A") != -1: + case 列番データ.indexOf("B") != -1: + 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 6px rgba(255, 0, 0, 0.77)'; + }else{ + element.style.boxShadow = '0 0 4px rgba(0, 0, 0, 0.2)'; + } element.style.margin = '2px'; element.style.display = 'flex'; element.style.alignItems = 'center'; @@ -1287,12 +1320,12 @@ const setNewTrainItem = (element)=>{ element.addEventListener('touchend', () => element.style.transform = 'scale(1)'); if(element.getAttribute("style").includes("left")){ // borderを使って五角形を生成 下り - element.style.borderRadius = '20% 20% 80% 80%'; + element.style.borderRadius = '10% 10% 40% 40%'; element.style.flexDirection = 'column-reverse'; } else if(element.getAttribute("style").includes("right")){ // borderを使って五角形を生成 上り - element.style.borderRadius = '80% 80% 20% 20%'; + element.style.borderRadius = '40% 40% 10% 10%'; element.style.flexDirection = 'column'; } @@ -1387,7 +1420,7 @@ const setStrings = () =>{ } ` : ""} nameReplace(列車名データ,列番データ,行き先情報,hasProblem); - ${uiSetting === "tokyo" ? `setNewTrainItem(element);`: ``} + ${uiSetting === "tokyo" ? `setNewTrainItem(element,hasProblem);`: ``} } try{ for(let d of document.getElementById('disp').childNodes){ From c92f02fa0e35f1e2200e171fb191fb9e91346cfd Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 15 Jun 2025 05:20:11 +0000 Subject: [PATCH 51/77] =?UTF-8?q?=E6=8A=95=E7=A8=BF=E6=A9=9F=E8=83=BD?= =?UTF-8?q?=E3=81=B8=E3=81=AE=E3=82=A6=E3=82=A3=E3=83=B3=E3=83=89=E3=82=A6?= =?UTF-8?q?=E3=82=92=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- GeneralWebView.tsx | 30 +++++++++++++++++++ MenuPage.js | 2 ++ Top.js | 2 ++ .../EachTrainInfoCore/HeaderText.tsx | 13 ++++++-- 4 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 GeneralWebView.tsx diff --git a/GeneralWebView.tsx b/GeneralWebView.tsx new file mode 100644 index 0000000..dbc47ea --- /dev/null +++ b/GeneralWebView.tsx @@ -0,0 +1,30 @@ +import React, { CSSProperties } from "react"; +import { View, ViewProps } from "react-native"; +import { WebView } from "react-native-webview"; +import { BigButton } from "./components/atom/BigButton"; +import { useNavigation } from "@react-navigation/native"; +export default ({ route }) => { + if (!route.params) { + return null; + } + const { uri, useExitButton = true } = route.params; + const { goBack } = useNavigation(); + return ( + + { + const { data } = event.nativeEvent; + const {type} = JSON.parse(data); + if (type === "windowClose") return goBack(); + }} + /> + {useExitButton && } + + ); +}; +const styles: ViewProps["style"] = { + height: "100%", + backgroundColor: "#0099CC", +}; diff --git a/MenuPage.js b/MenuPage.js index de4f199..6f00ec3 100644 --- a/MenuPage.js +++ b/MenuPage.js @@ -18,6 +18,7 @@ import AllTrainDiagramView from "./components/AllTrainDiagramView"; import { useNavigation } from "@react-navigation/native"; import { news } from "./config/newsUpdate"; import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs"; +import GeneralWebView from "./GeneralWebView"; const Stack = createStackNavigator(); export function MenuPage() { @@ -128,6 +129,7 @@ export function MenuPage() { component={AllTrainDiagramView} /> + ); } diff --git a/Top.js b/Top.js index 4e547b8..5f25b74 100644 --- a/Top.js +++ b/Top.js @@ -13,6 +13,7 @@ import { useTrainMenu } from "./stateBox/useTrainMenu"; import { AS } from "./storageControl"; import { news } from "./config/newsUpdate"; import { Linking, Platform } from "react-native"; +import GeneralWebView from "./GeneralWebView"; const Stack = createStackNavigator(); export const Top = () => { const { webview } = useCurrentTrain(); @@ -64,6 +65,7 @@ export const Top = () => { component={TrainBase} /> + = ({ return ( scrollHandlers.ref.current?.scrollTo({ y: 0, animated: true })}> - { + navigate("generalWebView", { + uri: "https://jr-shikoku-data-post-system.pages.dev?trainNum=" + trainNum, + useExitButton: false + }); + SheetManager.hide("EachTrainInfo"); + }} > = ({ {isOneMan && } {trainName} - + From 61aca4c75e2bd2a4f6c1fe3968b575c1126206cc Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 15 Jun 2025 05:20:47 +0000 Subject: [PATCH 52/77] =?UTF-8?q?inject=E3=81=AE=E3=83=87=E3=82=B6?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/webViewInjectjavascript.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/webViewInjectjavascript.ts b/lib/webViewInjectjavascript.ts index 897b297..0b7beda 100644 --- a/lib/webViewInjectjavascript.ts +++ b/lib/webViewInjectjavascript.ts @@ -1302,7 +1302,7 @@ const setNewTrainItem = (element,hasProblem)=>{ break; } if(hasProblem){ - element.style.boxShadow = '0 0 6px rgba(255, 0, 0, 0.77)'; + element.style.boxShadow = '0 0 10px rgba(255, 0, 0, 0.9)'; }else{ element.style.boxShadow = '0 0 4px rgba(0, 0, 0, 0.2)'; } From c526055ddadcbf51c4f9692d0b4d39a4c0c3cd72 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 15 Jun 2025 09:09:05 +0000 Subject: [PATCH 53/77] =?UTF-8?q?=E8=B2=A8=E7=89=A9=E3=81=AE=E8=A1=A8?= =?UTF-8?q?=E7=A4=BA=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/webViewInjectjavascript.ts | 80 ++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/lib/webViewInjectjavascript.ts b/lib/webViewInjectjavascript.ts index 0b7beda..fe5c3d5 100644 --- a/lib/webViewInjectjavascript.ts +++ b/lib/webViewInjectjavascript.ts @@ -1000,6 +1000,39 @@ export const injectJavascriptData: InjectJavascriptData = ( `; 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) =>{ let isWanman = false; let trainName = ""; @@ -1055,37 +1088,6 @@ export const injectJavascriptData: InjectJavascriptData = ( } - 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 "臨時貨物"; - } - } let JRF = true; const JRFTemp = getJRF(列番データ); @@ -1259,11 +1261,11 @@ export const injectJavascriptData: InjectJavascriptData = ( const returnText2 = (ToData ? ToData+"行 " : ToData)+ TrainNumber; 行き先情報.innerText = ""; ${uiSetting === "tokyo" ? ` - 行き先情報.insertAdjacentHTML('beforebegin', "

" + (ToData ? ToData + "行 " : ToData) + "

"); - 行き先情報.insertAdjacentHTML('beforebegin', "

" + (isWanman ? "ワンマン " : "") + "

"); - 行き先情報.insertAdjacentHTML('beforebegin', "

" + trainName + "

"); - 行き先情報.insertAdjacentHTML('beforebegin', "

" + viaData + "

"); 行き先情報.insertAdjacentHTML('beforebegin', "

" + TrainNumber + (JRF ? "":"レ") + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + (isWanman ? "ワンマン " : "") + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + viaData + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + trainName + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + (ToData ? ToData + "行 " : ToData) + "

"); 行き先情報.insertAdjacentHTML('beforebegin', "

" + (hasProblem ? "‼️停止中‼️" : "") + "

"); `: ` 行き先情報.insertAdjacentHTML('beforebegin', "

" + returnText1 + "

"); @@ -1278,23 +1280,27 @@ export const injectJavascriptData: InjectJavascriptData = ( const setNewTrainItem = (element,hasProblem)=>{ + var 列番データ = element.getAttribute('offclick').split('"')[1]; + 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 { + }else if(JRFTemp){ + element.style.borderColor = 'rgba(0, 134, 158, 0.8)'; + }else{ element.style.borderColor = 'white'; } element.style.borderWidth = '2px'; element.style.borderStyle = 'solid'; element.style.borderRadius = '10%'; - var 列番データ = element.getAttribute('offclick').split('"')[1]; 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: From b143e4251d118001cad75bc14a53663a2ebf3c42 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 15 Jun 2025 09:43:05 +0000 Subject: [PATCH 54/77] =?UTF-8?q?=E8=A1=8C=E3=81=8D=E5=85=88=E6=83=85?= =?UTF-8?q?=E5=A0=B1=E3=82=92=E7=8B=AC=E8=87=AA=E3=82=B5=E3=83=BC=E3=83=90?= =?UTF-8?q?=E3=83=BC=E3=83=99=E3=83=BC=E3=82=B9=E3=81=AB=E3=81=99=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/webViewInjectjavascript.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/webViewInjectjavascript.ts b/lib/webViewInjectjavascript.ts index fe5c3d5..dc6568a 100644 --- a/lib/webViewInjectjavascript.ts +++ b/lib/webViewInjectjavascript.ts @@ -34,6 +34,21 @@ export const injectJavascriptData: InjectJavascriptData = ( 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 = {}; + 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) => { + trainDiagramData2 = data; + }); let probremsData = []; fetch("https://n8n.haruk.in/webhook/jrshikoku-position-problems").then((response) => response.json()).then((data) => { probremsData = data.data; @@ -1041,12 +1056,11 @@ export const injectJavascriptData: InjectJavascriptData = ( let TrainNumber = 列番データ; try{ - const diagram = trainTimeInfo[列番データ]; + const diagram = trainDiagramData2[列番データ] || trainTimeInfo[列番データ]; if(diagram){ const diagramData = diagram.split("#"); ToData = diagramData[diagramData.length - 2].split(",")[0]; } - }catch(e){} if(列車名データ.split(":")[1]){ const textBase = 列車名データ.split(":")[1].replace("\\r",""); From c98407527b36709272887adf5d6320434fb980c2 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 15 Jun 2025 16:35:39 +0000 Subject: [PATCH 55/77] =?UTF-8?q?=E8=A1=8C=E3=81=8D=E5=85=88=E3=81=AE?= =?UTF-8?q?=E8=A3=8F=E3=81=AB=E9=A7=85=E3=81=AE=E8=B7=AF=E7=B7=9A=E3=82=AB?= =?UTF-8?q?=E3=83=A9=E3=83=BC=E3=82=92=E8=A8=AD=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/webViewInjectjavascript.ts | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/webViewInjectjavascript.ts b/lib/webViewInjectjavascript.ts index dc6568a..c4187ed 100644 --- a/lib/webViewInjectjavascript.ts +++ b/lib/webViewInjectjavascript.ts @@ -30,6 +30,10 @@ export const injectJavascriptData: InjectJavascriptData = ( // 上部ヘッダーの取り扱い、自動再読み込み、setStringsの実行 const bootData = ` + let stationList = {}; + fetch("https://n8n.haruk.in/webhook/jr-shikoku-station-list").then((response) => response.json()).then((data) => { + stationList = data; + }); let trainDataList = []; fetch("https://n8n.haruk.in/webhook/jr-shikoku-position-custom-datalist").then((response) => response.json()).then((data) => { trainDataList = data[0].data; @@ -1275,11 +1279,27 @@ export const injectJavascriptData: InjectJavascriptData = ( const returnText2 = (ToData ? ToData+"行 " : ToData)+ TrainNumber; 行き先情報.innerText = ""; ${uiSetting === "tokyo" ? ` + let stationIDs = []; + let stationLines = []; + Object.keys(stationList).forEach((key) => { + const data = stationList[key].find(e => e.Station_JP === ToData )?.StationNumber; + if(data){ + stationIDs.push(data); + stationLines.push(key); + } + }); + let getColors = []; + if(stationLines.length === 0){ + getColors = ["#000"]; + }else{ + getColors = stationLines.map(e => GetLineBarColor(e)); + } + const gradient = getColors.length > 1 ? "linear-gradient(130deg, " + getColors[0] + " 0%, "+ getColors[0]+"50%, "+ getColors[1]+"50%, " + getColors[1] + " 100%)" : getColors[0]; 行き先情報.insertAdjacentHTML('beforebegin', "

" + TrainNumber + (JRF ? "":"レ") + "

"); 行き先情報.insertAdjacentHTML('beforebegin', "

" + (isWanman ? "ワンマン " : "") + "

"); 行き先情報.insertAdjacentHTML('beforebegin', "

" + viaData + "

"); 行き先情報.insertAdjacentHTML('beforebegin', "

" + trainName + "

"); - 行き先情報.insertAdjacentHTML('beforebegin', "

" + (ToData ? ToData + "行 " : ToData) + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + (ToData ? ToData + "行" : ToData) + "

"); 行き先情報.insertAdjacentHTML('beforebegin', "

" + (hasProblem ? "‼️停止中‼️" : "") + "

"); `: ` 行き先情報.insertAdjacentHTML('beforebegin', "

" + returnText1 + "

"); From 570a55f4307025eaad90d9bf617e82fa87cf24a1 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Thu, 3 Jul 2025 12:08:43 +0000 Subject: [PATCH 56/77] =?UTF-8?q?pushtoken=E3=82=92=E9=80=81=E4=BF=A1?= =?UTF-8?q?=E3=81=97=E3=81=A6true=E3=81=98=E3=82=83=E3=81=AA=E3=81=8B?= =?UTF-8?q?=E3=81=A3=E3=81=9F=E3=82=89webview=E3=81=8C=E9=96=8B=E3=81=91?= =?UTF-8?q?=E3=82=8C=E3=81=AA=E3=81=84=E3=82=88=E3=81=86=E3=81=AB=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EachTrainInfoCore/HeaderText.tsx | 8 +++++++- menu.js | 4 ++-- stateBox/useTrainMenu.js | 20 +++++++++++++++++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/components/ActionSheetComponents/EachTrainInfoCore/HeaderText.tsx b/components/ActionSheetComponents/EachTrainInfoCore/HeaderText.tsx index 5500354..69d0663 100644 --- a/components/ActionSheetComponents/EachTrainInfoCore/HeaderText.tsx +++ b/components/ActionSheetComponents/EachTrainInfoCore/HeaderText.tsx @@ -9,6 +9,8 @@ import { TrainViewIcon } from "./trainViewIcon"; import { OneManText } from "./HeaderTextParts/OneManText"; import { customTrainDataDetector } from "@/components/custom-train-data"; import { InfogramText } from "@/components/ActionSheetComponents/EachTrainInfoCore/HeaderTextParts/InfogramText"; +import { useTrainMenu } from "@/stateBox/useTrainMenu"; +import { useNotification } from "@/stateBox/useNotifications"; type Props = { data: { trainNum: string; limited: string }; @@ -42,6 +44,9 @@ export const HeaderText: FC = ({ }) => { const { limited, trainNum } = data; + const { updatePermission } = useTrainMenu(); + const {expoPushToken} = useNotification(); + // 列車名、種別、フォントの取得 const [typeName, trainName, fontAvailable, isOneMan, infogram] = useMemo(() => { @@ -124,11 +129,12 @@ export const HeaderText: FC = ({ style={{ borderRadius: 5, flexDirection: "row", alignItems: "center" }} onLongPress={() => { navigate("generalWebView", { - uri: "https://jr-shikoku-data-post-system.pages.dev?trainNum=" + trainNum, + uri: "https://jr-shikoku-data-post-system.pages.dev?trainNum=" + trainNum + "&token=" + expoPushToken, useExitButton: false }); SheetManager.hide("EachTrainInfo"); }} + disabled={!updatePermission} > { - scrollRef.current.scrollTo({ + scrollRef?.current.scrollTo({ y: mapHeight > 80 ? mapHeight - 80 : 0, animated: bool, }); }; const goToMap = () => { - scrollRef.current.scrollTo({ + scrollRef?.current.scrollTo({ y: 0, animated: true, }); diff --git a/stateBox/useTrainMenu.js b/stateBox/useTrainMenu.js index c4d8467..f169fc0 100644 --- a/stateBox/useTrainMenu.js +++ b/stateBox/useTrainMenu.js @@ -5,6 +5,8 @@ import { ASCore } from "../storageControl"; import { getStationList2 } from "../lib/getStationList"; import { injectJavascriptData } from "../lib/webViewInjectjavascript"; +import { useNotification } from "../stateBox/useNotifications"; + const initialState = { selectedLine: undefined, setSelectedLine: () => {}, @@ -28,6 +30,8 @@ const initialState = { setTrainInfo: () => {}, trainMenu: "true", setTrainMenu: () => {}, + updatePermission : false, + setUpdatePermission : () => {}, injectJavascript: "", }; @@ -38,6 +42,7 @@ export const useTrainMenu = () => { }; export const TrainMenuProvider = ({ children }) => { + const { expoPushToken } = useNotification(); const [selectedLine, setSelectedLine] = useState(undefined); const [mapsStationData, setMapsStationData] = useState(undefined); useEffect(() => { @@ -50,6 +55,19 @@ export const TrainMenuProvider = ({ children }) => { 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]) + //列車情報表示関連 const [trainInfo, setTrainInfo] = useState({ trainNum: undefined, @@ -106,6 +124,8 @@ export const TrainMenuProvider = ({ children }) => { setTrainInfo, trainMenu, setTrainMenu, + updatePermission, + setUpdatePermission, injectJavascript, }} > From d8453608c923d0f6725402ba16bb76ea5d8bbf02 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Thu, 3 Jul 2025 15:09:35 +0000 Subject: [PATCH 57/77] =?UTF-8?q?=E5=88=97=E8=BB=8A=E6=83=85=E5=A0=B1?= =?UTF-8?q?=E3=81=AE=E9=A0=AD=E3=81=AB=E8=A8=98=E8=BC=89=E3=81=99=E3=82=8B?= =?UTF-8?q?=E5=88=97=E8=BB=8A=E5=90=8D=E3=82=92=E3=82=B5=E3=83=BC=E3=83=90?= =?UTF-8?q?=E3=83=BC=E3=81=8B=E3=82=89=E5=8B=95=E7=9A=84=E3=81=AB=E5=8F=96?= =?UTF-8?q?=E5=BE=97=E5=A4=89=E6=9B=B4=E5=8F=AF=E8=83=BD=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EachTrainInfoCore.js | 5 +- .../EachTrainInfoCore/HeaderText.tsx | 30 +- .../EachTrainInfoCore/trainIconStatus.tsx | 60 ++-- components/AllTrainDiagramView.js | 4 +- components/custom-train-data.ts | 302 +++++++++--------- components/発車時刻表/EachData.tsx | 35 +- lib/webViewInjectjavascript.ts | 3 + stateBox/useAllTrainDiagram.js | 20 +- 8 files changed, 263 insertions(+), 196 deletions(-) diff --git a/components/ActionSheetComponents/EachTrainInfoCore.js b/components/ActionSheetComponents/EachTrainInfoCore.js index c6f7cc0..23a15cb 100644 --- a/components/ActionSheetComponents/EachTrainInfoCore.js +++ b/components/ActionSheetComponents/EachTrainInfoCore.js @@ -44,7 +44,8 @@ export const EachTrainInfoCore = ({ }) => { const { currentTrain } = useCurrentTrain(); const { originalStationList, stationList } = useStationList(); - const { allTrainDiagram: trainList } = useAllTrainDiagram(); + const { allTrainDiagram: trainList, allCustonTrainData } = + useAllTrainDiagram(); const { setTrainInfo } = useTrainMenu(); const [currentTrainData, setCurrentTrainData] = useState(); @@ -322,7 +323,7 @@ export const EachTrainInfoCore = ({ }, []); const openTrainInfo = (d) => { - const train = customTrainDataDetector(d); + const train = customTrainDataDetector(d, allCustonTrainData); let TrainNumber = ""; if (train.trainNumDistance != undefined) { const timeInfo = diff --git a/components/ActionSheetComponents/EachTrainInfoCore/HeaderText.tsx b/components/ActionSheetComponents/EachTrainInfoCore/HeaderText.tsx index 69d0663..79b6195 100644 --- a/components/ActionSheetComponents/EachTrainInfoCore/HeaderText.tsx +++ b/components/ActionSheetComponents/EachTrainInfoCore/HeaderText.tsx @@ -1,8 +1,6 @@ import React, { CSSProperties, FC, useEffect, useMemo, useState } from "react"; -import { Text, View, LayoutAnimation, TextStyle, TouchableOpacity } from "react-native"; -import { Ionicons } from "@expo/vector-icons"; +import { Text, View, TextStyle, TouchableOpacity } from "react-native"; import { SheetManager } from "react-native-actions-sheet"; -import { getType } from "../../../lib/eachTrainInfoCoreLib/getType"; import { migrateTrainName } from "../../../lib/eachTrainInfoCoreLib/migrateTrainName"; import { TrainIconStatus } from "./trainIconStatus"; import { TrainViewIcon } from "./trainViewIcon"; @@ -10,6 +8,7 @@ import { OneManText } from "./HeaderTextParts/OneManText"; import { customTrainDataDetector } from "@/components/custom-train-data"; import { InfogramText } from "@/components/ActionSheetComponents/EachTrainInfoCore/HeaderTextParts/InfogramText"; import { useTrainMenu } from "@/stateBox/useTrainMenu"; +import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram"; import { useNotification } from "@/stateBox/useNotifications"; type Props = { @@ -40,17 +39,21 @@ export const HeaderText: FC = ({ tailStation, navigate, from, - scrollHandlers + scrollHandlers, }) => { const { limited, trainNum } = data; const { updatePermission } = useTrainMenu(); - const {expoPushToken} = useNotification(); + const { allCustonTrainData } = useAllTrainDiagram(); + const { expoPushToken } = useNotification(); // 列車名、種別、フォントの取得 const [typeName, trainName, fontAvailable, isOneMan, infogram] = useMemo(() => { - const customTrainData = customTrainDataDetector(trainNum); + const customTrainData = customTrainDataDetector( + trainNum, + allCustonTrainData + ); const [type, fontAvailable, isOneMan] = (() => { switch (customTrainData.type) { case "LTDEXP": @@ -123,14 +126,23 @@ export const HeaderText: FC = ({ }, [trainData]); return ( - scrollHandlers.ref.current?.scrollTo({ y: 0, animated: true })}> + + scrollHandlers.ref.current?.scrollTo({ y: 0, animated: true }) + } + > { navigate("generalWebView", { - uri: "https://jr-shikoku-data-post-system.pages.dev?trainNum=" + trainNum + "&token=" + expoPushToken, - useExitButton: false + uri: + "https://jr-shikoku-data-post-system.pages.dev?trainNum=" + + trainNum + + "&token=" + + expoPushToken, + useExitButton: false, }); SheetManager.hide("EachTrainInfo"); }} diff --git a/components/ActionSheetComponents/EachTrainInfoCore/trainIconStatus.tsx b/components/ActionSheetComponents/EachTrainInfoCore/trainIconStatus.tsx index ce910e1..105eb0f 100644 --- a/components/ActionSheetComponents/EachTrainInfoCore/trainIconStatus.tsx +++ b/components/ActionSheetComponents/EachTrainInfoCore/trainIconStatus.tsx @@ -6,6 +6,7 @@ import { useInterval } from "../../../lib/useInterval"; import { Icon } from "@expo/vector-icons/build/createIconSet"; import { SheetManager } from "react-native-actions-sheet"; import { customTrainDataDetector } from "../../custom-train-data"; +import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram"; type GlyphNames = ComponentProps["name"]; @@ -22,11 +23,14 @@ export const TrainIconStatus: FC = ({ data, navigate, from }) => { const [trainIcon, setTrainIcon] = useState(null); const [anpanmanStatus, setAnpanmanStatus] = useState(); const [address, setAddress] = useState(""); + const { allCustonTrainData } = useAllTrainDiagram(); useEffect(() => { if (!data.trainNum) return; - const { trainIcon, infoUrl } = customTrainDataDetector(data.trainNum); - if (trainIcon) setTrainIcon(trainIcon); - + const { img, infoUrl } = customTrainDataDetector( + data.trainNum, + allCustonTrainData + ); + if (img) setTrainIcon(img); if (infoUrl) setAddress(infoUrl); switch (data.trainNum) { @@ -57,31 +61,31 @@ export const TrainIconStatus: FC = ({ data, navigate, from }) => { } }); break; - case "2074D": - case "2076D": - case "2080D": - case "2082D": - case "2071D": - case "2073D": - case "2079D": - case "2081D": - fetch( - `https://n8n.haruk.in/webhook/dosan-anpanman-first?trainNum=${ - data.trainNum - }&month=${dayjs().format("M")}&day=${dayjs().format("D")}` - ) - .then((d) => d.json()) - .then((d) => { - console.log(d); - if (d.trainStatus == "〇") { - //setAnpanmanStatus({name:"checkmark-circle-outline",color:"blue"}); - } else if (d.trainStatus == "▲") { - setAnpanmanStatus({ name: "warning-outline", color: "yellow" }); - } else if (d.trainStatus == "×") { - //setAnpanmanStatus({ name: "close-circle-outline", color: "red" }); - } - }); - break; + case "2074D": + case "2076D": + case "2080D": + case "2082D": + case "2071D": + case "2073D": + case "2079D": + case "2081D": + fetch( + `https://n8n.haruk.in/webhook/dosan-anpanman-first?trainNum=${ + data.trainNum + }&month=${dayjs().format("M")}&day=${dayjs().format("D")}` + ) + .then((d) => d.json()) + .then((d) => { + console.log(d); + if (d.trainStatus == "〇") { + //setAnpanmanStatus({name:"checkmark-circle-outline",color:"blue"}); + } else if (d.trainStatus == "▲") { + setAnpanmanStatus({ name: "warning-outline", color: "yellow" }); + } else if (d.trainStatus == "×") { + //setAnpanmanStatus({ name: "close-circle-outline", color: "red" }); + } + }); + break; } }, [data.trainNum]); const [move, setMove] = useState(true); diff --git a/components/AllTrainDiagramView.js b/components/AllTrainDiagramView.js index a9ddd98..c426258 100644 --- a/components/AllTrainDiagramView.js +++ b/components/AllTrainDiagramView.js @@ -21,7 +21,7 @@ import { BigButton } from "./atom/BigButton"; import { Switch } from "react-native-elements"; export default function AllTrainDiagramView() { const { goBack, navigate } = useNavigation(); - const { keyList, allTrainDiagram } = useAllTrainDiagram(); + const { keyList, allTrainDiagram, allCustonTrainData } = useAllTrainDiagram(); const [input, setInput] = useState(""); // 文字入力 const [keyBoardVisible, setKeyBoardVisible] = useState(false); const [useStationName, setUseStationName] = useState(false); @@ -53,7 +53,7 @@ export default function AllTrainDiagramView() { }, []); const openTrainInfo = (d) => { - const train = customTrainDataDetector(d); + const train = customTrainDataDetector(d, allCustonTrainData); let TrainNumber = ""; if (train.trainNumDistance != undefined) { const timeInfo = diff --git a/components/custom-train-data.ts b/components/custom-train-data.ts index 59c049a..abe330c 100644 --- a/components/custom-train-data.ts +++ b/components/custom-train-data.ts @@ -1,6 +1,19 @@ import dayjs from "dayjs"; -export const customTrainDataDetector = (TrainNumber: string) => { - const trainGetText = `?trainNum=${TrainNumber}&month=${dayjs().format("M")}&day=${dayjs().format("D")}`; +export const customTrainDataDetector = ( + TrainNumber: string, + allCustonTrainData?: any[] +) => { + if (allCustonTrainData && allCustonTrainData.length > 0) { + const customTrain = allCustonTrainData.find( + (train) => train.TrainNumber === TrainNumber + ); + if (customTrain) { + return customTrain; + } + } + const trainGetText = `?trainNum=${TrainNumber}&month=${dayjs().format( + "M" + )}&day=${dayjs().format("D")}`; switch (TrainNumber) { //しおかぜメイン //8000 ノーマル @@ -24,23 +37,23 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "しおかぜ", - trainIcon: "https://storage.haruk.in/s8000nr.png", + img: "https://storage.haruk.in/s8000nr.png", infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/shiokaze.html", trainNumDistance: 0, info: "いしづちと併結 / 8000系で運転", - infogram: "G" + infogram: "G", }; case "2M": return { type: "LTDEXP", trainName: "しおかぜ", - trainIcon: "https://storage.haruk.in/s8000nr.png", + img: "https://storage.haruk.in/s8000nr.png", infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/shiokaze.html", trainNumDistance: 0, info: "8000系で運転", - infogram: "G" + infogram: "G", }; //8000 アンパン case "10M": @@ -50,11 +63,11 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "しおかぜ", - trainIcon: `https://n8n.haruk.in/webhook/anpanman-pictures.png${trainGetText}`, + img: `https://n8n.haruk.in/webhook/anpanman-pictures.png${trainGetText}`, infoUrl: "https://www.jr-eki.com/aptrain/naani/yosan/train.html", trainNumDistance: 0, info: "いしづちと併結 / アンパンマン列車で運転", - infogram: "G" + infogram: "G", }; //8600 case "8M": @@ -68,12 +81,12 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "しおかぜ", - trainIcon: "https://storage.haruk.in/s8600.png", + img: "https://storage.haruk.in/s8600.png", infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/shiokaze.html", trainNumDistance: 0, info: "いしづちと併結 / 8600系で運転", - infogram: "G" + infogram: "G", }; //いしづちメイン @@ -99,12 +112,12 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "いしづち", - trainIcon: "https://storage.haruk.in/s8000no.png", + img: "https://storage.haruk.in/s8000no.png", infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/ishizuchi.html", trainNumDistance: 1000, info: "しおかぜと併結 / 8000系で運転", - infogram: "" + infogram: "", }; //8000 アンパン @@ -115,11 +128,11 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "いしづち", - trainIcon: `https://n8n.haruk.in/webhook/anpanman-pictures.png${trainGetText}`, + img: `https://n8n.haruk.in/webhook/anpanman-pictures.png${trainGetText}`, infoUrl: "https://www.jr-eki.com/aptrain/naani/yosan/train.html", trainNumDistance: 1000, info: "しおかぜと併結 / アンパンマン列車で運転", - infogram: "" + infogram: "", }; //8600 @@ -134,12 +147,12 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "いしづち", - trainIcon: "https://storage.haruk.in/s8600_isz.png", + img: "https://storage.haruk.in/s8600_isz.png", infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/ishizuchi.html", trainNumDistance: 1000, info: "しおかぜと併結 / 8600系で運転", - infogram: "" + infogram: "", }; //MEXP @@ -148,24 +161,24 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "モーニングEXP高松", - trainIcon: "https://storage.haruk.in/s8000nr.png", + img: "https://storage.haruk.in/s8000nr.png", infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/morning.html", trainNumDistance: null, info: "8000系で運転", - infogram: "G" + infogram: "G", }; //8600 case "1091M": return { type: "LTDEXP", trainName: "モーニングEXP松山", - trainIcon: "https://storage.haruk.in/s8600_isz.png", + img: "https://storage.haruk.in/s8600_isz.png", infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/morning.html", trainNumDistance: null, info: "8600系で運転", - infogram: "G" + infogram: "G", }; //三桁いしづち //8000 アンパン @@ -174,11 +187,11 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "いしづち", - trainIcon: `https://n8n.haruk.in/webhook/anpanman-pictures.png${trainGetText}`, + img: `https://n8n.haruk.in/webhook/anpanman-pictures.png${trainGetText}`, infoUrl: "https://www.jr-eki.com/aptrain/naani/yosan/train.html", trainNumDistance: 940, info: "アンパンマン列車で運転", - infogram: "G" + infogram: "G", }; //8600 case "1043M": @@ -186,23 +199,23 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "いしづち", - trainIcon: "https://storage.haruk.in/s8600_isz.png", + img: "https://storage.haruk.in/s8600_isz.png", infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/ishizuchi.html", trainNumDistance: 940, info: "8600系で運転", - infogram: "" + infogram: "", }; case "1046M": return { type: "LTDEXP", trainName: "いしづち", - trainIcon: "https://storage.haruk.in/s8600_isz.png", + img: "https://storage.haruk.in/s8600_isz.png", infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/ishizuchi.html", trainNumDistance: 940, info: "8600系で運転", - infogram: "G" + infogram: "G", }; //南風 2700ノーマル @@ -227,11 +240,12 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "南風", - trainIcon: "https://storage.haruk.in/s2700.png", - infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/nanpu.html", + img: "https://storage.haruk.in/s2700.png", + infoUrl: + "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/nanpu.html", trainNumDistance: 30, info: "2700系で運転", - infogram: "G" + infogram: "G", }; //2700アンパン @@ -248,11 +262,11 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "南風", - trainIcon: `https://n8n.haruk.in/webhook/anpanman-pictures.png${trainGetText}`, + img: `https://n8n.haruk.in/webhook/anpanman-pictures.png${trainGetText}`, infoUrl: "https://www.jr-eki.com/aptrain/naani/dosan/train.html", trainNumDistance: 30, info: "アンパンマン列車で運転", - infogram: "G" + infogram: "G", }; //うずしお @@ -273,12 +287,12 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "うずしお", - trainIcon: "https://storage.haruk.in/s2700_uzu.png", + img: "https://storage.haruk.in/s2700_uzu.png", infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/uzushio.html", trainNumDistance: 3000, info: "2700系で運転", - infogram: "" + infogram: "", }; //2700 二両編成 @@ -295,12 +309,12 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "うずしお", - trainIcon: "https://storage.haruk.in/s2700_uzu.png", + img: "https://storage.haruk.in/s2700_uzu.png", infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/uzushio.html", trainNumDistance: 3000, info: "2700系で運転", - infogram: "" + infogram: "", }; //2600 @@ -317,15 +331,14 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "うずしお", - trainIcon: "https://storage.haruk.in/s2600.png", + img: "https://storage.haruk.in/s2600.png", infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/uzushio.html", trainNumDistance: 3000, info: "2600系で運転", - infogram: "" + infogram: "", }; - //マリンライナー case "3104M": case "3106M": @@ -398,11 +411,12 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "Rapid", trainName: "マリンライナー", - trainIcon: "https://storage.haruk.in/s5001.png", - infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/marine.html", + img: "https://storage.haruk.in/s5001.png", + infoUrl: + "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/marine.html", trainNumDistance: 3100, info: "", - infogram: "G" + infogram: "G", }; case "3102M": case "3101M": @@ -412,22 +426,23 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "Rapid", trainName: "マリンライナー", - trainIcon: "https://storage.haruk.in/s5001k.png", - infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/marine.html", + img: "https://storage.haruk.in/s5001k.png", + infoUrl: + "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/marine.html", trainNumDistance: 3100, info: "", - infogram: "" + infogram: "", }; //下りサンポート case "1219M": return { type: "Normal", trainName: "南風リレー", - trainIcon: "", + img: "", infoUrl: "", trainNumDistance: null, info: " 土曜・休日は多度津-琴平間運休", - infogram: "" + infogram: "", }; case "111M": @@ -443,11 +458,11 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "Rapid", trainName: "サンポート南風リレー", - trainIcon: null, + img: null, infoUrl: null, trainNumDistance: null, info: null, - infogram: "" + infogram: "", }; case "5109M": case "5135M": @@ -455,32 +470,32 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "OneManRapid", trainName: "サンポート南風リレー", - trainIcon: null, + img: null, infoUrl: null, trainNumDistance: null, info: null, - infogram: "" + infogram: "", }; case "137M": return { type: "Rapid", trainName: "サンポート", - trainIcon: null, + img: null, infoUrl: null, trainNumDistance: null, info: "土曜・休日運休", - infogram: "" + infogram: "", }; //上りサンポート case "116M": return { type: "Normal", trainName: "南風リレー", - trainIcon: null, + img: null, infoUrl: null, trainNumDistance: null, info: null, - infogram: "" + infogram: "", }; case "130M": @@ -494,11 +509,11 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "Rapid", trainName: "サンポート南風リレー", - trainIcon: "", + img: "", infoUrl: "", trainNumDistance: null, info: "", - infogram: "" + infogram: "", }; case "5118M": case "5120M": @@ -508,11 +523,11 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "OneManRapid", trainName: "サンポート南風リレー", - trainIcon: null, + img: null, infoUrl: null, trainNumDistance: null, info: null, - infogram: "" + infogram: "", }; //サンライズ瀬戸 @@ -521,24 +536,24 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "NightLTDEXP", trainName: "サンライズ瀬戸", - trainIcon: "https://storage.haruk.in/w285.png", + img: "https://storage.haruk.in/w285.png", infoUrl: "https://www.jr-odekake.net/train/sunriseseto_izumo/index.html", trainNumDistance: null, info: "", - infogram: "ブ" + infogram: "ブ", }; case "8041M": //琴平延長高松迄 case "8031M": //琴平延長高松以降 return { type: "NightLTDEXP", trainName: "サンライズ瀬戸", - trainIcon: "https://storage.haruk.in/w285.png", + img: "https://storage.haruk.in/w285.png", infoUrl: "https://www.jr-odekake.net/train/sunriseseto_izumo/index.html", trainNumDistance: null, info: "琴平延長運転日", - infogram: "ブ" + infogram: "ブ", }; //宇和海 @@ -572,11 +587,12 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "宇和海", - trainIcon: "https://storage.haruk.in/s2000_uwa.png", - infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/uwakai.html", + img: "https://storage.haruk.in/s2000_uwa.png", + infoUrl: + "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/uwakai.html", trainNumDistance: 1050, info: "2000系で運転", - infogram: "" + infogram: "", }; //2000 アンパン込み case "1058D": @@ -588,11 +604,11 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "宇和海", - trainIcon: `https://n8n.haruk.in/webhook/anpanman-pictures.png${trainGetText}`, + img: `https://n8n.haruk.in/webhook/anpanman-pictures.png${trainGetText}`, infoUrl: "https://www.jr-eki.com/aptrain/naani/yosan/train.html", trainNumDistance: 1050, info: "アンパン列車で運転", - infogram: "" + infogram: "", }; //しまんと case "2002D": @@ -602,12 +618,12 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "しまんと", - trainIcon: "https://storage.haruk.in/s2700_smn.png", + img: "https://storage.haruk.in/s2700_smn.png", infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/shimanto.html", trainNumDistance: 2000, info: "2700系で運転", - infogram: "" + infogram: "", }; //あしずり 2000 @@ -622,12 +638,12 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "あしずり", - trainIcon: `https://n8n.haruk.in/webhook/anpanman-pictures.png${trainGetText}`, + img: `https://n8n.haruk.in/webhook/anpanman-pictures.png${trainGetText}`, infoUrl: "https://www.jr-eki.com/aptrain/naani/first-generation/jikoku.html", trainNumDistance: 2070, info: "2000系で運転", - infogram: "" + infogram: "", }; //あしずり 2700 @@ -638,24 +654,24 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "あしずり", - trainIcon: "https://storage.haruk.in/s2700_asi.png", + img: "https://storage.haruk.in/s2700_asi.png", infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/ashizuri.html", trainNumDistance: 2070, info: "2700系で運転", - infogram: "" + infogram: "", }; case "2072D": case "2083D": return { type: "LTDEXP", trainName: "あしずり", - trainIcon: "https://storage.haruk.in/s2700_asi.png", + img: "https://storage.haruk.in/s2700_asi.png", infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/ashizuri.html", trainNumDistance: 2070, info: "2700系で運転", - infogram: "G" + infogram: "G", }; //剣山 @@ -669,12 +685,12 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "剣山", - trainIcon: "https://storage.haruk.in/s185tu.png", + img: "https://storage.haruk.in/s185tu.png", infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/tsurugisan.html", trainNumDistance: 4000, info: "キハ185系で運転", - infogram: "" + infogram: "", }; //よしのがわトロッコ @@ -683,12 +699,12 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "よしのがわトロッコ", - trainIcon: "https://storage.haruk.in/s185to_ai.png", + img: "https://storage.haruk.in/s185to_ai.png", infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/event_train/yoshino_torokko.html", trainNumDistance: null, info: "", - infogram: "" + infogram: "", }; //岡山高松アントロ @@ -700,12 +716,12 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "アンパンマントロッコ", - trainIcon: "https://storage.haruk.in/s32to4.png", + img: "https://storage.haruk.in/s32to4.png", infoUrl: "https://www.jr-eki.com/aptrain/naani/torokko_seto/jikoku.html", trainNumDistance: null, info: "", - infogram: "G" + infogram: "G", }; //伊予灘ものがたり @@ -714,22 +730,22 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "伊予灘ものがたり", - trainIcon: "https://storage.haruk.in/s185iyor.png", + img: "https://storage.haruk.in/s185iyor.png", infoUrl: "https://iyonadamonogatari.com/", trainNumDistance: null, info: "", - infogram: "G" + infogram: "G", }; case "8092D": case "8094D": return { type: "LTDEXP", trainName: "伊予灘ものがたり", - trainIcon: "https://storage.haruk.in/s185iyoy.png", + img: "https://storage.haruk.in/s185iyoy.png", infoUrl: "https://iyonadamonogatari.com/", trainNumDistance: null, info: "", - infogram: "G" + infogram: "G", }; //千年ものがたり @@ -738,11 +754,11 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "四国まんなか千年ものがたり", - trainIcon: "https://storage.haruk.in/s185mm1.png", + img: "https://storage.haruk.in/s185mm1.png", infoUrl: "https://www.jr-shikoku.co.jp/sennenmonogatari/", trainNumDistance: null, info: "", - infogram: "G" + infogram: "G", }; //夜明けものがたり @@ -753,67 +769,67 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "LTDEXP", trainName: "時代の夜明けのものがたり", - trainIcon: "https://storage.haruk.in/s185ym1.png", + img: "https://storage.haruk.in/s185ym1.png", infoUrl: "https://www.jr-shikoku.co.jp/yoakenomonogatari/index.html", trainNumDistance: null, info: "", - infogram: "G" + infogram: "G", }; case "9174M": return { type: "SPCL_Rapid", trainName: "マリンライナー94号", - trainIcon: "https://storage.haruk.in/s5001.png", - infoUrl: "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/marine.html", + img: "https://storage.haruk.in/s5001.png", + infoUrl: + "https://www.jr-shikoku.co.jp/01_trainbus/vehicle-info/marine.html", trainNumDistance: null, info: "臨時列車 4/12,13,19のみ運転", - infogram: "G" + infogram: "G", }; case "9395D": return { type: "SPCL_Normal", trainName: "", - trainIcon: "https://storage.haruk.in/s1500.png", + img: "https://storage.haruk.in/s1500.png", infoUrl: null, trainNumDistance: null, info: "臨時列車 4/12,13,19のみ運転", - infogram: "" + infogram: "", + }; + case "9662D": + case "9665D": + return { + type: "SPCL_Normal", + trainName: "れんげ号", + img: "", + infoUrl: null, + trainNumDistance: null, + info: "臨時列車 4/29のみ運転", + infogram: "", + }; + case "9664D": + case "9663D": + return { + type: "SPCL_Normal", + trainName: "わらぐろ号", + img: "", + infoUrl: null, + trainNumDistance: null, + info: "臨時列車 4/29のみ運転", + infogram: "", }; - case "9662D": - case "9665D": - return { - type: "SPCL_Normal", - trainName: "れんげ号", - trainIcon: "", - infoUrl: null, - trainNumDistance: null, - info: "臨時列車 4/29のみ運転", - infogram: "" - }; - case "9664D": - case "9663D": - return { - type: "SPCL_Normal", - trainName: "わらぐろ号", - trainIcon: "", - infoUrl: null, - trainNumDistance: null, - info: "臨時列車 4/29のみ運転", - infogram: "" - }; default: - if(getJRF(TrainNumber) !== null){ + if (getJRF(TrainNumber) !== null) { return { type: "Freight", trainName: getJRF(TrainNumber), - trainIcon: "https://storage.haruk.in/ef210a.png", + img: "https://storage.haruk.in/ef210a.png", infoUrl: null, trainNumDistance: null, info: "", infogram: "", }; - } - else if ( + } else if ( new RegExp(/^4[1-9]\d\d[DM]$/).test(TrainNumber) || new RegExp(/^5[1-7]\d\d[DM]$/).test(TrainNumber) || new RegExp(/^3[2-9]\d\d[DM]$/).test(TrainNumber) @@ -821,38 +837,38 @@ export const customTrainDataDetector = (TrainNumber: string) => { return { type: "OneMan", trainName: "", - trainIcon: null, + img: null, infoUrl: null, trainNumDistance: null, info: null, - infogram: "" + infogram: "", }; else if ( new RegExp(/^[1-9]\d\d[DM]$/).test(TrainNumber) || new RegExp(/^1[26]\d\d[DM]$/).test(TrainNumber) || new RegExp(/^58\d\d[DM]$/).test(TrainNumber) || new RegExp(/^6\d\d\d[DM]$/).test(TrainNumber) - ){ - return { - type: "Normal", - trainName: "", - trainIcon: null, - infoUrl: null, - trainNumDistance: null, - info: null, - infogram: "" - }; - } else { - return { - type: "Other", - trainName: "", - trainIcon: null, - infoUrl: null, - trainNumDistance: null, - info: null, - infogram: "" - }; - } + ) { + return { + type: "Normal", + trainName: "", + img: null, + infoUrl: null, + trainNumDistance: null, + info: null, + infogram: "", + }; + } else { + return { + type: "Other", + trainName: "", + img: null, + infoUrl: null, + trainNumDistance: null, + info: null, + infogram: "", + }; + } } }; export const getJRF = (num: string) => { diff --git a/components/発車時刻表/EachData.tsx b/components/発車時刻表/EachData.tsx index 664fd8e..1e2f2dc 100644 --- a/components/発車時刻表/EachData.tsx +++ b/components/発車時刻表/EachData.tsx @@ -18,6 +18,7 @@ import { TrainPositionDataDelete } from "./LED_inside_Component/TrainPositionDat import { useStationList } from "../../stateBox/useStationList"; import useInterval from "@/lib/useInterval"; import dayjs from "dayjs"; +import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram"; type Props = { d: { @@ -45,6 +46,7 @@ export const EachData: FC = (props) => { } = props; const { currentTrain } = useCurrentTrain(); const { stationList } = useStationList(); + const { allCustonTrainData } = useAllTrainDiagram(); const openTrainInfo = (d: { train: string; lastStation: string; @@ -74,7 +76,10 @@ export const EachData: FC = (props) => { }; const getTrainDataFromCurrentTrain = (trainNum: string) => { - const customTrainData = customTrainDataDetector(d.train); + const customTrainData = customTrainDataDetector( + d.train, + allCustonTrainData + ); switch (customTrainData.type) { case "Normal": case "OneMan": @@ -122,21 +127,22 @@ export const EachData: FC = (props) => { const [isShow, setIsShow] = useState(true); const [isDepartureNow, setIsDepartureNow] = useState(false); - useEffect(()=>{ + useEffect(() => { const currentTime = dayjs(); - const trainTime = currentTime.set("hour", parseInt(d.time.split(":")[0])).set("minute", parseInt(d.time.split(":")[1])); + const trainTime = currentTime + .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); - return()=>{ + return () => { setIsDepartureNow(false); setIsShow(true); - } - }, [d.time,currentTrainData]); - useInterval(()=>{ + }; + }, [d.time, currentTrainData]); + useInterval(() => { if (isDepartureNow) { - setIsShow(!isShow); - + setIsShow(!isShow); } }, 800); return ( @@ -172,7 +178,7 @@ export const EachData: FC = (props) => { opacity: isShow ? 1 : 0.5, }} onPress={() => openTrainInfo(d)} - key={ d.train + "-eachData" } + key={d.train + "-eachData"} > = (props) => { {!!isDepartureNow && ( - + )} {trainDescriptionSwitch && ( {}, + allCustonTrainData: [], }; const AllTrainDiagramContext = createContext(initialState); @@ -12,6 +13,7 @@ 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)), @@ -41,10 +43,26 @@ export const AllTrainDiagramProvider = ({ children }) => { }); }); }, []); + 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 ( {children} From bb41118e39f273fa9a5359f0e9042ee163e8e6cf Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sat, 5 Jul 2025 05:19:06 +0000 Subject: [PATCH 58/77] =?UTF-8?q?=E6=95=B0=E5=AD=97=E3=81=AE=E8=A1=A8?= =?UTF-8?q?=E7=A4=BA=E3=82=84=E3=83=AA=E3=82=B9=E3=83=88=E3=81=AE=E8=A1=A8?= =?UTF-8?q?=E7=A4=BA=E4=BD=8D=E7=BD=AE=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/AllTrainDiagramView.js | 9 +++++++++ lib/webViewInjectjavascript.ts | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/components/AllTrainDiagramView.js b/components/AllTrainDiagramView.js index c426258..491f9cc 100644 --- a/components/AllTrainDiagramView.js +++ b/components/AllTrainDiagramView.js @@ -74,6 +74,7 @@ export default function AllTrainDiagramView() { return ( { if (useStationName) { @@ -93,6 +94,14 @@ export default function AllTrainDiagramView() { return d.includes(input); })} renderItem={({ item }) => } + ListEmptyComponent={ + + + 検索結果がありません。 + + + } + keyExtractor={(item) => item} //initialNumToRender={100} /> diff --git a/lib/webViewInjectjavascript.ts b/lib/webViewInjectjavascript.ts index 0858bb4..cc4076b 100644 --- a/lib/webViewInjectjavascript.ts +++ b/lib/webViewInjectjavascript.ts @@ -1266,7 +1266,7 @@ export const injectJavascriptData: InjectJavascriptData = ( isWanman = data.isWanman; if(data.trainName != ""){ trainName = data.trainName; - if(!isNaN(data.trainNumDistance)){ + if(data.trainNumDistance != null){ trainName += parseInt(列番データ.replace("M", "").replace("D", "")) - data.trainNumDistance+"号"; } } From 3488c5e8d5cfde69e253ef0e03bf3c303e873bc1 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sat, 5 Jul 2025 05:33:55 +0000 Subject: [PATCH 59/77] =?UTF-8?q?=E3=82=A2=E3=82=A4=E3=82=B3=E3=83=B3?= =?UTF-8?q?=E3=81=8C=E8=A8=AD=E5=AE=9A=E3=81=95=E3=82=8C=E3=81=A6=E3=81=84?= =?UTF-8?q?=E3=81=A6=E3=82=82=E3=82=A2=E3=83=89=E3=83=AC=E3=82=B9=E3=81=8C?= =?UTF-8?q?=E8=A8=AD=E5=AE=9A=E3=81=95=E3=82=8C=E3=81=A6=E3=81=AA=E3=81=8B?= =?UTF-8?q?=E3=81=A3=E3=81=9F=E3=82=89=E3=82=AF=E3=83=AA=E3=83=83=E3=82=AF?= =?UTF-8?q?=E3=81=A7=E3=81=8D=E3=81=AA=E3=81=84=E3=82=88=E3=81=86=E3=81=AB?= =?UTF-8?q?=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ActionSheetComponents/EachTrainInfoCore/trainIconStatus.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/components/ActionSheetComponents/EachTrainInfoCore/trainIconStatus.tsx b/components/ActionSheetComponents/EachTrainInfoCore/trainIconStatus.tsx index 105eb0f..2612f7f 100644 --- a/components/ActionSheetComponents/EachTrainInfoCore/trainIconStatus.tsx +++ b/components/ActionSheetComponents/EachTrainInfoCore/trainIconStatus.tsx @@ -108,6 +108,7 @@ export const TrainIconStatus: FC = ({ data, navigate, from }) => { }); SheetManager.hide("EachTrainInfo"); }} + disabled={!address} > {move ? ( Date: Sat, 5 Jul 2025 07:47:44 +0000 Subject: [PATCH 60/77] =?UTF-8?q?=E3=81=8A=E6=B0=97=E3=81=AB=E5=85=A5?= =?UTF-8?q?=E3=82=8A=E3=83=AA=E3=82=B9=E3=83=88=E3=81=8B=E3=82=89=E3=81=AE?= =?UTF-8?q?=E3=82=B8=E3=83=A3=E3=83=B3=E3=83=97=E3=82=92=E5=85=A8=E3=81=A6?= =?UTF-8?q?=E3=81=AE=E9=A7=85=E3=81=A7=E5=88=A9=E7=94=A8=E5=8F=AF=E8=83=BD?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Apps/WebView.jsx | 44 +++++++++++++++++++++++++++---------- lib/getStationList.ts | 11 ++++++++++ 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/components/Apps/WebView.jsx b/components/Apps/WebView.jsx index 28e19dc..257d189 100644 --- a/components/Apps/WebView.jsx +++ b/components/Apps/WebView.jsx @@ -2,7 +2,13 @@ import React from "react"; import { Platform, LayoutAnimation } from "react-native"; import { WebView } from "react-native-webview"; -import { lineList, stationNamePair } from "../../lib/getStationList"; +import { + lineList, + lineList_LineWebID, + lineListPair, + stationIDPair, + stationNamePair, +} from "../../lib/getStationList"; import { checkDuplicateTrainData } from "../../lib/checkDuplicateTrainData"; import { useFavoriteStation } from "../../stateBox/useFavoriteStation"; import { useCurrentTrain } from "../../stateBox/useCurrentTrain"; @@ -129,19 +135,35 @@ export const AppsWebView = ({ openStationACFromEachTrainInfo }) => { const onLoadEnd = () => { if (once) return () => {}; if (!stationData) return () => {}; + if (!originalStationList) return () => {}; if (favoriteStation.length < 1) return () => {}; - const getStationLine = (now) => { - const returnData = Object.keys(stationData).filter((d) => { - const cache = stationData[d].findIndex( - (data) => data.Station_JP == now.Station_JP - ); - return cache != -1; + const bootStationList = []; + Object.keys(originalStationList).forEach((d) => { + let findNearStations = false; + originalStationList[d].forEach((x) => { + let lineName = lineList_LineWebID[d]; + if (findNearStations) { + if (x.MyStation){ + bootStationList.push({ line: lineName, station: x }); + findNearStations = false; + } + return; + } + if (x.StationNumber == favoriteStation[0][0].StationNumber) { + console.log(originalStationList[d]); + if (!x.MyStation) findNearStations = true; + else bootStationList.push({ line: lineName, station: x }); + } }); - return returnData[0]; - }; - const lineName = getStationLine(favoriteStation[0][0]); + if (favoriteStation[0].StationNumber == "M12") { + bootStationList.push({ + line: "seto", + station: { Station_JP: "児島", MyStation: "0" }, + }); + } + }); webview.current?.injectJavaScript( - `MoveDisplayStation('${lineName}_${favoriteStation[0][0].MyStation}_${favoriteStation[0][0].Station_JP}')` + `MoveDisplayStation('${bootStationList[0].line}_${bootStationList[0].station.MyStation}_${bootStationList[0].station.Station_JP}')` ); once = true; }; diff --git a/lib/getStationList.ts b/lib/getStationList.ts index 1a851f3..796e893 100644 --- a/lib/getStationList.ts +++ b/lib/getStationList.ts @@ -40,6 +40,17 @@ export const lineListPair = { N: "鳴門線(池谷-鳴門間)[N]", M: "瀬戸大橋線(児島-宇多津間)[M]", }; +export const lineList_LineWebID = { + "予讃線(高松-松山間)[Y]" : "yosan", + "予讃線(松山-宇和島間)[U]" : "uwajima", + "予讃線/愛ある伊予灘線(向井原-伊予大洲間)[S]" : "uwajima2", + "土讃線(多度津-高知間)[D]" : "dosan", + "土讃線(高知-窪川間)[K]" : "dosan2", + "高徳線(高松-徳島間)[T]" : "koutoku", + "徳島線(徳島-阿波池田間)[B]" : "tokushima", + "鳴門線(池谷-鳴門間)[N]" : "naruto", + "瀬戸大橋線(児島-宇多津間)[M]" : "seto", +}; export const getStationList2 = async () => { return { yosan, From 65123424a34d6511a09a818b583f12292c8e3bb2 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sat, 5 Jul 2025 07:57:55 +0000 Subject: [PATCH 61/77] =?UTF-8?q?=E9=A7=85=E3=81=B8=E3=81=AE=E7=A7=BB?= =?UTF-8?q?=E5=8B=95=E3=82=B9=E3=82=AF=E3=83=AA=E3=83=97=E3=83=88=E3=82=92?= =?UTF-8?q?hooks=E3=81=AB=E7=A7=BB=E5=8B=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Apps/WebView.jsx | 33 ++--------------- stateBox/useStationList.tsx | 74 +++++++++++++++++++++++++++++-------- 2 files changed, 63 insertions(+), 44 deletions(-) diff --git a/components/Apps/WebView.jsx b/components/Apps/WebView.jsx index 257d189..13d0e13 100644 --- a/components/Apps/WebView.jsx +++ b/components/Apps/WebView.jsx @@ -23,7 +23,7 @@ export const AppsWebView = ({ openStationACFromEachTrainInfo }) => { const { navigate } = useNavigation(); const { favoriteStation } = useFavoriteStation(); const { isLandscape } = useDeviceOrientationChange(); - const { originalStationList, stationList } = useStationList(); + const { originalStationList, stationList, getInjectJavascriptAddress } = useStationList(); const { setSelectedLine, mapsStationData: stationData, @@ -137,34 +137,9 @@ export const AppsWebView = ({ openStationACFromEachTrainInfo }) => { if (!stationData) return () => {}; if (!originalStationList) return () => {}; if (favoriteStation.length < 1) return () => {}; - const bootStationList = []; - Object.keys(originalStationList).forEach((d) => { - let findNearStations = false; - originalStationList[d].forEach((x) => { - let lineName = lineList_LineWebID[d]; - if (findNearStations) { - if (x.MyStation){ - bootStationList.push({ line: lineName, station: x }); - findNearStations = false; - } - return; - } - if (x.StationNumber == favoriteStation[0][0].StationNumber) { - console.log(originalStationList[d]); - if (!x.MyStation) findNearStations = true; - else bootStationList.push({ line: lineName, station: x }); - } - }); - if (favoriteStation[0].StationNumber == "M12") { - bootStationList.push({ - line: "seto", - station: { Station_JP: "児島", MyStation: "0" }, - }); - } - }); - webview.current?.injectJavaScript( - `MoveDisplayStation('${bootStationList[0].line}_${bootStationList[0].station.MyStation}_${bootStationList[0].station.Station_JP}')` - ); + const string = getInjectJavascriptAddress(favoriteStation[0][0].StationNumber); + if (!string) return () => {}; + webview.current?.injectJavaScript(string); once = true; }; diff --git a/stateBox/useStationList.tsx b/stateBox/useStationList.tsx index 97eac6a..aae75b8 100644 --- a/stateBox/useStationList.tsx +++ b/stateBox/useStationList.tsx @@ -5,7 +5,11 @@ import React, { useEffect, FC, } from "react"; -import { lineList, getStationList } from "../lib/getStationList"; +import { + lineList, + getStationList, + lineList_LineWebID, +} from "../lib/getStationList"; type initialStateType = { originalStationList: any[][]; @@ -13,6 +17,7 @@ type initialStateType = { getStationDataFromName: (id: string) => any[]; getStationDataFromId: (id: string) => any[]; stationList: any[]; + getInjectJavascriptAddress: (StationNumber: string) => string; }; const initialState = { originalStationList: [[]], @@ -20,6 +25,7 @@ const initialState = { getStationDataFromName: () => [], getStationDataFromId: () => [], stationList: [], + getInjectJavascriptAddress: (StationNumber: string) => "", }; const StationListContext = createContext(initialState); @@ -40,7 +46,10 @@ export const StationListProvider: FC = ({ children }) => { Object.keys(originalStationList).forEach((key) => { originalStationList[key].forEach((station) => { if (station.StationNumber === id) { - returnArray = [...returnArray, ...getStationDataFromName(station.Station_JP)]; + returnArray = [ + ...returnArray, + ...getStationDataFromName(station.Station_JP), + ]; } }); }); @@ -58,21 +67,56 @@ export const StationListProvider: FC = ({ children }) => { return returnArray; }; const [stationList, setStationList] = useState([[]]); - useEffect(()=>{ - if(originalStationList.length === 0) return; - const stationList = - lineList.map((d) => - originalStationList[d].map((a) => ({ - StationNumber: a.StationNumber, - StationName: a.Station_JP, - })) - ); - setStationList(stationList); - },[originalStationList]) - + useEffect(() => { + if (originalStationList.length === 0) return; + const stationList = lineList.map((d) => + originalStationList[d].map((a) => ({ + StationNumber: a.StationNumber, + StationName: a.Station_JP, + })) + ); + setStationList(stationList); + }, [originalStationList]); + + const getInjectJavascriptAddress = (StationNumber: string) => { + const bootStationList = []; + Object.keys(originalStationList).forEach((d) => { + let findNearStations = false; + originalStationList[d].forEach((x) => { + let lineName = lineList_LineWebID[d]; + if (findNearStations) { + if (x.MyStation) { + bootStationList.push({ line: lineName, station: x }); + findNearStations = false; + } + return; + } + if (x.StationNumber == StationNumber) { + console.log(originalStationList[d]); + if (!x.MyStation) findNearStations = true; + else bootStationList.push({ line: lineName, station: x }); + } + }); + if (StationNumber == "M12") { + bootStationList.push({ + line: "seto", + station: { Station_JP: "児島", MyStation: "0" }, + }); + } + }); + return `MoveDisplayStation('${bootStationList[0].line}_${bootStationList[0].station.MyStation}_${bootStationList[0].station.Station_JP}')`; + }; + return ( {children} From 218f9d509393bdd4de37ec4f1137a6dd0b7f1aa7 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sat, 5 Jul 2025 08:48:16 +0000 Subject: [PATCH 62/77] =?UTF-8?q?=E5=85=A8=E9=A7=85=E5=9C=B0=E5=9B=B3?= =?UTF-8?q?=E8=A1=A8=E7=A4=BA=E3=81=AB=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/TrainMenu/MapPin.tsx | 11 ++++++----- components/trainMenu.js | 18 ++++++++---------- lib/getStationList.ts | 5 +++++ stateBox/useStationList.tsx | 2 +- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/components/TrainMenu/MapPin.tsx b/components/TrainMenu/MapPin.tsx index f679e6b..5d4eef2 100644 --- a/components/TrainMenu/MapPin.tsx +++ b/components/TrainMenu/MapPin.tsx @@ -1,6 +1,7 @@ import React, { FC } from "react"; import { Marker } from "react-native-maps"; import { useNavigation } from "@react-navigation/native"; +import { useStationList } from "@/stateBox/useStationList"; type Props = { index: number; indexBase: number; @@ -13,7 +14,8 @@ type Props = { export const MapPin: FC = (props) => { const { index, indexBase, latlng, D, d, navigate, webview } = props; - const {goBack} = useNavigation(); + const { goBack } = useNavigation(); + const { getInjectJavascriptAddress } = useStationList(); return ( = (props) => { longitude: parseFloat(latlng[1]), }} onPress={() => { - webview.current?.injectJavaScript( - `MoveDisplayStation('${d}_${D.MyStation}_${D.Station_JP}'); - document.getElementById("disp").insertAdjacentHTML("afterbegin", "
");` - ); + const address = getInjectJavascriptAddress(D.StationNumber); + if (!address) return; + webview.current?.injectJavaScript(address); if (navigate) goBack(); }} image={require("../../assets/reccha-small.png")} diff --git a/components/trainMenu.js b/components/trainMenu.js index ad3ad94..746084f 100644 --- a/components/trainMenu.js +++ b/components/trainMenu.js @@ -4,12 +4,13 @@ import MapView from "react-native-maps"; import { useCurrentTrain } from "../stateBox/useCurrentTrain"; import { useNavigation } from "@react-navigation/native"; import lineColorList from "../assets/originData/lineColorList"; -import { lineListPair, stationIDPair } from "../lib/getStationList"; +import { lineList_LineWebID, lineListPair, stationIDPair } from "../lib/getStationList"; import { SheetManager } from "react-native-actions-sheet"; import { useTrainMenu } from "../stateBox/useTrainMenu"; import { MapPin } from "./TrainMenu/MapPin"; import { UsefulBox } from "./TrainMenu/UsefulBox"; import { MapsButton } from "./TrainMenu/MapsButton"; +import { useStationList } from "@/stateBox/useStationList"; export default function TrainMenu({ style }) { const { webview } = useCurrentTrain(); const mapRef = useRef(); @@ -20,22 +21,19 @@ export default function TrainMenu({ style }) { setSelectedLine, mapsStationData: stationData, } = useTrainMenu(); + const { originalStationList } = useStationList(); useEffect(() => { const stationPinData = []; - Object.keys(stationData).forEach((d, indexBase) => { - stationData[d].forEach((D, index) => { - if (!D.StationMap) return null; - if (selectedLine && selectedLine != d) return; - const latlng = D.StationMap.replace( - "https://www.google.co.jp/maps/place/", - "" - ).split(","); + Object.keys(originalStationList).forEach((d, indexBase) => { + originalStationList[d].forEach((D, index) => { + if (selectedLine && selectedLine != lineList_LineWebID[d]) return; + const latlng = [D.lat,D.lng]; if (latlng.length == 0) return null; stationPinData.push({ D, d, latlng, indexBase: 0, index }); }); }); setStationPin(stationPinData); - }, [stationData, selectedLine]); + }, [originalStationList, selectedLine]); useLayoutEffect(() => { mapRef.current.fitToCoordinates( stationPin.map(({ latlng }) => ({ diff --git a/lib/getStationList.ts b/lib/getStationList.ts index 796e893..02608df 100644 --- a/lib/getStationList.ts +++ b/lib/getStationList.ts @@ -178,6 +178,11 @@ export const getStationList = async () => { 予讃線, stationList["日英対応表"] ); + stationList["予讃線(松山-宇和島間)[U]"] = addStationPosition( + concatBetweenStations(stationList["予讃線(松山-宇和島間)[U]"]), + 内子線, + stationList["日英対応表"] + ); stationList["予讃線/愛ある伊予灘線(向井原-伊予大洲間)[S]"] = addStationPosition( concatBetweenStations( diff --git a/stateBox/useStationList.tsx b/stateBox/useStationList.tsx index aae75b8..4a0d10a 100644 --- a/stateBox/useStationList.tsx +++ b/stateBox/useStationList.tsx @@ -104,7 +104,7 @@ export const StationListProvider: FC = ({ children }) => { }); } }); - return `MoveDisplayStation('${bootStationList[0].line}_${bootStationList[0].station.MyStation}_${bootStationList[0].station.Station_JP}')`; + return `MoveDisplayStation('${bootStationList[0].line}_${bootStationList[0].station.MyStation}_${bootStationList[0].station.Station_JP}');document.getElementById("disp").insertAdjacentHTML("afterbegin", "
");`; }; return ( From 012544beebf66d416d7a93f252e599ce201bcb47 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sat, 5 Jul 2025 09:43:44 +0000 Subject: [PATCH 63/77] =?UTF-8?q?=E9=A7=85=E3=81=AE=E5=9C=B0=E5=9B=B3?= =?UTF-8?q?=E6=83=85=E5=A0=B1=E3=82=92=E5=85=A8=E9=96=8B=E6=94=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/ActionSheetComponents/StationDeteilView.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/components/ActionSheetComponents/StationDeteilView.js b/components/ActionSheetComponents/StationDeteilView.js index a75c2e2..b4a4626 100644 --- a/components/ActionSheetComponents/StationDeteilView.js +++ b/components/ActionSheetComponents/StationDeteilView.js @@ -135,9 +135,7 @@ export const StationDeteilView = (props) => { useShow={useShow} /> )} - {!currentStation[0].StationMap || ( - - )} + {!trainBus || ( Date: Sat, 5 Jul 2025 10:49:30 +0000 Subject: [PATCH 64/77] =?UTF-8?q?LED=E3=81=AE=E6=9E=A0=E3=81=AB=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE=E6=83=85=E5=A0=B1=E3=82=B8=E3=83=A3=E3=83=B3=E3=83=97?= =?UTF-8?q?=E3=83=9C=E3=82=BF=E3=83=B3=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/FavoriteList.tsx | 21 +--- .../LED_Vision_Component/Header.js | 112 +++++++++++------- components/発車時刻表/LED_vidion.js | 2 +- stateBox/useCurrentTrain.js | 1 + 4 files changed, 77 insertions(+), 59 deletions(-) diff --git a/components/FavoriteList.tsx b/components/FavoriteList.tsx index 814da0f..55b3ef9 100644 --- a/components/FavoriteList.tsx +++ b/components/FavoriteList.tsx @@ -8,11 +8,13 @@ import { useNavigation } from "@react-navigation/native"; import { useTrainMenu } from "../stateBox/useTrainMenu"; import { FavoriteListItem } from "./atom/FavoriteListItem"; import { BigButton } from "./atom/BigButton"; +import { useStationList } from "@/stateBox/useStationList"; export const FavoriteList: FC = () => { const { favoriteStation } = useFavoriteStation(); const { webview } = useCurrentTrain(); const { navigate, addListener, goBack, canGoBack } = useNavigation(); const { mapsStationData: stationData } = useTrainMenu(); + const { getInjectJavascriptAddress } = useStationList(); useEffect(() => { const unsubscribe = addListener("tabPress", goToTrainMenu); @@ -38,27 +40,16 @@ export const FavoriteList: FC = () => { {favoriteStation - .filter((d) => d[0].StationMap) .map((currentStation) => { return ( { - const getStationLine = (now) => { - const returnData = Object.keys(stationData).filter((d) => { - const cache = stationData[d].findIndex( - (data) => data.Station_JP == now.Station_JP - ); - return cache != -1; - }); - return returnData[0]; - }; - const lineName = getStationLine(currentStation[0]); - - webview.current?.injectJavaScript( - `MoveDisplayStation('${lineName}_${currentStation[0].MyStation}_${currentStation[0].Station_JP}'); - document.getElementById("disp").insertAdjacentHTML("afterbegin", "
");` + const scriptString = getInjectJavascriptAddress( + currentStation[0].StationNumber ); + if (!scriptString) return; + webview.current?.injectJavaScript(scriptString); goBack(); if (canGoBack()) goBack(); }} diff --git a/components/発車時刻表/LED_Vision_Component/Header.js b/components/発車時刻表/LED_Vision_Component/Header.js index 274b9c8..dece8e8 100644 --- a/components/発車時刻表/LED_Vision_Component/Header.js +++ b/components/発車時刻表/LED_Vision_Component/Header.js @@ -1,48 +1,74 @@ import { View, Text } from "react-native"; import { useCurrentTrain } from "../../../stateBox/useCurrentTrain"; import LottieView from "lottie-react-native"; -import { Ionicons } from "@expo/vector-icons"; +import { Ionicons, AntDesign } from "@expo/vector-icons"; +import { useStationList } from "@/stateBox/useStationList"; +import { useNavigation } from "@react-navigation/native"; -export const Header = () => { - const { currentTrainLoading, setCurrentTrainLoading,getCurrentTrain } = useCurrentTrain(); - return ( - - - - - 次の列車 - - Next Train - - - {currentTrainLoading == "loading" ? ( - - ) : currentTrainLoading == "error" ? ( - { - setCurrentTrainLoading("loading"); - getCurrentTrain(); - }} - /> - ) : null} - +export const Header = ({ station }) => { + const { + currentTrainLoading, + setCurrentTrainLoading, + getCurrentTrain, + inject, + } = useCurrentTrain(); + const { getInjectJavascriptAddress } = useStationList(); + const { navigate } = useNavigation(); + return ( + + + { + navigate("positions", { screen: "Apps" }); + const script = getInjectJavascriptAddress(station.StationNumber); + inject(script); + }} + /> - ); - }; \ No newline at end of file + + + 次の列車 + + Next Train + + + {currentTrainLoading == "loading" ? ( + + ) : currentTrainLoading == "error" ? ( + { + setCurrentTrainLoading("loading"); + getCurrentTrain(); + }} + /> + ) : null} + + + ); +}; diff --git a/components/発車時刻表/LED_vidion.js b/components/発車時刻表/LED_vidion.js index 14502fd..96d297b 100644 --- a/components/発車時刻表/LED_vidion.js +++ b/components/発車時刻表/LED_vidion.js @@ -222,7 +222,7 @@ export default function LED_vision(props) { marginHorizontal: width * 0.01, }} > -
+
{selectedTrain.map((d) => ( {}, getCurrentTrain: () => {}, + inject: () => {}, }; const CurrentTrainContext = createContext(initialState); From 36ac66df3edf8aa8d6af739ecc3ae900dc86c955 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sat, 5 Jul 2025 16:20:53 +0000 Subject: [PATCH 65/77] =?UTF-8?q?=E3=83=A1=E3=83=8B=E3=83=A5=E3=83=BC?= =?UTF-8?q?=E3=81=AB=E3=81=8A=E6=B0=97=E3=81=AB=E5=85=A5=E3=82=8A=E3=81=8C?= =?UTF-8?q?=E7=84=A1=E3=81=84=E5=A0=B4=E5=90=88=E3=81=AE=E8=A6=81=E7=B4=A0?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Menu/Carousel/CarouselBox.tsx | 51 ++++++++++++++++++++---- menu.js | 3 +- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/components/Menu/Carousel/CarouselBox.tsx b/components/Menu/Carousel/CarouselBox.tsx index 950acec..f126278 100644 --- a/components/Menu/Carousel/CarouselBox.tsx +++ b/components/Menu/Carousel/CarouselBox.tsx @@ -1,7 +1,13 @@ import Sign from "@/components/駅名表/Sign"; import React, { useEffect, useRef, useState } from "react"; import { AS } from "@/storageControl"; -import { useWindowDimensions, View, LayoutAnimation } from "react-native"; +import { + useWindowDimensions, + View, + LayoutAnimation, + TouchableOpacity, + Text, +} from "react-native"; import Carousel, { ICarouselInstance } from "react-native-reanimated-carousel"; import { SheetManager } from "react-native-actions-sheet"; import { StationNumber } from "../StationPagination"; @@ -13,6 +19,7 @@ export const CarouselBox = ({ setListIndex, listIndex, navigate, + stationListMode }) => { const carouselRef = useRef(null); const { height, width } = useWindowDimensions(); @@ -66,12 +73,36 @@ export const CarouselBox = ({ key={item[0].StationNumber} > - + {item[0].StationNumber != "null" ? ( + + ) : ( + + + + {stationListMode == "position" ? "現在地の近くに駅がありません。" : "お気に入りリストがありません。お気に入りの駅を追加しよう!"} + + + + )} ); @@ -80,7 +111,11 @@ export const CarouselBox = ({ 0 + ? listUpStation + : [[{ StationNumber: "null" }]] + } height={(((width / 100) * 80) / 20) * 9 + 10} pagingEnabled={true} snapEnabled={true} diff --git a/menu.js b/menu.js index ac2491e..73df951 100644 --- a/menu.js +++ b/menu.js @@ -312,7 +312,7 @@ export default function Menu(props) { /> )} - {listUpStation.length != 0 && originalStationList.length != 0 && ( + {originalStationList.length != 0 && ( <> {listUpStation[listIndex] && ( From fdea8be0b4ef9ba60ddae60e3664178f817c5c04 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 6 Jul 2025 08:01:57 +0000 Subject: [PATCH 66/77] =?UTF-8?q?=E5=BE=B3=E5=B3=B6=E7=B7=9A=E3=81=AE?= =?UTF-8?q?=E5=BE=B3=E5=B3=B6=E9=A7=85=E3=80=81=E9=98=BF=E6=B3=A2=E6=B1=A0?= =?UTF-8?q?=E7=94=B0=E9=A7=85=E3=81=AE=E5=9C=B0=E7=82=B9=E6=83=85=E5=A0=B1?= =?UTF-8?q?=E3=81=8C=E7=84=A1=E3=81=8B=E3=81=A3=E3=81=9F=E5=95=8F=E9=A1=8C?= =?UTF-8?q?=E3=82=92=E3=83=87=E3=83=BC=E3=82=BF=E3=82=BD=E3=83=BC=E3=82=B9?= =?UTF-8?q?=E5=81=B4=E3=81=AE=E6=94=B9=E5=A4=89=E3=81=A7=E5=AF=BE=E5=87=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/四国旅客鉄道徳島線.json | 46 +++++++++++++++++++++++++ components/Apps/WebView.jsx | 2 +- components/trainMenu.js | 8 ++--- lib/getStationList.ts | 6 +--- 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/assets/四国旅客鉄道徳島線.json b/assets/四国旅客鉄道徳島線.json index fa19f06..92e5e7a 100644 --- a/assets/四国旅客鉄道徳島線.json +++ b/assets/四国旅客鉄道徳島線.json @@ -1,6 +1,29 @@ { "type": "FeatureCollection", "features": [ + { + "properties": { + "name": "阿波池田", + "uri": "https://uedayou.net/jrslod/四国旅客鉄道/土讃線/阿波池田", + "color": "E25885" + }, + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [133.80429, 34.02714], + [133.80515, 34.02656] + ] + } + }, + { + "properties": { + "name": "阿波池田", + "uri": "https://uedayou.net/jrslod/四国旅客鉄道/土讃線/阿波池田" + }, + "type": "Feature", + "geometry": { "type": "Point", "coordinates": [133.80429, 34.02714] } + }, { "properties": { "name": "佃", @@ -561,6 +584,29 @@ "type": "Feature", "geometry": { "type": "Point", "coordinates": [134.53819, 34.08082] } }, + { + "properties": { + "name": "徳島", + "uri": "https://uedayou.net/jrslod/四国旅客鉄道/高徳線/徳島", + "color": "9ACD32" + }, + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [134.55251, 34.07404], + [134.55049, 34.07498] + ] + } + }, + { + "properties": { + "name": "徳島", + "uri": "https://uedayou.net/jrslod/四国旅客鉄道/高徳線/徳島" + }, + "type": "Feature", + "geometry": { "type": "Point", "coordinates": [134.55251, 34.07404] } + }, { "properties": { "name": "徳島線", diff --git a/components/Apps/WebView.jsx b/components/Apps/WebView.jsx index 13d0e13..9cd2c11 100644 --- a/components/Apps/WebView.jsx +++ b/components/Apps/WebView.jsx @@ -139,7 +139,7 @@ export const AppsWebView = ({ openStationACFromEachTrainInfo }) => { if (favoriteStation.length < 1) return () => {}; const string = getInjectJavascriptAddress(favoriteStation[0][0].StationNumber); if (!string) return () => {}; - webview.current?.injectJavaScript(string); + webview?.current.injectJavaScript(string); once = true; }; diff --git a/components/trainMenu.js b/components/trainMenu.js index 746084f..80687a3 100644 --- a/components/trainMenu.js +++ b/components/trainMenu.js @@ -24,7 +24,7 @@ export default function TrainMenu({ style }) { const { originalStationList } = useStationList(); useEffect(() => { const stationPinData = []; - Object.keys(originalStationList).forEach((d, indexBase) => { + Object.keys(lineList_LineWebID).forEach((d, indexBase) => { originalStationList[d].forEach((D, index) => { if (selectedLine && selectedLine != lineList_LineWebID[d]) return; const latlng = [D.lat,D.lng]; @@ -35,14 +35,14 @@ export default function TrainMenu({ style }) { setStationPin(stationPinData); }, [originalStationList, selectedLine]); useLayoutEffect(() => { - mapRef.current.fitToCoordinates( + mapRef?.current.fitToCoordinates( stationPin.map(({ latlng }) => ({ latitude: parseFloat(latlng[0]), longitude: parseFloat(latlng[1]), })), { edgePadding: { top: 80, bottom: 120, left: 50, right: 50 } } // Add margin values here ); - }, [stationPin]); + }, [stationPin,mapRef]); return ( ))} diff --git a/lib/getStationList.ts b/lib/getStationList.ts index 02608df..45d3e17 100644 --- a/lib/getStationList.ts +++ b/lib/getStationList.ts @@ -211,15 +211,11 @@ export const getStationList = async () => { 鳴門線, stationList["日英対応表"] ); - const tokushimaCurrent = addStationPosition( + stationList["徳島線(徳島-阿波池田間)[B]"] = addStationPosition( concatBetweenStations(stationList["徳島線(徳島-阿波池田間)[B]"]), 徳島線, stationList["日英対応表"] ); - stationList["徳島線(徳島-阿波池田間)[B]"] = [ - tokushimaCurrent[tokushimaCurrent.length - 1], - ...tokushimaCurrent, - ]; stationList["徳島線(徳島-阿波池田間)[B]"].pop(); stationList["瀬戸大橋線(児島-宇多津間)[M]"] = [ { From caa4694c94308a0b1d33bb13ce822dc8ced9ea52 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Sun, 6 Jul 2025 11:14:24 +0000 Subject: [PATCH 67/77] =?UTF-8?q?=E6=A4=9C=E7=B4=A2=E3=83=9C=E3=82=BF?= =?UTF-8?q?=E3=83=B3=E6=9A=AB=E5=AE=9A=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Menu/Carousel/CarouselTypeChanger.tsx | 49 +++++++++--- components/Menu/RailScope/SearchUnitBox.tsx | 76 +++++++++++++++++++ menu.js | 31 +++++++- 3 files changed, 143 insertions(+), 13 deletions(-) create mode 100644 components/Menu/RailScope/SearchUnitBox.tsx diff --git a/components/Menu/Carousel/CarouselTypeChanger.tsx b/components/Menu/Carousel/CarouselTypeChanger.tsx index 11f13af..84767a7 100644 --- a/components/Menu/Carousel/CarouselTypeChanger.tsx +++ b/components/Menu/Carousel/CarouselTypeChanger.tsx @@ -1,13 +1,23 @@ import { AS } from "@/storageControl"; import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs"; import React, { useEffect, useRef } from "react"; -import { View, TouchableOpacity, Text, LayoutAnimation } from "react-native"; +import { useWindowDimensions } from "react-native"; +import { + View, + TouchableOpacity, + Text, + LayoutAnimation, + KeyboardAvoidingView, + Platform, +} from "react-native"; import Ionicons from "react-native-vector-icons/Ionicons"; +import { SearchUnitBox } from "@/components/Menu/RailScope/SearchUnitBox"; export const CarouselTypeChanger = ({ locationStatus, position, mapsRef, + scrollRef, stationListMode, setStationListMode, setSelectedCurrentStation, @@ -15,7 +25,9 @@ export const CarouselTypeChanger = ({ setMapMode, }) => { const tabBarHeight = useBottomTabBarHeight(); - const returnToDefaultMode = ()=>{ + const [isSearchMode, setisSearchMode] = React.useState(false); + const { height, width } = useWindowDimensions(); + const returnToDefaultMode = () => { LayoutAnimation.configureNext({ duration: 300, create: { @@ -28,13 +40,32 @@ export const CarouselTypeChanger = ({ }, }); setMapMode(false); - } + }; return ( - + + { + onPressIn={() => { if (!position) return; returnToDefaultMode(); setStationListMode("position"); @@ -99,7 +129,8 @@ export const CarouselTypeChanger = ({ - + ); }; diff --git a/components/Menu/RailScope/SearchUnitBox.tsx b/components/Menu/RailScope/SearchUnitBox.tsx new file mode 100644 index 0000000..81512c0 --- /dev/null +++ b/components/Menu/RailScope/SearchUnitBox.tsx @@ -0,0 +1,76 @@ +import React from "react"; +import { + TouchableOpacity, + Text, + View, + LayoutAnimation, + TextInput, + KeyboardAvoidingView, + Platform, +} from "react-native"; +import Ionicons from "react-native-vector-icons/Ionicons"; +import { useWindowDimensions } from "react-native"; +export const SearchUnitBox = ({ isSearchMode, setisSearchMode }) => { + const { height, width } = useWindowDimensions(); + return ( + <> + { + LayoutAnimation.configureNext({ + duration: 200, + update: { type: "easeInEaseOut", springDamping: 0.6 }, + }); + setisSearchMode(true); + }} + > + {!isSearchMode && } + {isSearchMode && ( + + { + LayoutAnimation.configureNext({ + duration: 200, + update: { type: "easeInEaseOut", springDamping: 0.6 }, + }); + setisSearchMode(false); + }} + > + あああああああああああああああああああああああああああああああああああああああああああああああああああああああああ + + + setKeyBoardVisible(true)} + onEndEditing={() => {}} + //onChange={(ret) => setInput(ret.nativeEvent.text)} + //value={input} + style={{ flex: 1 }} + /> + + + )} + + + ); +}; diff --git a/menu.js b/menu.js index 73df951..60c57bc 100644 --- a/menu.js +++ b/menu.js @@ -5,6 +5,8 @@ import { ScrollView, useWindowDimensions, LayoutAnimation, + Text, + TouchableOpacity, } from "react-native"; import Constants from "expo-constants"; import { @@ -30,6 +32,8 @@ import { CarouselBox } from "./components/Menu/Carousel/CarouselBox"; import { CarouselTypeChanger } from "./components/Menu/Carousel/CarouselTypeChanger"; import { useUserPosition } from "./stateBox/useUserPosition"; import { AS } from "./storageControl"; +import { Ionicons } from "@expo/vector-icons"; +import { SearchUnitBox } from "./components/Menu/RailScope/SearchUnitBox"; configureReanimatedLogger({ level: ReanimatedLogLevel.error, // Set the log level to error strict: true, // Reanimated runs in strict mode by default @@ -209,13 +213,32 @@ export default function Menu(props) { }} > - + {!mapMode ? ( + + ) : ( + + JRShikoku RailScope + + )} { console.log(e.nativeEvent.velocity); @@ -302,7 +325,7 @@ export default function Menu(props) { {...{ locationStatus, position, - mapsRef, + mapsRef,scrollRef, stationListMode, setStationListMode, setSelectedCurrentStation: setListIndex, @@ -310,7 +333,7 @@ export default function Menu(props) { setMapMode, }} /> - )} + )} {originalStationList.length != 0 && ( <> @@ -322,7 +345,7 @@ export default function Menu(props) { setListIndex, listIndex, navigate, - stationListMode + stationListMode, }} /> {listUpStation[listIndex] && ( From 6b39a3f7233f087024f5e62a64b8b17323e54cd3 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Mon, 7 Jul 2025 10:28:30 +0000 Subject: [PATCH 68/77] =?UTF-8?q?key=E3=81=AE=E5=85=A5=E5=8A=9B=E4=B8=8D?= =?UTF-8?q?=E8=B6=B3=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/trainMenu.js | 1 + 1 file changed, 1 insertion(+) diff --git a/components/trainMenu.js b/components/trainMenu.js index 80687a3..cd416f1 100644 --- a/components/trainMenu.js +++ b/components/trainMenu.js @@ -161,6 +161,7 @@ export default function TrainMenu({ style }) { }); }); }} + key={stationIDPair[d]} > Date: Mon, 7 Jul 2025 11:48:46 +0000 Subject: [PATCH 69/77] =?UTF-8?q?=E3=83=A1=E3=83=8B=E3=83=A5=E3=83=BC?= =?UTF-8?q?=E3=81=AE=E8=B7=AF=E7=B7=9A=E5=88=A5=E3=83=AA=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=82=A2=E3=83=83=E3=83=97=E6=A9=9F=E8=83=BD=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Menu/Carousel/CarouselBox.tsx | 35 +++++- .../Menu/Carousel/CarouselTypeChanger.tsx | 3 +- components/Menu/RailScope/SearchUnitBox.tsx | 106 ++++++++++++------ menu.js | 29 ++++- 4 files changed, 128 insertions(+), 45 deletions(-) diff --git a/components/Menu/Carousel/CarouselBox.tsx b/components/Menu/Carousel/CarouselBox.tsx index f126278..51fbe47 100644 --- a/components/Menu/Carousel/CarouselBox.tsx +++ b/components/Menu/Carousel/CarouselBox.tsx @@ -7,6 +7,7 @@ import { LayoutAnimation, TouchableOpacity, Text, + ScrollView, } from "react-native"; import Carousel, { ICarouselInstance } from "react-native-reanimated-carousel"; import { SheetManager } from "react-native-actions-sheet"; @@ -19,11 +20,22 @@ export const CarouselBox = ({ setListIndex, listIndex, navigate, - stationListMode + stationListMode, }) => { const carouselRef = useRef(null); const { height, width } = useWindowDimensions(); const [dotButton, setDotButton] = useState(false); + const carouselBadgeScrollViewRef = useRef(null); + + useEffect(() => { + if (!carouselBadgeScrollViewRef.current) return; + const scrollToIndex = listIndex * (width / listUpStation.length) + 10; + console.log("scrollToIndex", scrollToIndex); + carouselBadgeScrollViewRef.current.scrollTo({ + x: scrollToIndex, + animated: true, + }); + }, [listIndex, dotButton, width, carouselBadgeScrollViewRef]); const oPSign = () => { const payload = { currentStation: listUpStation[listIndex], @@ -98,7 +110,9 @@ export const CarouselBox = ({ }} > - {stationListMode == "position" ? "現在地の近くに駅がありません。" : "お気に入りリストがありません。お気に入りの駅を追加しよう!"} + {stationListMode == "position" + ? "現在地の近くに駅がありません。" + : "お気に入りリストがありません。お気に入りの駅を追加しよう!"} @@ -131,12 +145,23 @@ export const CarouselBox = ({ onSnapToItem={setListIndex} renderItem={RenderItem} /> - { + // ScrollViewのrefを保存 + if (scrollViewRef) { + carouselBadgeScrollViewRef.current = scrollViewRef; + } }} > {originalStationList && @@ -158,7 +183,7 @@ export const CarouselBox = ({ /> ); })} - + ); }; diff --git a/components/Menu/Carousel/CarouselTypeChanger.tsx b/components/Menu/Carousel/CarouselTypeChanger.tsx index 84767a7..57266ae 100644 --- a/components/Menu/Carousel/CarouselTypeChanger.tsx +++ b/components/Menu/Carousel/CarouselTypeChanger.tsx @@ -23,9 +23,10 @@ export const CarouselTypeChanger = ({ setSelectedCurrentStation, mapMode, setMapMode, + isSearchMode, + setisSearchMode, }) => { const tabBarHeight = useBottomTabBarHeight(); - const [isSearchMode, setisSearchMode] = React.useState(false); const { height, width } = useWindowDimensions(); const returnToDefaultMode = () => { LayoutAnimation.configureNext({ diff --git a/components/Menu/RailScope/SearchUnitBox.tsx b/components/Menu/RailScope/SearchUnitBox.tsx index 81512c0..9d0c1f2 100644 --- a/components/Menu/RailScope/SearchUnitBox.tsx +++ b/components/Menu/RailScope/SearchUnitBox.tsx @@ -10,53 +10,90 @@ import { } from "react-native"; import Ionicons from "react-native-vector-icons/Ionicons"; import { useWindowDimensions } from "react-native"; +import lineColorList from "@/assets/originData/lineColorList"; +import { lineList_LineWebID, stationIDPair } from "@/lib/getStationList"; export const SearchUnitBox = ({ isSearchMode, setisSearchMode }) => { const { height, width } = useWindowDimensions(); return ( <> - { - LayoutAnimation.configureNext({ - duration: 200, - update: { type: "easeInEaseOut", springDamping: 0.6 }, - }); - setisSearchMode(true); - }} - > - {!isSearchMode && } - {isSearchMode && ( + { + LayoutAnimation.configureNext({ + duration: 100, + update: { type: "easeInEaseOut", springDamping: 0.6 }, + }); + setisSearchMode(true); + }} + > + {!isSearchMode && } + {!!isSearchMode && ( - { + + + { LayoutAnimation.configureNext({ - duration: 200, + duration: 100, update: { type: "easeInEaseOut", springDamping: 0.6 }, }); setisSearchMode(false); - }} - > - あああああああああああああああああああああああああああああああああああああああああああああああああああああああああ - - + + + {Object.keys(lineList_LineWebID).map((d) => ( + { + const id = stationIDPair[lineList_LineWebID[d]]; + const s = isSearchMode == id ? undefined : id; + if (!s) return; + setisSearchMode(s); + }} + key={stationIDPair[lineList_LineWebID[d]]} + > + + {stationIDPair[lineList_LineWebID[d]]} + + + ))} + {/* { //value={input} style={{ flex: 1 }} /> + */} - )} - + )} + ); }; diff --git a/menu.js b/menu.js index 60c57bc..14e3a88 100644 --- a/menu.js +++ b/menu.js @@ -19,7 +19,7 @@ import LED_vision from "./components/発車時刻表/LED_vidion"; import { TitleBar } from "./components/Menu/TitleBar"; import { FixedContentBottom } from "./components/Menu/FixedContentBottom"; -import { lineList } from "./lib/getStationList"; +import { lineList, stationIDPair } from "./lib/getStationList"; import { useFavoriteStation } from "./stateBox/useFavoriteStation"; import { useNavigation } from "@react-navigation/native"; import { useStationList } from "./stateBox/useStationList"; @@ -32,6 +32,7 @@ import { CarouselBox } from "./components/Menu/Carousel/CarouselBox"; import { CarouselTypeChanger } from "./components/Menu/Carousel/CarouselTypeChanger"; import { useUserPosition } from "./stateBox/useUserPosition"; import { AS } from "./storageControl"; +import { lineList_LineWebID } from "./lib/getStationList"; import { Ionicons } from "@expo/vector-icons"; import { SearchUnitBox } from "./components/Menu/RailScope/SearchUnitBox"; configureReanimatedLogger({ @@ -171,13 +172,26 @@ export default function Menu(props) { const [listIndex, setListIndex] = useState(0); const [listUpStation, setListUpStation] = useState([]); + const [isSearchMode, setisSearchMode] = useState(false); useEffect(() => { - if (stationListMode == "position") { + if (!!isSearchMode) { + const returnData = []; + Object.keys(lineList_LineWebID).forEach((d, indexBase) => { + originalStationList[d].forEach((D, index) => { + if (isSearchMode && isSearchMode != stationIDPair[lineList_LineWebID[d]]) return; + const latlng = [D.lat, D.lng]; + if (latlng.length == 0) return null; + returnData.push([D]); + }); + }); + setListUpStation(returnData); + } + else if (stationListMode == "position") { setListUpStation(nearPositionStation.filter((d) => d != undefined)); } else { setListUpStation(favoriteStation.filter((d) => d != undefined)); } - }, [nearPositionStation, favoriteStation, stationListMode]); + }, [nearPositionStation, favoriteStation, stationListMode, isSearchMode]); useEffect(() => { if (listUpStation.length == 0) { setListIndex(0); @@ -325,15 +339,18 @@ export default function Menu(props) { {...{ locationStatus, position, - mapsRef,scrollRef, + mapsRef, + scrollRef, stationListMode, setStationListMode, setSelectedCurrentStation: setListIndex, mapMode, setMapMode, + isSearchMode, + setisSearchMode, }} /> - )} + )} {originalStationList.length != 0 && ( <> @@ -373,6 +390,8 @@ export default function Menu(props) { setSelectedCurrentStation: setListIndex, mapMode, setMapMode, + isSearchMode, + setisSearchMode, }} /> )} From 249f09bbc7f1ddd3516ff5f8b52ea7c950b4ee53 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Mon, 7 Jul 2025 11:58:10 +0000 Subject: [PATCH 70/77] =?UTF-8?q?=E7=80=AC=E6=88=B8=E5=A4=A7=E6=A9=8B?= =?UTF-8?q?=E7=B7=9A=E3=81=A7=E8=A1=A8=E7=A4=BA=E3=81=A7=E3=81=8D=E3=81=AA?= =?UTF-8?q?=E3=81=84=E3=83=90=E3=82=B0=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- menu.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/menu.js b/menu.js index 14e3a88..e5c34af 100644 --- a/menu.js +++ b/menu.js @@ -181,6 +181,9 @@ export default function Menu(props) { if (isSearchMode && isSearchMode != stationIDPair[lineList_LineWebID[d]]) return; const latlng = [D.lat, D.lng]; if (latlng.length == 0) return null; + if(D.StationNumber == undefined) { + return null; + } returnData.push([D]); }); }); From 3da4986a7ce92d5743a4a8f215c5f576f0dc1d3d Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Mon, 7 Jul 2025 13:34:13 +0000 Subject: [PATCH 71/77] =?UTF-8?q?=E5=9C=B0=E5=9B=B3=E8=A1=A8=E7=A4=BA?= =?UTF-8?q?=E3=81=AE=E6=8C=99=E5=8B=95=E5=A4=89=E6=9B=B4=E3=80=81=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE=E6=83=85=E5=A0=B1=E3=81=B8=E3=81=AE=E7=A7=BB=E5=8B=95?= =?UTF-8?q?=E3=83=9C=E3=82=BF=E3=83=B3=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EachTrainInfo/LandscapeTrainInfo.js | 2 +- .../EachTrainInfoCore/trainIconStatus.tsx | 2 - .../StationDeteilView.js | 35 ++++++++---- .../StationInsideMapButton.tsx | 1 + .../StationTrainPositionButton.tsx | 54 +++++++++++++++++++ components/Menu/Carousel/CarouselBox.tsx | 3 +- .../FavoliteSettings/FavoiliteSettingsItem.js | 1 - menu.js | 27 +++++++--- stateBox/useCurrentTrain.js | 2 +- stateBox/useStationList.tsx | 1 - 10 files changed, 103 insertions(+), 25 deletions(-) create mode 100644 components/ActionSheetComponents/StationDeteilView/StationTrainPositionButton.tsx diff --git a/components/ActionSheetComponents/EachTrainInfo/LandscapeTrainInfo.js b/components/ActionSheetComponents/EachTrainInfo/LandscapeTrainInfo.js index 8538b65..96b8152 100644 --- a/components/ActionSheetComponents/EachTrainInfo/LandscapeTrainInfo.js +++ b/components/ActionSheetComponents/EachTrainInfo/LandscapeTrainInfo.js @@ -33,7 +33,7 @@ export const LandscapeTrainInfo = (props) => { stickyHeaderIndices={[1]} scrollEventThrottle={16} onScroll={(d) => { - console.log(d.nativeEvent.contentOffset.y); + // Handle scroll events }} > diff --git a/components/ActionSheetComponents/EachTrainInfoCore/trainIconStatus.tsx b/components/ActionSheetComponents/EachTrainInfoCore/trainIconStatus.tsx index 2612f7f..ed642e9 100644 --- a/components/ActionSheetComponents/EachTrainInfoCore/trainIconStatus.tsx +++ b/components/ActionSheetComponents/EachTrainInfoCore/trainIconStatus.tsx @@ -51,7 +51,6 @@ export const TrainIconStatus: FC = ({ data, navigate, from }) => { ) .then((d) => d.json()) .then((d) => { - console.log(d); if (d.trainStatus == "〇") { //setAnpanmanStatus({name:"checkmark-circle-outline",color:"blue"}); } else if (d.trainStatus == "▲") { @@ -76,7 +75,6 @@ export const TrainIconStatus: FC = ({ data, navigate, from }) => { ) .then((d) => d.json()) .then((d) => { - console.log(d); if (d.trainStatus == "〇") { //setAnpanmanStatus({name:"checkmark-circle-outline",color:"blue"}); } else if (d.trainStatus == "▲") { diff --git a/components/ActionSheetComponents/StationDeteilView.js b/components/ActionSheetComponents/StationDeteilView.js index b4a4626..3cfffd2 100644 --- a/components/ActionSheetComponents/StationDeteilView.js +++ b/components/ActionSheetComponents/StationDeteilView.js @@ -18,6 +18,7 @@ import { TrainBusButton } from "./StationDeteilView/TrainBusButton"; import { 駅構内図 } from "./StationDeteilView/StationInsideMapButton"; import { WebSiteButton } from "./StationDeteilView/WebSiteButton"; import { StationTimeTableButton } from "./StationDeteilView/StationTimeTableButton"; +import { StationTrainPositionButton } from "./StationDeteilView/StationTrainPositionButton"; export const StationDeteilView = (props) => { if (!props.payload) return <>; @@ -104,16 +105,23 @@ export const StationDeteilView = (props) => { } /> - {currentStation[0].JrHpUrl && - currentStation[0].StationNumber != "M12" && ( - <駅構内図 //児島例外/ - navigate={navigate} - goTo={goTo} - useShow={useShow} - address={currentStation[0].JrHpUrl} - onExit={onExit} - /> - )} + + + {currentStation[0].JrHpUrl && + currentStation[0].StationNumber != "M12" && ( + <駅構内図 //児島例外/ + navigate={navigate} + goTo={goTo} + useShow={useShow} + address={currentStation[0].JrHpUrl} + onExit={onExit} + /> + )} + {!currentStation[0].JrHpUrl || ( { useShow={useShow} /> )} - + {!trainBus || ( = (props) => { alignContent: "center", alignItems: "center", margin: 2, + flex: 1, }} onPress={() => { navigate("howto", { info, goTo, useShow }); diff --git a/components/ActionSheetComponents/StationDeteilView/StationTrainPositionButton.tsx b/components/ActionSheetComponents/StationDeteilView/StationTrainPositionButton.tsx new file mode 100644 index 0000000..dcc0a84 --- /dev/null +++ b/components/ActionSheetComponents/StationDeteilView/StationTrainPositionButton.tsx @@ -0,0 +1,54 @@ +import { FC } from "react"; +import { TouchableOpacity, View, Text, Linking } from "react-native"; +import { useStationList } from "@/stateBox/useStationList"; +import { useCurrentTrain } from "@/stateBox/useCurrentTrain"; +import AntDesign from "react-native-vector-icons/AntDesign"; +type Props = { + stationNumber: string; + onExit: () => void; + navigate?: (screen: string, params: { screen: string }) => void; +}; +export const StationTrainPositionButton: FC = (props) => { + const { stationNumber, onExit, navigate } = props; + const { + inject, + } = useCurrentTrain(); + const { getInjectJavascriptAddress } = useStationList(); + return ( + { + navigate("positions", { screen: "Apps" }); + const script = getInjectJavascriptAddress(stationNumber); + inject(script); + onExit(); + }} + > + + + + 走行位置に移動 + + + + ); +}; diff --git a/components/Menu/Carousel/CarouselBox.tsx b/components/Menu/Carousel/CarouselBox.tsx index 51fbe47..d093f8e 100644 --- a/components/Menu/Carousel/CarouselBox.tsx +++ b/components/Menu/Carousel/CarouselBox.tsx @@ -29,8 +29,7 @@ export const CarouselBox = ({ useEffect(() => { if (!carouselBadgeScrollViewRef.current) return; - const scrollToIndex = listIndex * (width / listUpStation.length) + 10; - console.log("scrollToIndex", scrollToIndex); + const scrollToIndex = (dotButton ? 28 : 22) * listIndex - (width / 2) + (dotButton ? 28 : 22) - 5; carouselBadgeScrollViewRef.current.scrollTo({ x: scrollToIndex, animated: true, diff --git a/components/Settings/FavoliteSettings/FavoiliteSettingsItem.js b/components/Settings/FavoliteSettings/FavoiliteSettingsItem.js index 51ba766..cdc84f8 100644 --- a/components/Settings/FavoliteSettings/FavoiliteSettingsItem.js +++ b/components/Settings/FavoliteSettings/FavoiliteSettingsItem.js @@ -8,7 +8,6 @@ import { AS } from "../../../storageControl"; export const FavoriteSettingsItem = ({ currentStation }) => { const lineIDs = []; const EachIDs = []; - console.log(currentStation); currentStation.forEach((d) => { if (!d.StationNumber) return; const textArray = d.StationNumber.split(""); diff --git a/menu.js b/menu.js index e5c34af..ff730fc 100644 --- a/menu.js +++ b/menu.js @@ -178,18 +178,30 @@ export default function Menu(props) { const returnData = []; Object.keys(lineList_LineWebID).forEach((d, indexBase) => { originalStationList[d].forEach((D, index) => { - if (isSearchMode && isSearchMode != stationIDPair[lineList_LineWebID[d]]) return; + if ( + isSearchMode && + isSearchMode != stationIDPair[lineList_LineWebID[d]] + ) + return; const latlng = [D.lat, D.lng]; if (latlng.length == 0) return null; - if(D.StationNumber == undefined) { + if (D.StationNumber == undefined) { return null; } returnData.push([D]); }); }); + if (mapMode) { + mapsRef?.current.fitToCoordinates( + listUpStation.map((d) => ({ + latitude: parseFloat(d[0].lat), + longitude: parseFloat(d[0].lng), + })), + { edgePadding: { top: 80, bottom: 120, left: 50, right: 50 } } // Add margin values here + ); + } setListUpStation(returnData); - } - else if (stationListMode == "position") { + } else if (stationListMode == "position") { setListUpStation(nearPositionStation.filter((d) => d != undefined)); } else { setListUpStation(favoriteStation.filter((d) => d != undefined)); @@ -200,12 +212,16 @@ export default function Menu(props) { setListIndex(0); return; } + if (listUpStation.length == 1) { + setListIndex(0); + return; + } if (listUpStation[listIndex] == undefined) { const count = listIndex - 1; setMapMode(false); setListIndex(count); } - }, [listIndex, nearPositionStation, listUpStation]); + }, [listIndex, nearPositionStation, listUpStation, isSearchMode]); useEffect(() => { if (originalStationList == undefined) return; if (listUpStation.length == 0) return; @@ -258,7 +274,6 @@ export default function Menu(props) { }} onScrollBeginDrag={onScrollBeginDrag} onScrollEndDrag={(e) => { - console.log(e.nativeEvent.velocity); if (e.nativeEvent.contentOffset.y < mapHeight - 80) { if (scrollStartPosition > e.nativeEvent.contentOffset.y) { goToMap(); diff --git a/stateBox/useCurrentTrain.js b/stateBox/useCurrentTrain.js index 2d5d8e2..15f6b44 100644 --- a/stateBox/useCurrentTrain.js +++ b/stateBox/useCurrentTrain.js @@ -15,7 +15,7 @@ const initialState = { currentTrainLoading: "loading", setCurrentTrainLoading: () => {}, getCurrentTrain: () => {}, - inject: () => {}, + inject: (i) => {}, }; const CurrentTrainContext = createContext(initialState); diff --git a/stateBox/useStationList.tsx b/stateBox/useStationList.tsx index 4a0d10a..7073735 100644 --- a/stateBox/useStationList.tsx +++ b/stateBox/useStationList.tsx @@ -92,7 +92,6 @@ export const StationListProvider: FC = ({ children }) => { return; } if (x.StationNumber == StationNumber) { - console.log(originalStationList[d]); if (!x.MyStation) findNearStations = true; else bootStationList.push({ line: lineName, station: x }); } From 72e7894725cb4bf73e7e89c89a0fe3980cd19e7f Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Tue, 8 Jul 2025 06:04:18 +0000 Subject: [PATCH 72/77] =?UTF-8?q?=E6=A7=98=E5=AD=90=E3=81=AE=E3=81=8A?= =?UTF-8?q?=E3=81=8B=E3=81=97=E3=81=84=E5=88=97=E8=BB=8A=E3=81=8C=E6=AD=A3?= =?UTF-8?q?=E5=B8=B8=E3=81=AB=E8=A1=A8=E7=A4=BA=E3=81=95=E3=82=8C=E3=81=A6?= =?UTF-8?q?=E3=81=84=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F=E3=83=90=E3=82=B0?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/webViewInjectjavascript.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/webViewInjectjavascript.ts b/lib/webViewInjectjavascript.ts index cc4076b..b9926ec 100644 --- a/lib/webViewInjectjavascript.ts +++ b/lib/webViewInjectjavascript.ts @@ -1440,7 +1440,7 @@ const setStrings = () =>{ var 行き先情報 = element.getElementsByTagName("p")[0]; var 列番データ = element.getAttribute('offclick').split('"')[1]; var 列車名データ = element.getAttribute('offclick').split('"')[3]; - const trainData = trainPositionDatas.find(e => e.TrainNum == 列番データ); + const trainData = trainPositionDatas.filter(e=>!(e.Pos && e.Pos.includes("予告窓"))).find(e => e.TrainNum == 列番データ); const hasProblem = probremsData.find((e)=>{ return e.TrainNum == trainData.TrainNum && e.Pos == trainData.Pos; }); From d586bc562fe805e236d5b13e8c20a3d9974b7632 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Tue, 8 Jul 2025 12:23:29 +0000 Subject: [PATCH 73/77] =?UTF-8?q?=E3=82=AB=E3=83=AB=E3=83=BC=E3=82=BB?= =?UTF-8?q?=E3=83=AB=E3=81=AE=E6=8C=99=E5=8B=95=E3=82=92=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E3=80=81=E3=83=90=E3=83=83=E3=82=B8=E3=81=AE=E3=82=B5=E3=82=A4?= =?UTF-8?q?=E3=82=BA=E3=81=A8=E3=82=B9=E3=82=AF=E3=83=AD=E3=83=BC=E3=83=AB?= =?UTF-8?q?=E3=81=AE=E8=AA=BF=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Menu/Carousel/CarouselBox.tsx | 13 ++--- menu.js | 66 +++++++++++++----------- 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/components/Menu/Carousel/CarouselBox.tsx b/components/Menu/Carousel/CarouselBox.tsx index d093f8e..680addf 100644 --- a/components/Menu/Carousel/CarouselBox.tsx +++ b/components/Menu/Carousel/CarouselBox.tsx @@ -29,7 +29,8 @@ export const CarouselBox = ({ useEffect(() => { if (!carouselBadgeScrollViewRef.current) return; - const scrollToIndex = (dotButton ? 28 : 22) * listIndex - (width / 2) + (dotButton ? 28 : 22) - 5; + const dotSize = dotButton ? 28 : 24; + const scrollToIndex = dotSize * listIndex - width / 2 + dotSize - 5; carouselBadgeScrollViewRef.current.scrollTo({ x: scrollToIndex, animated: true, @@ -64,13 +65,6 @@ export const CarouselBox = ({ setDotButton(data === "true"); }); }, []); - useEffect(() => { - if (!carouselRef.current) return; - carouselRef?.current.scrollTo({ - count: listIndex - carouselRef.current.getCurrentIndex(), - animated: true, - }); - }, [listIndex]); const RenderItem = ({ item, index }) => { return ( = listUpStation.length ? 0 : listIndex} /> { + useLayoutEffect(() => { if (!!isSearchMode) { const returnData = []; Object.keys(lineList_LineWebID).forEach((d, indexBase) => { @@ -191,20 +191,16 @@ export default function Menu(props) { returnData.push([D]); }); }); - if (mapMode) { - mapsRef?.current.fitToCoordinates( - listUpStation.map((d) => ({ - latitude: parseFloat(d[0].lat), - longitude: parseFloat(d[0].lng), - })), - { edgePadding: { top: 80, bottom: 120, left: 50, right: 50 } } // Add margin values here - ); - } + if (JSON.stringify(returnData) == JSON.stringify(listUpStation)) return; setListUpStation(returnData); } else if (stationListMode == "position") { - setListUpStation(nearPositionStation.filter((d) => d != undefined)); + const returnData = nearPositionStation.filter((d) => d != undefined); + if (JSON.stringify(returnData) == JSON.stringify(listUpStation)) return; + setListUpStation(returnData); } else { - setListUpStation(favoriteStation.filter((d) => d != undefined)); + const returnData = favoriteStation.filter((d) => d != undefined); + if (JSON.stringify(returnData) == JSON.stringify(listUpStation)) return; + setListUpStation(returnData); } }, [nearPositionStation, favoriteStation, stationListMode, isSearchMode]); useEffect(() => { @@ -221,7 +217,7 @@ export default function Menu(props) { setMapMode(false); setListIndex(count); } - }, [listIndex, nearPositionStation, listUpStation, isSearchMode]); + }, [listIndex, listUpStation, isSearchMode]); useEffect(() => { if (originalStationList == undefined) return; if (listUpStation.length == 0) return; @@ -233,9 +229,18 @@ export default function Menu(props) { latitudeDelta: 0.05, longitudeDelta: 0.05, }; - if (mapMode) return; - mapsRef.current.animateToRegion(mapRegion, 1000); - }, [listIndex, nearPositionStation, listUpStation, mapsRef]); + if (mapMode) { + mapsRef?.current.fitToCoordinates( + listUpStation.map((d) => ({ + latitude: parseFloat(d[0].lat), + longitude: parseFloat(d[0].lng), + })), + { edgePadding: { top: 80, bottom: 120, left: 50, right: 50 } } // Add margin values here + ); + } else { + mapsRef.current.animateToRegion(mapRegion, 1000); + } + }, [listIndex, listUpStation]); return ( ) : ( - - JRShikoku RailScope - + <> + // + // JRShikoku RailScope + // )} Date: Tue, 8 Jul 2025 13:28:00 +0000 Subject: [PATCH 74/77] =?UTF-8?q?=E8=B5=B0=E8=A1=8C=E4=BD=8D=E7=BD=AE?= =?UTF-8?q?=E3=81=AEUI=E3=81=AB=E7=A8=AE=E5=88=A5=E3=82=84=E5=86=85?= =?UTF-8?q?=E5=AD=90=E7=B5=8C=E7=94=B1=E3=81=AE=E3=83=A9=E3=82=A4=E3=83=B3?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0=E3=80=81=E5=AF=9D=E5=8F=B0=E7=89=B9?= =?UTF-8?q?=E6=80=A5=E3=82=92=E3=83=94=E3=83=B3=E3=82=AF=E3=81=AB=E5=A4=89?= =?UTF-8?q?=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/getTrainType.ts | 4 +-- lib/webViewInjectjavascript.ts | 53 ++++++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/lib/getTrainType.ts b/lib/getTrainType.ts index 5dda2d3..151630c 100644 --- a/lib/getTrainType.ts +++ b/lib/getTrainType.ts @@ -5,7 +5,7 @@ type nameString = | "SPCL" | "Normal" | string; -type colorString = "aqua" | "red" | "#297bff" | "white"; +type colorString = "aqua" | "red" | "#297bff" | "white" | "pink"; type trainTypeString = | "快速" | "特急" @@ -28,7 +28,7 @@ export const getTrainType: getTrainType = (nameString) => { case "LTDEXP": return { color: "red", name: "特急", data: "express" }; case "NightLTDEXP": - return { color: "red", name: "寝台特急", data: "express" }; + return { color: "pink", name: "寝台特急", data: "express" }; case "SPCL": case "SPCL_Rapid": case "SPCL_EXP": diff --git a/lib/webViewInjectjavascript.ts b/lib/webViewInjectjavascript.ts index b9926ec..c0484d7 100644 --- a/lib/webViewInjectjavascript.ts +++ b/lib/webViewInjectjavascript.ts @@ -1055,6 +1055,8 @@ export const injectJavascriptData: InjectJavascriptData = ( const nameReplace = (列車名データ,列番データ,行き先情報,hasProblem) =>{ let isWanman = false; let trainName = ""; + let trainType = ""; + let trainTypeColor = "black"; let viaData = ""; let ToData = ""; let TrainNumber = 列番データ; @@ -1262,7 +1264,43 @@ export const injectJavascriptData: InjectJavascriptData = ( getThrew(列番データ); if(trainDataList.find(e => e.id === 列番データ) !== undefined){ const data = trainDataList.find(e => e.id === 列番データ); - //{id,isWanman,trainName,viaData,ToData} + //{id,isWanman,trainName,viaData,ToData,TrainNumber,JRF,type,infoUrl,trainNumDistance,info,infogram} + trainType = (()=>{ + switch(data.type){ + case "Normal": + trainTypeColor = "black"; + return "普通"; + case "OneMan": + trainTypeColor = "black"; + return "普通"; + case "Freight": + trainTypeColor = "black"; + return "貨物"; + case "SPCL_Normal": + trainTypeColor = "#297bff"; + return "臨時"; + case "SPCL_Rapid": + trainTypeColor = "#297bff"; + return "臨時快速"; + case "SPCL_LTDEXP": + trainTypeColor = "#297bff"; + return "臨時特急"; + case "LTDEXP": + trainTypeColor = "red"; + return "特急"; + case "NightLTDEXP": + trainTypeColor = "rgb(211, 0, 176)"; + return "寝台特急"; + case "OneManRapid": + trainTypeColor = "rgba(0, 140, 255, 1)"; + return "快速"; + case "Rapid": + trainTypeColor = "rgba(0, 140, 255, 1)"; + return "快速"; + default: + return ""; + } + })(); isWanman = data.isWanman; if(data.trainName != ""){ trainName = data.trainName; @@ -1293,16 +1331,25 @@ export const injectJavascriptData: InjectJavascriptData = ( }); let getColors = []; if(stationLines.length === 0){ - getColors = ["#000"]; + getColors = ["rgba(97, 96, 96, 0.81)"]; }else{ getColors = stationLines.map(e => GetLineBarColor(e)); } + let yosan2Color = undefined; + if(viaData == "(内子経由)"){ + yosan2Color ="#F5AC13"; + } + else if(viaData == "(海経由)"){ + yosan2Color = "#9AA7D7"; + } + const gradient = getColors.length > 1 ? "linear-gradient(130deg, " + getColors[0] + " 0%, "+ getColors[0]+"50%, "+ getColors[1]+"50%, " + getColors[1] + " 100%)" : getColors[0]; 行き先情報.insertAdjacentHTML('beforebegin', "

" + TrainNumber + (JRF ? "":"レ") + "

"); 行き先情報.insertAdjacentHTML('beforebegin', "

" + (isWanman ? "ワンマン " : "") + "

"); - 行き先情報.insertAdjacentHTML('beforebegin', "

" + viaData + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + viaData + "

"); 行き先情報.insertAdjacentHTML('beforebegin', "

" + trainName + "

"); 行き先情報.insertAdjacentHTML('beforebegin', "

" + (ToData ? ToData + "行" : ToData) + "

"); + 行き先情報.insertAdjacentHTML('beforebegin', "

" + trainType + "

"); 行き先情報.insertAdjacentHTML('beforebegin', "

" + (hasProblem ? "‼️停止中‼️" : "") + "

"); `: ` 行き先情報.insertAdjacentHTML('beforebegin', "

" + returnText1 + "

"); From 59d7d425e5f52f547ac569aa7874fbd5adbefca1 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Tue, 8 Jul 2025 14:33:19 +0000 Subject: [PATCH 75/77] =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=AB=E3=81=AA?= =?UTF-8?q?=E3=81=A3=E3=81=9F=E3=82=A2=E3=82=A4=E3=82=B3=E3=83=B3=E3=82=92?= =?UTF-8?q?=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LED_Vision_Component/Header.js | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/components/発車時刻表/LED_Vision_Component/Header.js b/components/発車時刻表/LED_Vision_Component/Header.js index dece8e8..5fc696e 100644 --- a/components/発車時刻表/LED_Vision_Component/Header.js +++ b/components/発車時刻表/LED_Vision_Component/Header.js @@ -25,22 +25,6 @@ export const Header = ({ station }) => { }} > - { - navigate("positions", { screen: "Apps" }); - const script = getInjectJavascriptAddress(station.StationNumber); - inject(script); - }} - /> From b512efd3ec1f7d38a2d1a10cb159ad7f34f95818 Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Tue, 8 Jul 2025 16:43:31 +0000 Subject: [PATCH 76/77] ver.6.1 release --- components/Menu/Carousel/CarouselBox.tsx | 3 ++- components/Settings/SettingTopPage.js | 2 +- config/newsUpdate.ts | 2 +- menu.js | 1 + 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/components/Menu/Carousel/CarouselBox.tsx b/components/Menu/Carousel/CarouselBox.tsx index 680addf..0b048fc 100644 --- a/components/Menu/Carousel/CarouselBox.tsx +++ b/components/Menu/Carousel/CarouselBox.tsx @@ -21,6 +21,7 @@ export const CarouselBox = ({ listIndex, navigate, stationListMode, + isSearchMode }) => { const carouselRef = useRef(null); const { height, width } = useWindowDimensions(); @@ -103,7 +104,7 @@ export const CarouselBox = ({ }} > - {stationListMode == "position" + {!!isSearchMode ? "路線検索モードです。上に並んでいる路線を選んでみましょう!" :stationListMode == "position" ? "現在地の近くに駅がありません。" : "お気に入りリストがありません。お気に入りの駅を追加しよう!"} diff --git a/components/Settings/SettingTopPage.js b/components/Settings/SettingTopPage.js index f13913f..52e40f7 100644 --- a/components/Settings/SettingTopPage.js +++ b/components/Settings/SettingTopPage.js @@ -17,7 +17,7 @@ import { SwitchArea } from "../atom/SwitchArea"; import { useNotification } from "../../stateBox/useNotifications"; import { SheetHeaderItem } from "@/components/atom/SheetHeaderItem"; -const versionCode = "6.0.2"; +const versionCode = "6.1.0"; // Update this version code as needed export const SettingTopPage = ({ testNFC, diff --git a/config/newsUpdate.ts b/config/newsUpdate.ts index 04902c9..c3e61f4 100644 --- a/config/newsUpdate.ts +++ b/config/newsUpdate.ts @@ -1 +1 @@ -export const news = "2025-03-06"; +export const news = "2025-07-09"; diff --git a/menu.js b/menu.js index 3f492ba..bc51c70 100644 --- a/menu.js +++ b/menu.js @@ -387,6 +387,7 @@ export default function Menu(props) { listIndex, navigate, stationListMode, + isSearchMode }} /> {listUpStation[listIndex] && ( From 8a7285bb20c76d6e99cafd96193957829906f9ac Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Tue, 8 Jul 2025 16:44:05 +0000 Subject: [PATCH 77/77] =?UTF-8?q?=E8=A9=A6=E9=A8=93=E6=99=82=E3=81=AEbuild?= =?UTF-8?q?=E8=A8=AD=E5=AE=9A=E6=9B=B4=E6=96=B0=E3=82=92=E9=81=A9=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app.json b/app.json index c30ea2f..347f5f0 100644 --- a/app.json +++ b/app.json @@ -7,7 +7,7 @@ "android", "web" ], - "version": "6.0.1", + "version": "6.0.2", "orientation": "default", "icon": "./assets/icons/s8600.png", "splash": { @@ -22,7 +22,7 @@ "**/*" ], "ios": { - "buildNumber": "47", + "buildNumber": "48", "supportsTablet": false, "bundleIdentifier": "jrshikokuinfo.xprocess.hrkn", "config": {