diff --git a/App.js b/App.js index 6ba4a20..1b954ea 100644 --- a/App.js +++ b/App.js @@ -19,6 +19,7 @@ import "./components/ActionSheetComponents/sheets.js"; import { TrainDelayDataProvider } from "./stateBox/useTrainDelayData.js"; import { SafeAreaProvider } from "react-native-safe-area-context"; import { DeviceOrientationChangeProvider } from "./stateBox/useDeviceOrientationChange.js"; +import { TrainMenuProvider } from "./stateBox/useTrainMenu.js"; LogBox.ignoreLogs([ "ViewPropTypes will be removed", "ColorPropType will be removed", @@ -42,9 +43,11 @@ export default function App() { - - - + + + + + @@ -63,6 +66,8 @@ export function AppContainer() { {}; + const { + setSelectedLine, + setInjectJavaScript, + mapsStationData: stationData, + } = useTrainMenu(); //画面表示関連 const [iconSetting, setIconSetting] = useState(undefined); @@ -164,6 +171,13 @@ export default function Apps({ stationData }) { }); return; } + case "currentLines": { + const lineInfo = dataSet.currentLines.split("\n")[0]; + const lineID = stationNamePair[lineInfo]; + + setSelectedLine(lineID); + return; + } default: { return; } @@ -322,7 +336,10 @@ export default function Apps({ stationData }) { )} {isLandscape || ( navigate("trainMenu", { webview })} + onPress={() => { + setInjectJavaScript(""); + navigate("trainMenu", { webview }); + }} top={Platform.OS == "ios" ? Constants.statusBarHeight : 0} mapSwitch={mapSwitch == "true" ? "flex" : "none"} /> @@ -467,12 +484,13 @@ const MapsButton = ({ onPress, top, mapSwitch }) => { textAlignVertical: "center", fontWeight: "bold", color: "white", + fontSize: 20, }, }; return ( - + ); diff --git a/Top.js b/Top.js index 76556d5..046b2c0 100644 --- a/Top.js +++ b/Top.js @@ -14,14 +14,16 @@ import { optionData } from "./lib/stackOption.js"; import { useNavigation } from "@react-navigation/native"; import { useCurrentTrain } from "./stateBox/useCurrentTrain.js"; import { AS } from "./storageControl.js"; +import { useTrainMenu } from "./stateBox/useTrainMenu"; const Stack = createStackNavigator(); export const Top = ({ navigationRef }) => { - const { webview, getCurrentTrain } = useCurrentTrain(); + const { webview } = useCurrentTrain(); const navigation = useNavigation(); const { navigate, addListener } = navigation; //地図用 - const [mapsStationData, setMapsStationData] = useState(undefined); + const { setMapsStationData, injectJavaScript, setInjectJavaScript } = + useTrainMenu(); useEffect(() => { getStationList2().then(setMapsStationData); @@ -47,15 +49,22 @@ export const Top = ({ navigationRef }) => { if (navigationRef.current?.getCurrentRoute().name == "Apps") { if (mapSwitch == "true") { navigation.navigate("trainMenu"); + setInjectJavaScript(""); } else { webview.current?.injectJavaScript(`AccordionClassEvent()`); } } else { + if (mapSwitch == "true") { + if (injectJavaScript) { + webview.current?.injectJavaScript(injectJavaScript); + setInjectJavaScript(""); + } + } navigation.navigate("Apps"); } }); return unsubscribe; - }, [navigation, mapSwitch]); + }, [navigation, mapSwitch, injectJavaScript]); return ( @@ -66,7 +75,7 @@ export const Top = ({ navigationRef }) => { gestureEnabled: true, headerTransparent: true, }} - children={() => } + component={Apps} /> { } + component={TrainMenu} /> } + component={FavoriteList} /> ); diff --git a/app.json b/app.json index 7a27a91..faae236 100644 --- a/app.json +++ b/app.json @@ -44,7 +44,7 @@ }, "assetBundlePatterns": ["**/*"], "ios": { - "buildNumber": "33", + "buildNumber": "34", "supportsTablet": true, "bundleIdentifier": "jrshikokuinfo.xprocess.hrkn", "config": { diff --git a/assets/reccha-small.png b/assets/reccha-small.png new file mode 100644 index 0000000..9944706 Binary files /dev/null and b/assets/reccha-small.png differ diff --git a/assets/reccha.png b/assets/reccha.png new file mode 100644 index 0000000..b7bf2e5 Binary files /dev/null and b/assets/reccha.png differ diff --git a/components/ActionSheetComponents/EachTrainInfo/StateBox.js b/components/ActionSheetComponents/EachTrainInfo/StateBox.js index c26f41b..3258cc0 100644 --- a/components/ActionSheetComponents/EachTrainInfo/StateBox.js +++ b/components/ActionSheetComponents/EachTrainInfo/StateBox.js @@ -17,7 +17,9 @@ export const StateBox = ({ text, title, style, mode }) => ( {text.split("~")[0]} - + + {mode == 2 ? "→" : "↓"} + {text.split("~")[1]} diff --git a/components/ActionSheetComponents/EachTrainInfo/TrainDataView.js b/components/ActionSheetComponents/EachTrainInfo/TrainDataView.js index 3595cda..6b84549 100644 --- a/components/ActionSheetComponents/EachTrainInfo/TrainDataView.js +++ b/components/ActionSheetComponents/EachTrainInfo/TrainDataView.js @@ -17,7 +17,7 @@ export const TrainDataView = ({ }) => { const { width, height } = useWindowDimensions(); const { isLandscape } = useDeviceOrientationChange(); - const { webview, getCurrentTrain } = useCurrentTrain(); + const { webview, getCurrentTrain, inject } = useCurrentTrain(); const [mapsStationData, setMapsStationData] = useState(undefined); useEffect(() => { getStationList2().then(setMapsStationData); @@ -51,10 +51,10 @@ export const TrainDataView = ({ } }); if (!test.length) return; - webview.current?.injectJavaScript( - `MoveDisplayStation('${test[0].line}_${test[0].station.MyStation}_${test[0].station.Station_JP}');setStrings();` - ); navigate("Apps"); + inject( + `MoveDisplayStation('${test[0].line}_${test[0].station.MyStation}_${test[0].station.Station_JP}');document.getElementById("disp").insertAdjacentHTML("afterbegin", "
");` + ); SheetManager.hide("EachTrainInfo"); }} > @@ -66,11 +66,11 @@ export const TrainDataView = ({ ? `${ currentTrainData?.Pos.replace("(下り)", "") .replace("(上り)", "") - .split("~")[0] + .split("~")[currentTrainData?.Direction == 1 ? 0 : 1] }~${ currentTrainData?.Pos.replace("(下り)", "") .replace("(上り)", "") - .split("~")[1] + .split("~")[currentTrainData?.Direction == 1 ? 1 : 0] }` : currentTrainData?.Pos } diff --git a/components/ActionSheetComponents/EachTrainInfoCore.js b/components/ActionSheetComponents/EachTrainInfoCore.js index 0b99ec1..828e66e 100644 --- a/components/ActionSheetComponents/EachTrainInfoCore.js +++ b/components/ActionSheetComponents/EachTrainInfoCore.js @@ -7,6 +7,7 @@ import { StyleSheet, useWindowDimensions, BackHandler, + Linking, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { SheetManager } from "react-native-actions-sheet"; @@ -25,7 +26,7 @@ import { DynamicHeaderScrollView } from "../DynamicHeaderScrollView"; import { LongHeader } from "./EachTrainInfo/LongHeader"; import { ShortHeader } from "./EachTrainInfo/ShortHeader"; import { ScrollStickyContent } from "./EachTrainInfo/ScrollStickyContent"; -import { getStationData } from "../../lib/eachTrainInfoCoreLib/getStationData"; +import { getStationID } from "../../lib/eachTrainInfoCoreLib/getStationData"; import { findReversalPoints } from "../../lib/eachTrainInfoCoreLib/findReversalPoints"; import { migrateTrainName } from "../../lib/eachTrainInfoCoreLib/migrateTrainName"; import { getType } from "../../lib/eachTrainInfoCoreLib/getType"; @@ -193,12 +194,20 @@ export const EachTrainInfoCore = ({ const pos = currentTrainData?.Pos.replace("(下り)", "") .replace("(上り)", "") .split("~"); - setCurrentPosition([ - getStationData(pos[0], stationList), - getStationData(pos[1], stationList), - ]); + const direction = parseInt(currentTrainData?.Direction) || 0; + if (direction == 0) { + setCurrentPosition([ + getStationID(pos[1], stationList), + getStationID(pos[0], stationList), + ]); + } else { + setCurrentPosition([ + getStationID(pos[0], stationList), + getStationID(pos[1], stationList), + ]); + } } else { - setCurrentPosition([getStationData(currentTrainData?.Pos, stationList)]); + setCurrentPosition([getStationID(currentTrainData?.Pos, stationList)]); } }, [currentTrainData]); @@ -235,12 +244,18 @@ export const EachTrainInfoCore = ({ } else { SheetManager.hide("EachTrainInfo").then(() => { //0.1秒待機してから開く - setTimeout(() => { - SheetManager.show("EachTrainInfo", { payload }); - }, 2); + setTimeout(() => SheetManager.show("EachTrainInfo", { payload }), 2); }); } }; + + const headerItem = { + currentTrainData, + currentPosition, + nearTrainIDList, + openTrainInfo, + navigate, + }; return ( - } - longHeader={ - - } + shortHeader={} + longHeader={} topStickyContent={ } @@ -361,6 +360,26 @@ export const EachTrainInfoCore = ({ trainList={trainList} trueTrainID={trueTrainID} /> + {!trainData.length && ( + + Linking.openURL(`https://twitter.com/search?q=${data.trainNum}`) + } + style={{ + padding: 10, + flexDirection: "row", + borderColor: "blue", + borderWidth: 1, + margin: 10, + borderRadius: 5, + alignItems: "center", + }} + > + + Twitterで検索 + + + )} {trainData.map((i, index) => i.split(",")[1] == "提" ? ( @@ -376,11 +395,11 @@ export const EachTrainInfoCore = ({ ) )} {tailStation.length != 0 && - tailStation.map((i, index) => + tailStation.map(({ station, dia }, index) => showTailStation.findIndex((d) => d == index) == -1 ? ( { - const array = openBackTrainInfo(i.station, trainData, i.dia); + const array = openBackTrainInfo(station, trainData, dia); if (!array) return; setTrainData(array); diff --git a/components/ActionSheetComponents/StationDeteilView.js b/components/ActionSheetComponents/StationDeteilView.js index 686b0c4..91cdf49 100644 --- a/components/ActionSheetComponents/StationDeteilView.js +++ b/components/ActionSheetComponents/StationDeteilView.js @@ -262,9 +262,9 @@ const NexPreStationLine = ({ currentStation, originalStationList }) => { "土讃線(多度津-高知間)[D]", "土讃線(高知-窪川間)[K]", "高徳線(高松-徳島間)[T]", - "徳島線(徳島-阿波池田)[B]", + "徳島線(徳島-阿波池田間)[B]", "鳴門線(池谷-鳴門間)[N]", - "瀬戸大橋線(宇多津-児島間)[M]", + "瀬戸大橋線(児島-宇多津間)[M]", ]; let returnData; lineList.forEach((d) => { diff --git a/components/ActionSheetComponents/TrainMenuLineSelector.js b/components/ActionSheetComponents/TrainMenuLineSelector.js new file mode 100644 index 0000000..c983da4 --- /dev/null +++ b/components/ActionSheetComponents/TrainMenuLineSelector.js @@ -0,0 +1,138 @@ +import React, { useEffect, useRef } from "react"; +import { + View, + LayoutAnimation, + ScrollView, + Linking, + Text, + TouchableOpacity, + Platform, + BackHandler, +} from "react-native"; +import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons"; +import ActionSheet, { + SheetManager, + useScrollHandlers, +} from "react-native-actions-sheet"; +import LottieView from "lottie-react-native"; +import { useSafeAreaInsets } from "react-native-safe-area-context"; +import ViewShot from "react-native-view-shot"; +import * as Sharing from "expo-sharing"; +import { useTrainDelayData } from "../../stateBox/useTrainDelayData"; +import { useTrainMenu } from "../../stateBox/useTrainMenu"; +import lineColorList from "../../assets/originData/lineColorList"; +import { stationIDPair } from "../../lib/getStationList2"; +import { lineListPair } from "../../lib/getStationList"; + +export const TrainMenuLineSelector = () => { + const { getTime, delayData, loadingDelayData, setLoadingDelayData } = + useTrainDelayData(); + const { + selectedLine, + setSelectedLine, + mapsStationData: stationData, + setMapsStationData, + } = useTrainMenu(); + const actionSheetRef = useRef(null); + const scrollHandlers = useScrollHandlers("scrollview-1", actionSheetRef); + const insets = useSafeAreaInsets(); + const viewShot = useRef(null); + const platformIs = Platform.OS == "android"; + return ( + } + ref={actionSheetRef} + isModal={Platform.OS == "ios"} + containerStyle={platformIs ? { paddingBottom: insets.bottom } : {}} + useBottomSafeAreaPadding={platformIs} + > + + + + + {Object.keys(stationData).map((d) => ( + { + SheetManager.hide("TrainMenuLineSelector"); + setSelectedLine(selectedLine == d ? undefined : d); + }} + > + + + + + {stationIDPair[d]} + + + + + + + + {lineListPair[stationIDPair[d]]} + + + + + ))} + + ); +}; +const Handler = () => { + useEffect(() => { + const backAction = () => { + SheetManager.hide("TrainMenuLineSelector"); + return true; + }; + const backHandler = BackHandler.addEventListener( + "hardwareBackPress", + backAction + ); + return () => backHandler.remove(); + }, []); + return <>; +}; diff --git a/components/ActionSheetComponents/sheets.js b/components/ActionSheetComponents/sheets.js index da95b04..eaa7427 100644 --- a/components/ActionSheetComponents/sheets.js +++ b/components/ActionSheetComponents/sheets.js @@ -2,9 +2,11 @@ import { registerSheet } from "react-native-actions-sheet"; import { EachTrainInfo } from "./EachTrainInfo"; import { JRSTraInfo } from "./JRSTraInfo"; import { StationDeteilView } from "./StationDeteilView"; +import { TrainMenuLineSelector } from "./TrainMenuLineSelector"; registerSheet("EachTrainInfo", EachTrainInfo); registerSheet("JRSTraInfo", JRSTraInfo); registerSheet("StationDetailView", StationDeteilView); +registerSheet("TrainMenuLineSelector", TrainMenuLineSelector); export {}; diff --git a/components/AndroidWidget/InfoWidget.jsx b/components/AndroidWidget/InfoWidget.jsx new file mode 100644 index 0000000..db3a556 --- /dev/null +++ b/components/AndroidWidget/InfoWidget.jsx @@ -0,0 +1,112 @@ +import React from "react"; +import { + FlexWidget, + TextWidget, + ListWidget, +} from "react-native-android-widget"; +import dayjs from "dayjs"; +import { ToastAndroid } from "react-native"; + +export const getInfoString = async () => { + // Fetch data from the server + const time = dayjs().format("HH:mm"); + const text = await fetch( + "https://script.google.com/macros/s/AKfycbz80LcaEUrhnlEsLkJy0LG2IRO3DBVQhfNmN1d_0f_HvtsujNQpxM90SrV9yKWH_JG1Ww/exec" + ) + .then((response) => response.text()) + .then((data) => { + if (data !== "") { + return data.split("^"); + } + return null; + }); + ToastAndroid.show(`${text}`, ToastAndroid.SHORT); + return { time, text }; +}; + +export function InfoWidget({ time, text }) { + return ( + + + + + + + + {text ? ( + + ) : ( + + )} + + + ); +} + +const FlexText = ({ flex, text }) => ( + + + +); diff --git a/components/AndroidWidget/TraInfoEXWidget.jsx b/components/AndroidWidget/TraInfoEXWidget.jsx index d55cb43..3cfc161 100644 --- a/components/AndroidWidget/TraInfoEXWidget.jsx +++ b/components/AndroidWidget/TraInfoEXWidget.jsx @@ -4,7 +4,25 @@ import { TextWidget, ListWidget, } from "react-native-android-widget"; +import dayjs from "dayjs"; +import { ToastAndroid } from "react-native"; +export const getDelayData = async () => { + // Fetch data from the server + const time = dayjs().format("HH:mm"); + const delayString = await fetch( + "https://script.google.com/macros/s/AKfycbyKxch7z7l8e07LXulRHqxjVoIiB13kcgvoToLE-rqlxLmLSKdlmqz0FI1F2EuA7Zfg/exec" + ) + .then((response) => response.text()) + .then((data) => { + if (data !== "") { + return data.split("^"); + } + return null; + }); + ToastAndroid.show(`${delayString}`, ToastAndroid.SHORT); + return { time, delayString }; +}; export function TraInfoEXWidget({ time, delayString }) { return ( { - // Fetch data from the server - const time = dayjs().format("HH:mm"); - const delayString = await fetch( - "https://script.google.com/macros/s/AKfycbyKxch7z7l8e07LXulRHqxjVoIiB13kcgvoToLE-rqlxLmLSKdlmqz0FI1F2EuA7Zfg/exec" - ) - .then((response) => response.text()) - .then((data) => { - if (data !== "") { - return data.split("^"); - } - return null; - }); - ToastAndroid.show(`${delayString}`, ToastAndroid.SHORT); - return { time, delayString }; -}; export async function widgetTaskHandler(props) { - const widgetInfo = props.widgetInfo; - const Widget = nameToWidget[widgetInfo.widgetName]; + const { + widgetInfo, + widgetAction, + renderWidget, + clickAction, + clickActionData, + } = props; + const WidgetName = await AS.getItem( + `widgetType/${widgetInfo.widgetId}` + ).catch((e) => "JR_shikoku_train_info"); ToastAndroid.show( - `Widget Action: ${JSON.stringify(props.widgetInfo.widgetId)}`, + `Widget Action: ${JSON.stringify(widgetInfo.widgetId)}`, ToastAndroid.SHORT ); - const { time, delayString } = await getDelayData(); - switch (props.widgetAction) { + ToastAndroid.show(`Widget Name: ${WidgetName}`, ToastAndroid.SHORT); + switch (widgetAction) { case "WIDGET_ADDED": case "WIDGET_UPDATE": case "WIDGET_CLICK": case "WIDGET_RESIZED": - // Not needed for now - props.renderWidget(); + switch (WidgetName) { + case "Info_Widget": { + const { time, text } = await getInfoString(); + renderWidget( + + ); + break; + } + case "JR_shikoku_train_info": + default: { + const { time, delayString } = await getDelayData(); + renderWidget( + + ); + break; + } + } break; case "WIDGET_DELETED": - // Not needed for now + AS.removeItem(`widgetType/${widgetInfo.widgetId}`); break; default: break; diff --git a/components/FavoriteList.js b/components/FavoriteList.js index 1d1a054..e46b613 100644 --- a/components/FavoriteList.js +++ b/components/FavoriteList.js @@ -5,11 +5,13 @@ import Icon from "react-native-vector-icons/Entypo"; import { useFavoriteStation } from "../stateBox/useFavoriteStation"; import { useCurrentTrain } from "../stateBox/useCurrentTrain"; import { useNavigation } from "@react-navigation/native"; +import { useTrainMenu } from "../stateBox/useTrainMenu"; import { FavoriteListItem } from "./atom/FavoriteListItem"; -export default function FavoriteList({ stationData }) { +export default function FavoriteList() { const { favoriteStation } = useFavoriteStation(); const { webview } = useCurrentTrain(); const { navigate, goBack } = useNavigation(); + const { mapsStationData: stationData } = useTrainMenu(); return ( @@ -45,7 +47,7 @@ export default function FavoriteList({ stationData }) { webview.current?.injectJavaScript( `MoveDisplayStation('${lineName}_${currentStation[0].MyStation}_${currentStation[0].Station_JP}'); - setStrings();` + document.getElementById("disp").insertAdjacentHTML("afterbegin", "
");` ); navigate("Apps"); }} diff --git a/components/Settings/SettingTopPage.js b/components/Settings/SettingTopPage.js index 8ebd75a..3b540d8 100644 --- a/components/Settings/SettingTopPage.js +++ b/components/Settings/SettingTopPage.js @@ -12,7 +12,7 @@ import * as Updates from "expo-updates"; import { useWindowDimensions } from "react-native"; import { ListItem } from "native-base"; -const versionCode = "5.2"; +const versionCode = "5.3"; export const SettingTopPage = ({ navigate, testNFC, updateAndReload }) => { const { width } = useWindowDimensions(); diff --git a/components/Settings/WidgetSettings.js b/components/Settings/WidgetSettings.js index 5b08b0c..b58e4c5 100644 --- a/components/Settings/WidgetSettings.js +++ b/components/Settings/WidgetSettings.js @@ -4,38 +4,38 @@ import { SwitchArea } from "../atom/SwitchArea"; import { CheckBox } from "react-native-elements"; import { TripleSwitchArea } from "../atom/TripleSwitchArea"; import { getWidgetInfo, WidgetPreview } from "react-native-android-widget"; -import { TraInfoEXWidget } from "../AndroidWidget/TraInfoEXWidget"; -import { - getDelayData, - nameToWidget, -} from "../AndroidWidget/widget-task-handler"; +import { getDelayData } from "../AndroidWidget/TraInfoEXWidget"; +import { getInfoString } from "../AndroidWidget/InfoWidget"; +import { AS } from "../../storageControl"; +import { nameToWidget } from "../AndroidWidget/widget-task-handler"; import { ListItem } from "native-base"; export const WidgetSettings = ({ navigate }) => { + const { JR_shikoku_train_info, Info_Widget } = nameToWidget; + const [time, setTime] = useState(); + const [delayString, setDelayString] = useState(); + const [trainInfo, setTrainInfo] = useState(); const [widgetList, setWidgetList] = useState([]); - useEffect(() => { + const reload = async () => { const d = []; - Object.keys(nameToWidget).forEach((element) => { - const widgetInfo = getWidgetInfo(element); - widgetInfo.then((s) => { - if (s.length > 0) { - s.forEach((elem) => { - console.log(elem); - d.push(elem); - }); - } - }); + const data = await getWidgetInfo("JR_shikoku_train_info"); + data.forEach((elem) => { + d.push(elem.widgetId); }); setWidgetList(d); - }, []); + }; + + useEffect(reload, []); - const [time, setTime] = useState(time); - const [delayString, setDelayString] = useState(delayString); useEffect(() => { getDelayData().then(({ time, delayString }) => { setTime(time); setDelayString(delayString); }); + getInfoString().then(({ time, text }) => { + setTime(time); + setTrainInfo(text.toString()); + }); }, []); return ( @@ -90,18 +90,29 @@ export const WidgetSettings = ({ navigate }) => { margin: 10, }} > - {Object.keys(nameToWidget).map((Name) => { - const Data = nameToWidget[Name]; - return ( - ( - - )} - width={400} - height={250} - /> - ); - })} + ( + + )} + width={400} + height={250} + /> + + + } + width={400} + height={250} + /> @@ -129,32 +140,8 @@ export const WidgetSettings = ({ navigate }) => { 名前 - {widgetList.map((widget) => ( - - - {widget.widgetId} - - - {widget.widgetName} - - + {widgetList.map((id) => ( + ))} ( /> ); +const WidgetList = ({ id }) => { + const [widgetConfig, setWidgetConfig] = useState(""); + const reload = () => { + AS.getItem(`widgetType/${id}`) + .then((widgetType) => { + setWidgetConfig(widgetType); + }) + .catch((e) => { + setWidgetConfig("JR_shikoku_train_info"); + }); + }; + useEffect(reload, [id]); + return ( + { + //widget.widgetNameで定義されてないもう一つのウィジェットを選択する + if (widgetConfig === "Info_Widget") { + AS.setItem(`widgetType/${id}`, "JR_shikoku_train_info"); + } else { + AS.setItem(`widgetType/${id}`, "Info_Widget"); + } + reload(); + }} + > + + {id} + + + {widgetConfig} + + + ); +}; diff --git a/components/trainMenu.js b/components/trainMenu.js index ebba80f..e95df18 100644 --- a/components/trainMenu.js +++ b/components/trainMenu.js @@ -1,21 +1,30 @@ import React, { useRef, useState, useEffect } from "react"; -import { View, Text, TouchableOpacity, Linking } from "react-native"; +import { View, Text, TouchableOpacity, Linking, Platform } from "react-native"; import MapView, { Marker } from "react-native-maps"; -import { MaterialCommunityIcons } from "@expo/vector-icons"; +import Constants from "expo-constants"; +import { MaterialCommunityIcons, Ionicons } from "@expo/vector-icons"; import { useCurrentTrain } from "../stateBox/useCurrentTrain"; import { useNavigation } from "@react-navigation/native"; import lineColorList from "../assets/originData/lineColorList"; import { stationIDPair } from "../lib/getStationList2"; import { lineListPair } from "../lib/getStationList"; -export default function TrainMenu({ stationData, style }) { +import { SheetManager } from "react-native-actions-sheet"; +import { useTrainMenu } from "../stateBox/useTrainMenu"; +export default function TrainMenu({ style }) { const { webview } = useCurrentTrain(); const mapRef = useRef(); const { navigate } = useNavigation(); const [stationPin, setStationPin] = useState([]); - const [selectedLine, setSelectedLine] = useState(undefined); + const { + selectedLine, + setSelectedLine, + injectJavaScript, + setInjectJavaScript, + mapsStationData: stationData, + } = useTrainMenu(); useEffect(() => { const stationPinData = []; - Object.keys(stationData).map((d, indexBase) => + Object.keys(stationData).map((d, indexBase) => { stationData[d].map((D, index) => { if (!D.StationMap) return null; if (selectedLine && selectedLine != d) return; @@ -24,9 +33,15 @@ export default function TrainMenu({ stationData, style }) { "" ).split(","); if (latlng.length == 0) return null; + if (index == 0 && stationPin.length > 0) { + setInjectJavaScript( + `MoveDisplayStation('${d}_${D.MyStation}_${D.Station_JP}'); + document.getElementById("disp").insertAdjacentHTML("afterbegin", "
");` + ); + } stationPinData.push({ D, d, latlng, indexBase: 0, index }); - }) - ); + }); + }); setStationPin(stationPinData); }, [stationData, selectedLine]); useEffect(() => { @@ -35,37 +50,11 @@ export default function TrainMenu({ stationData, style }) { latitude: parseFloat(latlng[0]), longitude: parseFloat(latlng[1]), })), - { edgePadding: { top: 100, bottom: 50, left: 50, right: 50 } } // Add margin values here + { edgePadding: { top: 80, bottom: 120, left: 50, right: 50 } } // Add margin values here ); }, [stationPin]); return ( - {selectedLine && ( - - - {selectedLine ? lineListPair[stationIDPair[selectedLine]] : "全線"} - - - )} - + SheetManager.show("TrainMenuLineSelector")} + > + + ▲  ここを押して路線をフィルタリングできます  ▲ + + + {selectedLine + ? lineListPair[stationIDPair[selectedLine]] + : "JR四国 対象全駅"} + + 路線記号からフィルタリング @@ -116,8 +143,12 @@ export default function TrainMenu({ stationData, style }) { padding: 5, margin: 2, borderRadius: 10, + borderColor: "white", + borderWidth: 1, + borderStyle: "solid", alignItems: "center", opacity: selectedLine == d ? 1 : !selectedLine ? 1 : 0.5, + zIndex: 10, }} onPress={() => setSelectedLine(selectedLine == d ? undefined : d)} > @@ -166,26 +197,14 @@ export default function TrainMenu({ stationData, style }) { )} - {navigate && ( - navigate("Apps")} - > - - - 閉じる - - - - )} + { + navigate("Apps"); + webview.current?.injectJavaScript(injectJavaScript); + }} + top={0} + mapSwitch={"flex"} + /> ); } @@ -221,10 +240,47 @@ const MapPin = ({ index, indexBase, latlng, D, d, navigate, webview }) => { onPress={() => { webview.current?.injectJavaScript( `MoveDisplayStation('${d}_${D.MyStation}_${D.Station_JP}'); - setStrings();` + document.getElementById("disp").insertAdjacentHTML("afterbegin", "
");` ); if (navigate) navigate("Apps"); }} + image={require("../assets/reccha-small.png")} > ); }; + +const MapsButton = ({ onPress, top, mapSwitch }) => { + const styles = { + touch: { + position: "absolute", + top, + left: 10, + width: 50, + height: 50, + backgroundColor: "#0099CC", + borderColor: "white", + borderStyle: "solid", + borderWidth: 1, + borderRadius: 50, + alignContent: "center", + alignSelf: "center", + alignItems: "center", + display: mapSwitch, + }, + text: { + textAlign: "center", + width: "auto", + height: "auto", + textAlignVertical: "center", + fontWeight: "bold", + color: "white", + }, + }; + return ( + + + + + + ); +}; diff --git a/components/発車時刻表/LED_vidion.js b/components/発車時刻表/LED_vidion.js index e34d69f..aeff31a 100644 --- a/components/発車時刻表/LED_vidion.js +++ b/components/発車時刻表/LED_vidion.js @@ -13,6 +13,7 @@ import { checkDuplicateTrainData } from "../../lib/checkDuplicateTrainData"; import { useCurrentTrain } from "../../stateBox/useCurrentTrain"; import { useAreaInfo } from "../../stateBox/useAreaInfo"; import { SheetManager } from "react-native-actions-sheet"; +import { AS } from "../../storageControl"; /** * @@ -59,6 +60,31 @@ export default function LED_vision(props) { const [trainDescriptionSwitch, setTrainDescriptionSwitch] = useState(false); const { areaInfo } = useAreaInfo(); + useEffect(() => { + AS.getItem("LEDSettings/trainIDSwitch").then((data) => { + console.log(data); + if (data == "true") { + setTrainIDSwitch(true); + } else { + setTrainIDSwitch(false); + } + }); + AS.getItem("LEDSettings/trainDescriptionSwitch").then((data) => { + if (data == "true") { + setTrainDescriptionSwitch(true); + } else { + setTrainDescriptionSwitch(false); + } + }); + AS.getItem("LEDSettings/finalSwitch").then((data) => { + if (data == "true") { + setFinalSwitch(true); + } else { + setFinalSwitch(false); + } + }); + }, []); + useEffect(() => { // 現在の駅に停車するダイヤを作成する副作用[列車ダイヤと現在駅情報] if (!trainDiagram) { @@ -164,14 +190,20 @@ export default function LED_vision(props) { true ); useEffect(() => { - if (!areaInfo) return () => {}; + if (!areaInfo) { + setAreaString(""); + return () => {}; + } setAreaString( areaInfo.substring(move, areaInfo.length) + areaInfo.substring(0, move) ); }, [move]); useEffect(() => { - if (!areaInfo) return () => {}; + if (!areaInfo) { + setAreaStringLength(0); + return () => {}; + } setAreaStringLength(areaInfo.length); }, [areaInfo]); @@ -282,16 +314,31 @@ const Footer = (props) => { return ( 種別名 / 列番 - + { + AS.setItem("LEDSettings/trainIDSwitch", value.toString()); + setTrainIDSwitch(value); + }} + /> 列車情報 { + AS.setItem("LEDSettings/trainDescriptionSwitch", value.toString()); + setTrainDescriptionSwitch(value); + }} /> 当駅止表示 - + { + AS.setItem("LEDSettings/finalSwitch", value.toString()); + setFinalSwitch(value); + }} + /> ); }; @@ -336,10 +383,24 @@ const EachData = ({ setTrain(customTrainDataDetector(d.train)); }, [currentTrain, d.train, trainDescriptionSwitch]); // 土讃線複数存在対策 + const currentTrainData = checkDuplicateTrainData( + currentTrain.filter((a) => a.num == d.train) + ); const trainDelayStatus = getTrainDelayStatus( - checkDuplicateTrainData(currentTrain.filter((a) => a.num == d.train)), + currentTrainData, station.Station_JP ); + const trainPositionText = currentTrainData?.Pos.match("~") + ? `現在地:${ + currentTrainData?.Pos.replace("(下り)", "") + .replace("(上り)", "") + .split("~")[currentTrainData?.Direction == 1 ? 0 : 1] + }→${ + currentTrainData?.Pos.replace("(下り)", "") + .replace("(上り)", "") + .split("~")[currentTrainData?.Direction == 1 ? 1 : 0] + }間を走行中` + : `現在地:${currentTrainData?.Pos}`; return ( <> + {trainDescriptionSwitch && } {trainDescriptionSwitch && !!train.info && ( )} diff --git a/components/駅名表/Sign.js b/components/駅名表/Sign.js index 38bc62f..84ee25e 100644 --- a/components/駅名表/Sign.js +++ b/components/駅名表/Sign.js @@ -1,6 +1,7 @@ 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 { MaterialCommunityIcons } from "@expo/vector-icons"; import LottieView from "lottie-react-native"; import { useInterval } from "../../lib/useInterval"; import { AS } from "../../storageControl"; @@ -9,7 +10,13 @@ import { useFavoriteStation } from "../../stateBox/useFavoriteStation"; import lineColorList from "../../assets/originData/lineColorList"; export default function Sign(props) { - const { currentStation, originalStationList, oP, oLP } = props; + const { + currentStation, + originalStationList, + oP, + oLP, + isCurrentStation = false, + } = props; const { favoriteStation, setFavoriteStation } = useFavoriteStation(); const [nexPrePosition, setNexPrePosition] = useState(0); @@ -68,9 +75,9 @@ export default function Sign(props) { "土讃線(多度津-高知間)[D]", "土讃線(高知-窪川間)[K]", "高徳線(高松-徳島間)[T]", - "徳島線(徳島-阿波池田)[B]", + "徳島線(徳島-阿波池田間)[B]", "鳴門線(池谷-鳴門間)[N]", - "瀬戸大橋線(宇多津-児島間)[M]", + "瀬戸大橋線(児島-宇多津間)[M]", ]; let returnData; lineList.forEach((d) => { @@ -92,39 +99,50 @@ export default function Sign(props) { - { - if (testButtonStatus) { - const otherData = favoriteStation.filter((d) => { - const compare = JSON.stringify(d); - const current = JSON.stringify(currentStation); - if (compare !== current) { - return true; - } else { - return false; - } - }); - AS.setItem("favoriteStation", JSON.stringify(otherData)); - setFavoriteStation(otherData); - } else { - let ret = favoriteStation; - ret.push(currentStation); - AS.setItem("favoriteStation", JSON.stringify(ret)); - setFavoriteStation(ret); - } - setTestButtonStatus(!testButtonStatus); - }} - > - - + {isCurrentStation ? ( + + + + ) : ( + { + if (testButtonStatus) { + const otherData = favoriteStation.filter((d) => { + const compare = JSON.stringify(d); + const current = JSON.stringify(currentStation); + if (compare !== current) { + return true; + } else { + return false; + } + }); + AS.setItem("favoriteStation", JSON.stringify(otherData)); + setFavoriteStation(otherData); + } else { + let ret = favoriteStation; + ret.push(currentStation); + AS.setItem("favoriteStation", JSON.stringify(ret)); + setFavoriteStation(ret); + } + setTestButtonStatus(!testButtonStatus); + }} + > + + + )} JR diff --git a/lib/eachTrainInfoCoreLib/getStationData.js b/lib/eachTrainInfoCoreLib/getStationData.js index 20b386a..35e4631 100644 --- a/lib/eachTrainInfoCoreLib/getStationData.js +++ b/lib/eachTrainInfoCoreLib/getStationData.js @@ -1,7 +1,7 @@ // 駅名から駅情報を取得する //stationName: 駅名 //stationList: 駅情報リスト -export const getStationData = (stationName, stationList) => { +export const getStationID = (stationName, stationList) => { const Stations = stationList.map((a) => a.filter((d) => d.StationName == stationName) ); @@ -13,3 +13,15 @@ export const getStationData = (stationName, stationList) => { if (!Station[0]) return []; return Station.map((d) => d.StationNumber)[0]; }; +export const getStationName = (stationId, stationList) => { + const Stations = stationList.map((a) => + a.filter((d) => d.StationNumber == stationId) + ); + const Station = + Stations && + Stations.reduce((newArray, e) => { + return newArray.concat(e); + }, []); + if (!Station[0]) return []; + return Station.map((d) => d.StaitonName)[0]; +}; diff --git a/lib/getStationList.js b/lib/getStationList.js index 06bb601..dcad90e 100644 --- a/lib/getStationList.js +++ b/lib/getStationList.js @@ -25,9 +25,9 @@ export const lineList = [ "土讃線(多度津-高知間)[D]", "土讃線(高知-窪川間)[K]", "高徳線(高松-徳島間)[T]", - "徳島線(徳島-阿波池田)[B]", + "徳島線(徳島-阿波池田間)[B]", "鳴門線(池谷-鳴門間)[N]", - "瀬戸大橋線(宇多津-児島間)[M]", + "瀬戸大橋線(児島-宇多津間)[M]", ]; export const lineListPair = { Y: "予讃線(高松-松山間)[Y]", @@ -36,9 +36,9 @@ export const lineListPair = { D: "土讃線(多度津-高知間)[D]", K: "土讃線(高知-窪川間)[K]", T: "高徳線(高松-徳島間)[T]", - B: "徳島線(徳島-阿波池田)[B]", + B: "徳島線(徳島-阿波池田間)[B]", N: "鳴門線(池谷-鳴門間)[N]", - M: "瀬戸大橋線(宇多津-児島間)[M]", + M: "瀬戸大橋線(児島-宇多津間)[M]", }; export const getStationList = async (props) => { @@ -65,9 +65,9 @@ export const getStationList = async (props) => { stationList["土讃線(多度津-高知間)[D]"], stationList["土讃線(高知-窪川間)[K]"], stationList["高徳線(高松-徳島間)[T]"], - stationList["徳島線(徳島-阿波池田)[B]"], + stationList["徳島線(徳島-阿波池田間)[B]"], stationList["鳴門線(池谷-鳴門間)[N]"], - stationList["瀬戸大橋線(宇多津-児島間)[M]"], + stationList["瀬戸大橋線(児島-宇多津間)[M]"], stationList.駅間リスト, stationList.日英対応表, ] = values; @@ -160,16 +160,16 @@ export const getStationList = async (props) => { stationList.日英対応表 ); const tokushimaCurrent = addStationPosition( - concatBetweenStations(stationList["徳島線(徳島-阿波池田)[B]"]), + concatBetweenStations(stationList["徳島線(徳島-阿波池田間)[B]"]), 徳島線, stationList.日英対応表 ); - stationList["徳島線(徳島-阿波池田)[B]"] = [ + stationList["徳島線(徳島-阿波池田間)[B]"] = [ tokushimaCurrent[tokushimaCurrent.length - 1], ...tokushimaCurrent, ]; - stationList["徳島線(徳島-阿波池田)[B]"].pop(); - stationList["瀬戸大橋線(宇多津-児島間)[M]"] = [ + stationList["徳島線(徳島-阿波池田間)[B]"].pop(); + stationList["瀬戸大橋線(児島-宇多津間)[M]"] = [ { Station_JP: "坂出", Station_EN: "Sakaide", diff --git a/lib/getStationList2.js b/lib/getStationList2.js index 11397b8..e554828 100644 --- a/lib/getStationList2.js +++ b/lib/getStationList2.js @@ -32,3 +32,15 @@ export const stationIDPair = { naruto: "N", seto: "M", }; + +export const stationNamePair = { + "予讃線(高松 - 松山)": "yosan", + "予讃線・内子線(松山 - 内子 - 宇和島)": "uwajima", + "予讃線・伊予灘線(向井原 - 伊予大洲)": "uwajima2", + "土讃線(多度津 - 高知)": "dosan", + "土讃線(高知 - 窪川)": "dosan2", + "高徳線(高松 - 徳島)": "koutoku", + "徳島線(徳島 - 阿波池田)": "tokushima", + "鳴門線(池谷 - 鳴門)": "naruto", + "瀬戸大橋線(児島 - 宇多津)": "seto", +}; diff --git a/lib/webViewInjectjavascript.js b/lib/webViewInjectjavascript.js index 27a218d..b1ff812 100644 --- a/lib/webViewInjectjavascript.js +++ b/lib/webViewInjectjavascript.js @@ -696,7 +696,11 @@ const setStrings = () =>{ } catch (e) {} } -const textInsert = new MutationObserver( (mutations) => setStrings()); +const textInsert = new MutationObserver( (mutations) =>{ + setStrings(); + const currentLines = document.querySelector('#topHeader div').innerText; + window.ReactNativeWebView.postMessage(JSON.stringify({type:"currentLines",currentLines})); +}); // 監視を開始 textInsert.observe(document.getElementById('disp'), { diff --git a/menu.js b/menu.js index 1606d78..64db365 100644 --- a/menu.js +++ b/menu.js @@ -52,7 +52,7 @@ export default function Menu({ getCurrentTrain }) { const makeCurrentStation = (location) => { if (!originalStationList) return () => {}; const findStationEachLine = (selectLine) => { - const searchArea = 0.0015; + const searchArea = 0.002; const _calcDistance = (from, to) => { let lat = Math.abs(from.lat - to.lat); let lng = Math.abs(from.lng - to.lng); @@ -172,6 +172,7 @@ export default function Menu({ getCurrentTrain }) { { const payload = { currentStation: diff --git a/stateBox/useCurrentTrain.js b/stateBox/useCurrentTrain.js index 7a96cfb..e49290a 100644 --- a/stateBox/useCurrentTrain.js +++ b/stateBox/useCurrentTrain.js @@ -31,14 +31,23 @@ export const CurrentTrainProvider = ({ children }) => { .then((response) => response.json()) .then((d) => d.data) .then((d) => - d.map((x) => ({ num: x.TrainNum, delay: x.delay, Pos: x.Pos })) + d.map((x) => ({ + Index: x.Index, + num: x.TrainNum, + delay: x.delay, + Pos: x.Pos, + PosNum: x.PosNum, + Direction: x.Direction, + Type: x.Type, + Line: x.Line, + })) ) .then((d) => { setCurrentTrain(d); setCurrentTrainLoading("success"); }) .catch(() => { - alert("現在の全在線列車取得エラー/再取得します"); + //alert("現在の全在線列車取得エラー/再取得します"); fetch( "https://script.google.com/macros/s/AKfycby9Y2-Bm75J_WkbZimi7iS8v5r9wMa9wtzpdwES9sOGF4i6HIYEJOM60W6gM1gXzt1o/exec", HeaderConfig @@ -57,6 +66,9 @@ export const CurrentTrainProvider = ({ children }) => { }); }); }; + const inject = (i) => { + webview.current?.injectJavaScript(i); + }; useEffect(getCurrentTrain, []); //初回だけ現在の全在線列車取得 @@ -72,6 +84,7 @@ export const CurrentTrainProvider = ({ children }) => { currentTrainLoading, setCurrentTrainLoading, getCurrentTrain, + inject, }} > {children} diff --git a/stateBox/useTrainMenu.js b/stateBox/useTrainMenu.js new file mode 100644 index 0000000..efbc979 --- /dev/null +++ b/stateBox/useTrainMenu.js @@ -0,0 +1,36 @@ +import React, { createContext, useContext, useState } from "react"; +const initialState = { + selectedLine: undefined, + setSelectedLine: () => {}, + mapsStationData: undefined, + setMapsStationData: () => {}, + injectJavaScript: "", + setInjectJavaScript: () => {}, +}; + +const TrainMenuContext = createContext(initialState); + +export const useTrainMenu = () => { + return useContext(TrainMenuContext); +}; + +export const TrainMenuProvider = ({ children }) => { + const [selectedLine, setSelectedLine] = useState(undefined); + const [mapsStationData, setMapsStationData] = useState(undefined); + const [injectJavaScript, setInjectJavaScript] = useState(); + + return ( + + {children} + + ); +}; diff --git a/storageControl.js b/storageControl.js index 4f43140..939a943 100644 --- a/storageControl.js +++ b/storageControl.js @@ -11,4 +11,5 @@ export const AS = { // if set to null, then it will never expire. expires: null, }), + removeItem: (key) => storage.remove({ key }), };