diff --git a/Apps.js b/Apps.js index 84c25ff..0e9679b 100644 --- a/Apps.js +++ b/Apps.js @@ -1,8 +1,16 @@ -import React, { useEffect, useRef, useState } from "react"; -import { View, Platform, Text, TouchableOpacity } from "react-native"; +import React, { useEffect, useState } from "react"; +import { + View, + Platform, + Text, + TouchableOpacity, + useWindowDimensions, + LayoutAnimation, +} from "react-native"; import { WebView } from "react-native-webview"; import Constants from "expo-constants"; import { Ionicons } from "@expo/vector-icons"; + import { AS } from "./storageControl"; import { news } from "./config/newsUpdate"; import { getStationList, lineList } from "./lib/getStationList"; @@ -11,15 +19,28 @@ import { checkDuplicateTrainData } from "./lib/checkDuplicateTrainData"; import { useFavoriteStation } from "./stateBox/useFavoriteStation"; import { useCurrentTrain } from "./stateBox/useCurrentTrain"; import { SheetManager } from "react-native-actions-sheet"; +import TrainMenu from "./components/trainMenu"; +import { EachTrainInfoCore } from "./components/ActionSheetComponents/EachTrainInfoCore"; /* import StatusbarDetect from './StatusbarDetect'; var Status = StatusbarDetect(); */ export default function Apps({ navigation, webview, stationData }) { const { currentTrain } = useCurrentTrain(); + const { height, width } = useWindowDimensions(); const { navigate } = navigation; var urlcache = ""; const { favoriteStation } = useFavoriteStation(); + const [isLandscape, setIsLandscape] = useState(false); //画面が横向きかどうか + const handleLayout = () => {}; + useEffect(() => { + if (height / width > 1.5) { + setIsLandscape(false); + } + if (height / width < 1.5) { + setIsLandscape(true); + } + }, [height, width]); //画面表示関連 const [iconSetting, setIconSetting] = useState(undefined); @@ -167,6 +188,7 @@ export default function Apps({ navigation, webview, stationData }) { case "ShowTrainTimeInfo": { const { trainNum, limited } = dataSet; //alert(trainNum, limited); + LayoutAnimation.easeInEaseOut(); setTrainInfo({ trainNum, limited, @@ -174,6 +196,7 @@ export default function Apps({ navigation, webview, stationData }) { currentTrain.filter((a) => a.num == trainNum) ), }); //遅延情報は未実装 + if (isLandscape) return; const payload = { data: { trainNum, @@ -271,8 +294,22 @@ export default function Apps({ navigation, webview, stationData }) { style={{ height: "100%", paddingTop: Platform.OS == "ios" ? Constants.statusBarHeight : 0, + flexDirection: isLandscape ? "row" : "column", }} + onLayout={handleLayout} > + {!trainInfo.trainNum && isLandscape ? ( + + ) : null} {/* {Status} */} - navigate("trainMenu", { webview })} - top={Platform.OS == "ios" ? Constants.statusBarHeight : 0} - mapSwitch={mapSwitch == "true" ? "flex" : "none"} - /> + {isLandscape && trainInfo.trainNum && ( + + + + )} + {isLandscape || ( + navigate("trainMenu", { webview })} + top={Platform.OS == "ios" ? Constants.statusBarHeight : 0} + mapSwitch={mapSwitch == "true" ? "flex" : "none"} + /> + )} + {isLandscape && trainInfo.trainNum && ( + { + LayoutAnimation.easeInEaseOut(); + setTrainInfo({ + trainNum: undefined, + limited: undefined, + trainData: undefined, + }); + }} + top={Platform.OS == "ios" ? Constants.statusBarHeight : 0} + /> + )} webview.current.reload()} top={Platform.OS == "ios" ? Constants.statusBarHeight : 0} + right={isLandscape && trainInfo.trainNum ? (width / 100) * 40 : 0} LoadError={LoadError} /> @@ -360,12 +433,54 @@ const MapsButton = ({ onPress, top, mapSwitch }) => { ); }; -const ReloadButton = ({ onPress, top, mapSwitch, LoadError = false }) => { +const LandscapeBackButton = ({ onPress, top }) => { const styles = { touch: { position: "absolute", top, - right: 10, + left: 10, + width: 50, + height: 50, + backgroundColor: "#0099CC", + borderColor: "white", + borderStyle: "solid", + borderWidth: 1, + borderRadius: 50, + alignContent: "center", + alignSelf: "center", + alignItems: "center", + display: "flex", + }, + text: { + textAlign: "center", + width: "auto", + height: "auto", + textAlignVertical: "center", + fontWeight: "bold", + color: "white", + }, + }; + return ( + + + + + + ); +}; + +const ReloadButton = ({ + onPress, + top, + mapSwitch, + LoadError = false, + right, +}) => { + const styles = { + touch: { + position: "absolute", + top, + right: 10 + right, width: 50, height: 50, backgroundColor: LoadError ? "red" : "#0099CC", diff --git a/app.json b/app.json index 1686ab8..19aa076 100644 --- a/app.json +++ b/app.json @@ -8,7 +8,7 @@ "android" ], "version": "4.6", - "orientation": "portrait", + "orientation": "default", "icon": "./assets/icon.png", "splash": { "image": "./assets/splash.png", diff --git a/components/ActionSheetComponents/EachTrainInfo.js b/components/ActionSheetComponents/EachTrainInfo.js index e88a619..6331cca 100644 --- a/components/ActionSheetComponents/EachTrainInfo.js +++ b/components/ActionSheetComponents/EachTrainInfo.js @@ -1,389 +1,11 @@ -import React, { useEffect, useState, useRef } from "react"; -import { - View, - LayoutAnimation, - ScrollView, - Linking, - Text, - TouchableOpacity, - TouchableWithoutFeedback, - Platform, -} from "react-native"; -import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons"; -import ActionSheet, { - SheetManager, - useScrollHandlers, -} from "react-native-actions-sheet"; -import { AS } from "../../storageControl"; -import trainList from "../../assets/originData/trainList"; -import { lineList } from "../../lib/getStationList"; -import { - heightPercentageToDP, - widthPercentageToDP, -} from "react-native-responsive-screen"; -import lineColorList from "../../assets/originData/lineColorList"; -import { useCurrentTrain } from "../../stateBox/useCurrentTrain"; -import { checkDuplicateTrainData } from "../../lib/checkDuplicateTrainData"; -import dayjs from "dayjs"; -import { getTrainType } from "../../lib/getTrainType"; -import { customTrainDataDetector } from "../custom-train-data"; -import { useBusAndTrainData } from "../../stateBox/useBusAndTrainData"; - +import React, { useRef } from "react"; +import { Platform } from "react-native"; +import ActionSheet from "react-native-actions-sheet"; +import { EachTrainInfoCore } from "./EachTrainInfoCore"; export const EachTrainInfo = (props) => { if (!props.payload) return <>; - const { - data, - navigate, - originalStationList, - openStationACFromEachTrainInfo = () => {}, - from, - } = props.payload; - const [trainData, setTrainData] = useState([]); - const [currentPosition, setCurrentPosition] = useState([]); - const [trainPositionSwitch, setTrainPositionSwitch] = useState("false"); - const { currentTrain } = useCurrentTrain(); - const { getInfluencedTrainData } = useBusAndTrainData(); - - const [currentTrainData, setCurrentTrainData] = useState([]); - const [nearTrainIDList, setNearTrainIDList] = useState([]); - const [showNearTrain, setShowNearTrain] = useState([]); - const [isConcatNear, setIsConcatNear] = useState(false); - const [tailStation, setTailStation] = useState(); - const [headStation, setHeadStation] = useState(); - // const [actionSheetHorizonalScroll, setActionSheetHorizonalScroll] = useState(false); - - //裏列車探索 - useEffect(() => { - if (!data.trainNum) return; - const [returnArray, TDArray] = getInfluencedTrainData(data.trainNum); - setNearTrainIDList(returnArray); - setShowNearTrain(TDArray); - }, [data]); - - useEffect(() => { - if (trainData.length == 0) return; - if (showNearTrain.length == 0) return; - showNearTrain.forEach((d) => { - const [station, se, time] = d.split(","); - - console.log(trainData); //trainDataは現在の列車の停車駅リスト - console.log(station); //showNearTrainは裏列車の停車駅リスト - console.log(trainData[0]); - if (station == trainData[0].split(",")[0]) - setHeadStation(trainData[0].split(",")[0]); - if (station == trainData[trainData.length - 1].split(",")[0]) - setTailStation(trainData[trainData.length - 1].split(",")[0]); - }); - }, [trainData, showNearTrain]); - - const openBackTrainInfo = (stationInfo, currentTrainIndex) => { - const migrationArray = (stationInfo) => { - const mainTrainStationPosition = trainData.findIndex( - (d) => d.split(",")[0] == stationInfo - ); - - const relationMain = (() => { - if (mainTrainStationPosition == 0) return "head"; - if (mainTrainStationPosition == trainData.length - 1) return "tail"; - return "middle"; - })(); - - const subTrainStationPosition = showNearTrain.findIndex( - (d) => d.split(",")[0] == stationInfo - ); - const relationSub = (() => { - if (subTrainStationPosition == 0) return "head"; - if (subTrainStationPosition == showNearTrain.length - 1) return "tail"; - return "middle"; - })(); - - switch (relationMain) { - case "head": - if (relationSub == "head") { - return; - } else if (relationSub == "tail") { - return [ - ...showNearTrain.slice(0, subTrainStationPosition), - ...trainData, - ]; - } else if (relationSub == "middle") { - return [ - ...showNearTrain.slice(0, subTrainStationPosition), - ...trainData, - ]; - } else return; - case "tail": - if (relationSub == "head") { - return [ - ...trainData.slice(0, mainTrainStationPosition), - ...showNearTrain, - ]; - } else if (relationSub == "tail") { - return; - } else if (relationSub == "middle") { - return [ - ...trainData.slice(0, mainTrainStationPosition), - ...showNearTrain.slice(subTrainStationPosition), - ]; - } else return; - case "middle": - if (relationSub == "head") { - return [ - ...trainData.slice(0, mainTrainStationPosition), - ...showNearTrain, - ]; - } else if (relationSub == "tail") { - return [ - ...showNearTrain.slice(0, subTrainStationPosition), - ...trainData.slice(mainTrainStationPosition), - ]; - } else return; - } - }; - const array = migrationArray(stationInfo); - if (!array) return; - setTrainData(array); - setIsConcatNear(true); - }; - - const openTrainInfo = (d) => { - const train = customTrainDataDetector(d); - let TrainNumber = ""; - if (train.trainNumDistance != undefined) { - const timeInfo = - parseInt(d.replace("M", "").replace("D", "")) - train.trainNumDistance; - TrainNumber = timeInfo + "号"; - } - const payload = { - data: { - trainNum: d, - limited: `${getTrainType(train.type).data}:${ - train.trainName - }${TrainNumber}`, - }, - navigate, - originalStationList, - from: "AllTrainDiagramView", - }; - SheetManager.hide("EachTrainInfo").then(() => { - //0.1秒待機してから開く - setTimeout(() => { - SheetManager.show("EachTrainInfo", { payload }); - }, 1); - }); - }; - useEffect(() => { - setCurrentTrainData( - checkDuplicateTrainData( - currentTrain.filter((d) => d.num == data.trainNum) - ) - ); - }, [currentTrain]); - - useEffect(() => { - //列車現在地アイコン表示スイッチ - AS.getItem("trainPositionSwitch") - .then((d) => { - if (d) { - setTrainPositionSwitch(d); - } else { - } - }) - .catch((d) => AS.setItem("trainPositionSwitch", "false")); - }, []); - //bconst insets = useSafeAreaInsets(); - const getStationData = (stationName) => { - const Stations = stationList.map((a) => - a.filter((d) => d.StationName == stationName) - ); - const Station = - Stations && - Stations.reduce((newArray, e) => { - return newArray.concat(e); - }, []); - if (!Station[0]) return []; - return Station.map((d) => d.StationNumber)[0]; - }; - useEffect(() => { - //currentTrainData.Pos = "鴨川~端岡"; //test - if (!currentTrainData?.Pos) return; - if (currentTrainData?.Pos.match("~")) { - const pos = currentTrainData?.Pos.replace("(下り)", "") - .replace("(上り)", "") - .split("~"); - setCurrentPosition([getStationData(pos[0]), getStationData(pos[1])]); - } else { - setCurrentPosition([getStationData(currentTrainData?.Pos)]); - } - }, [currentTrainData]); - - const stationList = - originalStationList && - lineList.map((d) => - originalStationList[d].map((a) => ({ - StationNumber: a.StationNumber, - StationName: a.Station_JP, - })) - ); - const stopStationIDList = trainData.map((i, index) => { - const [station, se, time] = i.split(","); - const Stations = stationList.map((a) => - a.filter((d) => d.StationName == station) - ); - const StationNumbers = - Stations && - Stations.reduce((newArray, e) => { - return newArray.concat(e); - }, []) - .filter((d) => d.StationNumber) - .map((d) => d.StationNumber); - return StationNumbers[0]; - }); - function findReversalPoints(array) { - try { - // arrayは現在位置の駅ID(駅在宅の場合は1つの配列、駅間の場合は2つの配列) - // stopStationIDListは停車駅の駅IDの配列 - if (!stopStationIDList.length) return []; - // arrayが二次元配列だったら早期リターン - if (!array instanceof Array) return []; - if (!array.length) return []; - if (array[0] instanceof Array) return []; - const arrayNumber = array.map((d) => ({ - line: d - .split("") - .filter((s) => "A" < s && s < "Z") - .join(""), - ID: d - .split("") - .filter((s) => "0" <= s && s <= "9") - .join(""), - })); - const stopStationIDListNumber = stopStationIDList.map((d) => { - if (!d) return { line: [], ID: [] }; - return { - line: d - .split("") - .filter((s) => "A" < s && s < "Z") - .join(""), - ID: d - .split("") - .filter((s) => "0" <= s && s <= "9") - .join(""), - }; - }); - // 完全一致 - if (array.length == 1) { - const index = stopStationIDList.indexOf(array[0]); - if (index != -1) return [index]; - // 通過駅の場合 - for (let i = 0; i < stopStationIDListNumber.length - 1; i++) { - if (stopStationIDListNumber[i].ID < arrayNumber[0].ID) { - if (stopStationIDListNumber[i + 1].ID > arrayNumber[0].ID) { - return [i + 1]; - } - } - if (stopStationIDListNumber[i].ID > arrayNumber[0].ID) { - if (stopStationIDListNumber[i + 1].ID < arrayNumber[0].ID) { - return [i + 1]; - } - } - } - } - // 駅間の場合 - if (array.length == 2) { - const index1 = stopStationIDList.indexOf(array[0]); - const index2 = stopStationIDList.indexOf(array[1]); - if (index1 != -1 && index2 != -1) { - // 駅間で通過駅も無い場合 - if (index1 < index2) { - if (index1 + 1 == index2) { - return [index2]; - } else { - const returnArray = []; - for (let i = index1 + 1; i <= index2; i++) { - returnArray.push(i); - } - return returnArray; - } - } - if (index1 > index2) { - if (index2 + 1 == index1) return [index1]; - else { - const returnArray = []; - for (let i = index2 + 1; i <= index1; i++) { - returnArray.push(i); - } - return returnArray; - } - } - } else { - const getNearStationID = (stationID) => { - for (let i = 0; i <= stopStationIDListNumber.length; i++) { - if (stopStationIDListNumber[i].ID < stationID) { - if (stopStationIDListNumber[i + 1].ID > stationID) { - return i + 1; - } - } - if (stopStationIDListNumber[i].ID > stationID) { - if (stopStationIDListNumber[i + 1].ID < stationID) { - return i + 1; - } - } - } - }; - let newIndex1 = index1; - let newIndex2 = index2; - if (index1 == -1) { - newIndex1 = getNearStationID(arrayNumber[0].ID); - } - if (index2 == -1) { - newIndex2 = getNearStationID(arrayNumber[1].ID); - } - if (newIndex1 && newIndex2) { - return [newIndex1, newIndex2]; - } - - // 通過駅の場合 - } - - return []; - } - } catch (e) { - console.log(e); - } - } - // 使用例 - const points = - trainPositionSwitch == "true" ? findReversalPoints(currentPosition) : []; - - useEffect(() => { - if (!data.trainNum) return; - const TD = trainList[data.trainNum]; - if (!TD) { - setTrainData([]); - return; - } - setTrainData(TD.split("#").filter((d) => d != "")); - }, [data]); - const getType = (string) => { - switch (string) { - case "express": - return "特急"; - case "rapid": - return "快速"; - default: - return ""; - } - }; - - const migrateTrainName = (string) => { - return string - .replace("マリン", "マリンライナー") - .replace("ライナーライナー", "ライナー"); - }; const actionSheetRef = useRef(null); - const scrollHandlers = useScrollHandlers("scrollview-1", actionSheetRef); return ( { ref={actionSheetRef} drawUnderStatusBar={false} isModal={Platform.OS == "ios"} + //useBottomSafeAreaPadding={Platform.OS == "android"} > - - - - - - - {data.limited - ? getType(data.limited.split(":")[0]) + - migrateTrainName( - data.limited.split(":")[1] || - (trainData.length > 0 - ? trainData[trainData.length - 1].split(",")[0] + "行き" - : " ") - ) - : ""} - - - - {data.trainNum} - {isConcatNear ? ` + ${nearTrainIDList}` : ""} - - - {data.limited != undefined && - getType(data.limited.split(":")[0]) && - !data.limited.split(":")[1].match("サンポート") && ( - { - LayoutAnimation.easeInEaseOut(); //setLoadingDelayData(true); - navigate("trainbase", { - info: "train.html?tn=" + data.trainNum, - from, - }); - SheetManager.hide("EachTrainInfo"); - }} - /> - )} - - {from == "AllTrainDiagramView" || ( - setActionSheetHorizonalScroll(true)} - //onScrollEndDrag={() => setActionSheetHorizonalScroll(false)} - //onScrollBeginDrag={() => console.log("onScrollBeginDrag")} - style={{ - flexDirection: "row", - //width: widthPercentageToDP("200%"), - minHeight: 200, - height: heightPercentageToDP("20%"), - }} - horizontal - pagingEnabled - > - - {/* - - - 行先 - - - 岡山 - - - - - - 車両案内 - - - - 宇多津でうずしお号と連結 - - - - - - - 編成(使用車両:2700系) - - - - {"[<自][自>][アン自|指>][アン指|G>]"} - - - - */} - - )} - - - 停車駅 - - - {!isNaN(currentTrainData?.delay) && - currentTrainData?.delay != 0 && ( - - (定刻) - - )} - - 見込 - - - - - - - {headStation && !isConcatNear && ( - openBackTrainInfo(headStation)} - style={{ - padding: 10, - flexDirection: "row", - borderColor: "blue", - borderWidth: 1, - margin: 10, - borderRadius: 5, - alignItems: "center", - }} - > - - 「本当の始発駅」を表示 - - - )} - {/* - ほげほげふがふが */} - - {trainData.map((i, index) => - i.split(",")[1] == "提" ? ( - - ) : ( - - ) - )} - {tailStation && !isConcatNear && ( - openBackTrainInfo(tailStation)} - style={{ - padding: 10, - flexDirection: "row", - borderColor: "blue", - borderWidth: 1, - margin: 10, - borderRadius: 5, - alignItems: "center", - }} - > - - 「本当の終着駅」を表示 - - - )} - - - - - - - - - + ); }; - -const DataFromButton = ({ i }) => { - const [station, se, time] = i.split(","); - return ( - Linking.openURL(time)} - key={station} - > - - - {station} - - - 提供元 - - - - - - ); -}; - -const StationButton = ({ - i, - index, - stationList, - points, - currentTrainData, - openStationACFromEachTrainInfo, -}) => { - const [station, se, time] = i.split(","); // 阿波池田,発,6:21 - const Stations = stationList - .map((a) => a.filter((d) => d.StationName == station)) - .reduce((newArray, e) => newArray.concat(e), []); - /*Array [ - Object { - "StationName": "佐古", - "StationNumber": "T01", - }, - Object { - "StationName": "佐古", - "StationNumber": "B01", - }, - ] */ - const StationNumbers = - Stations && - Stations.filter((d) => d.StationNumber).map((d) => d.StationNumber); - // Array [ "T01", "B01",] - const lineIDs = []; - const EachIDs = []; - StationNumbers.forEach((d) => { - const textArray = d.split(""); - lineIDs.push(textArray.filter((s) => "A" < s && s < "Z").join("")); - EachIDs.push(textArray.filter((s) => "0" <= s && s <= "9").join("")); - }); - // Array [ "T", "B",] - // Array [ "01", "01",] - - const dates = dayjs() - .set("hour", parseInt(time.split(":")[0])) - .set("minute", parseInt(time.split(":")[1])) - .add(isNaN(currentTrainData?.delay) ? 0 : currentTrainData.delay, "minute"); - const timeString = dates.format("HH:mm").split(":"); - - return ( - openStationACFromEachTrainInfo(station)} - key={station} - > - - - {lineIDs.map((lineID, index) => ( - - - - {lineIDs[index]} - {"\n"} - {EachIDs[index]} - - - - ))} - - - {station} - - {points && points.findIndex((d) => d == index) >= 0 ? ( - 🚊 - ) : null} - {!isNaN(currentTrainData?.delay) && currentTrainData?.delay != 0 && ( - - {time} - - )} - - {timeString[0]}:{timeString[1]} - - - {se?.replace("発", "出発").replace("着", "到着")} - - - - - ); -}; - -const TrainDataView = ({ - currentTrainData, - currentPosition, - nearTrainIDList, - openTrainInfo, -}) => { - return ( - - - - - - - { - if (nearTrainIDList.length == 0) return; - openTrainInfo(nearTrainIDList[0]); - }} - > - {nearTrainIDList.length == 0 ? ( - - ) : ( - - )} - - - - ); -}; - -const StateBox = ({ text, title, style }) => ( - - {title} - - - {text?.match("~") ? ( - <> - {text.split("~")[0]} - - {text.split("~")[1]} - - ) : ( - {text} - )} - - -); -const boxStyle = { - flex: 1, - backgroundColor: "white", - borderRadius: 10, - padding: 10, - margin: 10, -}; -const boxTextStyle = { - fontSize: 25, - color: "#0099CC", - textAlign: "right", -}; diff --git a/components/ActionSheetComponents/EachTrainInfo/DataFromButton.js b/components/ActionSheetComponents/EachTrainInfo/DataFromButton.js new file mode 100644 index 0000000..664a8bf --- /dev/null +++ b/components/ActionSheetComponents/EachTrainInfo/DataFromButton.js @@ -0,0 +1,36 @@ +import React from "react"; +import { View, Text, TouchableWithoutFeedback } from "react-native"; +import { MaterialCommunityIcons } from "@expo/vector-icons"; +import { Linking } from "react-native"; +export const DataFromButton = ({ i }) => { + const [station, se, time] = i.split(","); + return ( + Linking.openURL(time)} + key={station} + > + + + {station} + + + 提供元 + + + + + + ); +}; diff --git a/components/ActionSheetComponents/EachTrainInfo/EachStopList.js b/components/ActionSheetComponents/EachTrainInfo/EachStopList.js new file mode 100644 index 0000000..218a025 --- /dev/null +++ b/components/ActionSheetComponents/EachTrainInfo/EachStopList.js @@ -0,0 +1,137 @@ +import React from "react"; +import { View, Text, TouchableWithoutFeedback } from "react-native"; +import dayjs from "dayjs"; +import lineColorList from "../../../assets/originData/lineColorList"; + +export const EachStopList = ({ + i, + index, + stationList, + points, + currentTrainData, + openStationACFromEachTrainInfo, +}) => { + const [station, se, time] = i.split(","); // 阿波池田,発,6:21 + const Stations = stationList + .map((a) => a.filter((d) => d.StationName == station)) + .reduce((newArray, e) => newArray.concat(e), []); + /*Array [ + Object { + "StationName": "佐古", + "StationNumber": "T01", + }, + Object { + "StationName": "佐古", + "StationNumber": "B01", + }, + ] */ + const StationNumbers = + Stations && + Stations.filter((d) => d.StationNumber).map((d) => d.StationNumber); + // Array [ "T01", "B01",] + const lineIDs = []; + const EachIDs = []; + StationNumbers.forEach((d) => { + const textArray = d.split(""); + lineIDs.push(textArray.filter((s) => "A" < s && s < "Z").join("")); + EachIDs.push(textArray.filter((s) => "0" <= s && s <= "9").join("")); + }); + // Array [ "T", "B",] + // Array [ "01", "01",] + + const dates = dayjs() + .set("hour", parseInt(time.split(":")[0])) + .set("minute", parseInt(time.split(":")[1])) + .add(isNaN(currentTrainData?.delay) ? 0 : currentTrainData.delay, "minute"); + const timeString = dates.format("HH:mm").split(":"); + + return ( + openStationACFromEachTrainInfo(station)} + key={station} + > + + + {lineIDs.map((lineID, index) => ( + + + + {lineIDs[index]} + {"\n"} + {EachIDs[index]} + + + + ))} + + + {station} + + {points && points.findIndex((d) => d == index) >= 0 ? ( + 🚊 + ) : null} + {!isNaN(currentTrainData?.delay) && currentTrainData?.delay != 0 && ( + + {time} + + )} + + {timeString[0]}:{timeString[1]} + + + {se?.replace("発", "出発").replace("着", "到着")} + + + + + ); +}; diff --git a/components/ActionSheetComponents/EachTrainInfo/LandscapeTrainInfo.js b/components/ActionSheetComponents/EachTrainInfo/LandscapeTrainInfo.js new file mode 100644 index 0000000..8538b65 --- /dev/null +++ b/components/ActionSheetComponents/EachTrainInfo/LandscapeTrainInfo.js @@ -0,0 +1,47 @@ +import React from "react"; +import { View, Text, ScrollView, useWindowDimensions } from "react-native"; + +export const LandscapeTrainInfo = (props) => { + const { leftContent, topStickyContent, children, scrollHandlers } = props; + const { height, width } = useWindowDimensions(); + return ( + + + {width / 2} + {leftContent} + + { + console.log(d.nativeEvent.contentOffset.y); + }} + > + + + {topStickyContent} + + {children} + + + ); +}; diff --git a/components/ActionSheetComponents/EachTrainInfo/LongHeader.js b/components/ActionSheetComponents/EachTrainInfo/LongHeader.js new file mode 100644 index 0000000..95f23f9 --- /dev/null +++ b/components/ActionSheetComponents/EachTrainInfo/LongHeader.js @@ -0,0 +1,33 @@ +import React from "react"; +import { ScrollView } from "react-native"; +import { TrainDataView } from "./TrainDataView"; + +export const LongHeader = ({ + currentTrainData, + currentPosition, + nearTrainIDList, + openTrainInfo, +}) => { + return ( + setActionSheetHorizonalScroll(true)} + //onScrollEndDrag={() => setActionSheetHorizonalScroll(false)} + //onScrollBeginDrag={() => console.log("onScrollBeginDrag")} + style={{ + flexDirection: "row", + //width: widthPercentageToDP("200%"), + // minHeight: 200, + //height: heightPercentageToDP("20%"), + }} + horizontal + pagingEnabled + > + + + ); +}; diff --git a/components/ActionSheetComponents/EachTrainInfo/ScrollStickyContent.js b/components/ActionSheetComponents/EachTrainInfo/ScrollStickyContent.js new file mode 100644 index 0000000..3881b36 --- /dev/null +++ b/components/ActionSheetComponents/EachTrainInfo/ScrollStickyContent.js @@ -0,0 +1,57 @@ +import React from "react"; +import { View, Text } from "react-native"; + +export const ScrollStickyContent = ({ currentTrainData }) => { + return ( + + + 停車駅 + + + {!isNaN(currentTrainData?.delay) && currentTrainData?.delay != 0 && ( + + (定刻) + + )} + + 見込 + + + + + + ); +}; diff --git a/components/ActionSheetComponents/EachTrainInfo/ShortHeader.js b/components/ActionSheetComponents/EachTrainInfo/ShortHeader.js new file mode 100644 index 0000000..a289e24 --- /dev/null +++ b/components/ActionSheetComponents/EachTrainInfo/ShortHeader.js @@ -0,0 +1,35 @@ +import React from "react"; +import { ScrollView } from "react-native"; +import { TrainDataView } from "./TrainDataView"; + +export const ShortHeader = ({ + currentTrainData, + currentPosition, + nearTrainIDList, + openTrainInfo, +}) => { + return ( + setActionSheetHorizonalScroll(true)} + //onScrollEndDrag={() => setActionSheetHorizonalScroll(false)} + //onScrollBeginDrag={() => console.log("onScrollBeginDrag")} + style={{ + flexDirection: "row", + flex: 1, + //width: widthPercentageToDP("200%"), + // minHeight: 200, + //height: heightPercentageToDP("20%"), + }} + horizontal + pagingEnabled + > + + + ); +}; diff --git a/components/ActionSheetComponents/EachTrainInfo/StateBox.js b/components/ActionSheetComponents/EachTrainInfo/StateBox.js new file mode 100644 index 0000000..c26f41b --- /dev/null +++ b/components/ActionSheetComponents/EachTrainInfo/StateBox.js @@ -0,0 +1,55 @@ +import React from "react"; +import { View, Text } from "react-native"; + +export const StateBox = ({ text, title, style, mode }) => ( + + {title} + + + {text?.match("~") ? ( + <> + + {text.split("~")[0]} + + + + {text.split("~")[1]} + + + ) : ( + {text} + )} + + +); +const boxStyle = { + flex: 1, + backgroundColor: "white", + borderRadius: 10, + padding: 10, + margin: 10, +}; +const boxStyle2 = { + flex: 1, + backgroundColor: "white", + borderRadius: 10, + padding: 5, + margin: 5, +}; +const boxTextStyle2 = { + fontSize: 18, + color: "#0099CC", + textAlign: "right", +}; + +const boxTextStyle = { + fontSize: 25, + color: "#0099CC", + textAlign: "right", +}; diff --git a/components/ActionSheetComponents/EachTrainInfo/TrainDataView.js b/components/ActionSheetComponents/EachTrainInfo/TrainDataView.js new file mode 100644 index 0000000..e8a229e --- /dev/null +++ b/components/ActionSheetComponents/EachTrainInfo/TrainDataView.js @@ -0,0 +1,95 @@ +import React, { useEffect, useState } from "react"; +import { + View, + Text, + TouchableOpacity, + useWindowDimensions, +} from "react-native"; +import { StateBox } from "./StateBox"; +import { + heightPercentageToDP, + widthPercentageToDP, +} from "react-native-responsive-screen"; + +export const TrainDataView = ({ + currentTrainData, + currentPosition, + nearTrainIDList, + openTrainInfo, + mode = 0, +}) => { + const [isLandscape, setIsLandscape] = useState(false); + const { width, height } = useWindowDimensions(); + useEffect(() => { + if (height / width > 1.5) { + setIsLandscape(false); + } + if (height / width < 1.5) { + setIsLandscape(true); + } + }, [width, height]); + + return ( + + + + + + + { + if (nearTrainIDList.length == 0) return; + openTrainInfo(nearTrainIDList[0]); + }} + > + {nearTrainIDList.length == 0 ? ( + + ) : ( + + )} + + + + ); +}; diff --git a/components/ActionSheetComponents/EachTrainInfoCore.js b/components/ActionSheetComponents/EachTrainInfoCore.js new file mode 100644 index 0000000..756c047 --- /dev/null +++ b/components/ActionSheetComponents/EachTrainInfoCore.js @@ -0,0 +1,453 @@ +import React, { useEffect, useState, useRef } from "react"; +import { + View, + LayoutAnimation, + Text, + TouchableOpacity, + Platform, + StyleSheet, + useWindowDimensions, +} from "react-native"; +import { Ionicons } from "@expo/vector-icons"; +import ActionSheet, { + SheetManager, + useScrollHandlers, +} from "react-native-actions-sheet"; +import { AS } from "../../storageControl"; +import trainList from "../../assets/originData/trainList"; +import { lineList } from "../../lib/getStationList"; +import { heightPercentageToDP } from "react-native-responsive-screen"; +import { useCurrentTrain } from "../../stateBox/useCurrentTrain"; +import { checkDuplicateTrainData } from "../../lib/checkDuplicateTrainData"; +import { getTrainType } from "../../lib/getTrainType"; +import { customTrainDataDetector } from "../custom-train-data"; +import { useBusAndTrainData } from "../../stateBox/useBusAndTrainData"; +import { EachStopList } from "./EachTrainInfo/EachStopList"; +import { DataFromButton } from "./EachTrainInfo/DataFromButton"; +import { DynamicHeaderScrollView } from "../DynamicHeaderScrollView"; +import { LongHeader } from "./EachTrainInfo/LongHeader"; +import { ShortHeader } from "./EachTrainInfo/ShortHeader"; +import { ScrollStickyContent } from "./EachTrainInfo/ScrollStickyContent"; +import { LandscapeTrainInfo } from "./EachTrainInfo/LandscapeTrainInfo"; +import { getStationData } from "../../lib/eachTrainInfoCoreLib/getStationData"; +import { findReversalPoints } from "../../lib/eachTrainInfoCoreLib/findReversalPoints"; +import { migrateTrainName } from "../../lib/eachTrainInfoCoreLib/migrateTrainName"; +import { getType } from "../../lib/eachTrainInfoCoreLib/getType"; +import { searchSpecialTrain } from "../../lib/eachTrainInfoCoreLib/searchSpecialTrain"; +import { openBackTrainInfo } from "../../lib/eachTrainInfoCoreLib/openBackTrainInfo"; + +export const EachTrainInfoCore = ({ + actionSheetRef, + data, + navigate, + originalStationList, + openStationACFromEachTrainInfo, + from, + setTrainInfo, +}) => { + // const [actionSheetHorizonalScroll, setActionSheetHorizonalScroll] = useState(false); + + const { currentTrain } = useCurrentTrain(); + const [currentTrainData, setCurrentTrainData] = useState(); + + // const [actionSheetHorizonalScroll, setActionSheetHorizonalScroll] = useState(false); + + useEffect(() => { + console.log(currentTrain.length); + if (!currentTrain.length) return; + setCurrentTrainData( + checkDuplicateTrainData( + currentTrain.filter((d) => d.num == data.trainNum) + ) + ); + }, [currentTrain, data.trainNum]); + + //bconst insets = useSafeAreaInsets(); + + const [headStation, setHeadStation] = useState(); + const [tailStation, setTailStation] = useState(); + const [isConcatNear, setIsConcatNear] = useState(false); + const [showNearTrain, setShowNearTrain] = useState([]); + const [nearTrainIDList, setNearTrainIDList] = useState([]); + const { getInfluencedTrainData } = useBusAndTrainData(); + const [trainPositionSwitch, setTrainPositionSwitch] = useState("false"); + const [currentPosition, setCurrentPosition] = useState([]); + const [trainData, setTrainData] = useState([]); + const scrollHandlers = actionSheetRef + ? useScrollHandlers("scrollview-1", actionSheetRef) + : null; + + const stationList = + originalStationList && + lineList.map((d) => + originalStationList[d].map((a) => ({ + StationNumber: a.StationNumber, + StationName: a.Station_JP, + })) + ); + + // 使用例 + const points = + trainPositionSwitch == "true" + ? findReversalPoints(currentPosition, stopStationIDList) + : []; + const stopStationIDList = trainData.map((i, index) => { + const [station, se, time] = i.split(","); + const Stations = stationList.map((a) => + a.filter((d) => d.StationName == station) + ); + const StationNumbers = + Stations && + Stations.reduce((newArray, e) => { + return newArray.concat(e); + }, []) + .filter((d) => d.StationNumber) + .map((d) => d.StationNumber); + return StationNumbers[0]; + }); + + const { height, width } = useWindowDimensions(); + const [isLandscape, setIsLandscape] = useState(false); + + const [trueTrainID, setTrueTrainID] = useState(); + useEffect(() => { + if (!data.trainNum) return; + const TD = trainList[data.trainNum]; + setIsConcatNear(false); + setHeadStation(); + setTailStation(); + if (!TD) { + const specialTrainActualID = searchSpecialTrain(data.trainNum, trainList); + setTrueTrainID(specialTrainActualID || undefined); + setTrainData([]); + return; + } + setTrainData(TD.split("#").filter((d) => d != "")); + }, [data]); + //裏列車探索 + useEffect(() => { + if (!data.trainNum) return; + const [returnArray, TDArray] = getInfluencedTrainData(data.trainNum); + setNearTrainIDList(returnArray); + setShowNearTrain(TDArray); + if (trainData.length == 0) return; + if (TDArray.length == 0) return; + let head; + let tail; + TDArray.forEach((d) => { + const [station, se, time] = d.split(","); + + if (station == trainData[0].split(",")[0]) { + head = trainData[0].split(",")[0]; + } + if (station == trainData[trainData.length - 1].split(",")[0]) { + tail = trainData[trainData.length - 1].split(",")[0]; + } + }); + if (head) setHeadStation(head); + else setHeadStation(); + if (tail) setTailStation(tail); + else setTailStation(); + }, [trainData, data]); + + useEffect(() => { + //currentTrainData.Pos = "鴨川~端岡"; //test + if (!currentTrainData) return; + if (!currentTrainData?.Pos) return; + if (currentTrainData?.Pos.match("~")) { + const pos = currentTrainData?.Pos.replace("(下り)", "") + .replace("(上り)", "") + .split("~"); + setCurrentPosition([ + getStationData(pos[0], stationList), + getStationData(pos[1], stationList), + ]); + } else { + setCurrentPosition([getStationData(currentTrainData?.Pos, stationList)]); + } + }, [currentTrainData]); + + useEffect(() => { + if (height / width > 1.5) { + setIsLandscape(false); + } + if (height / width < 1.5) { + setIsLandscape(true); + } + }, [width, height]); + + const replaceSpecialTrainDetail = (trainNum) => { + let TD = trainList[trainNum]; + if (!TD) return; + setTrainData(TD.split("#").filter((d) => d != "")); + }; + + useEffect(() => { + //列車現在地アイコン表示スイッチ + AS.getItem("trainPositionSwitch") + .then((d) => { + if (d) setTrainPositionSwitch(d); + }) + .catch((d) => AS.setItem("trainPositionSwitch", "false")); + }, []); + + const openTrainInfo = (d) => { + const train = customTrainDataDetector(d); + let TrainNumber = ""; + if (train.trainNumDistance != undefined) { + const timeInfo = + parseInt(d.replace("M", "").replace("D", "")) - train.trainNumDistance; + TrainNumber = timeInfo + "号"; + } + const payload = { + data: { + trainNum: d, + limited: `${getTrainType(train.type).data}:${ + train.trainName + }${TrainNumber}`, + }, + navigate, + originalStationList, + from: "AllTrainDiagramView", + }; + if (setTrainInfo) { + setTrainInfo(payload.data); + } else { + SheetManager.hide("EachTrainInfo").then(() => { + //0.1秒待機してから開く + setTimeout(() => { + SheetManager.show("EachTrainInfo", { payload }); + }, 1); + }); + } + }; + return ( + + {isLandscape || ( + + + + )} + + + {data.limited + ? getType(data.limited.split(":")[0]) + + migrateTrainName( + data.limited.split(":")[1] || + (trainData.length > 0 + ? trainData[trainData.length - 1].split(",")[0] + "行き" + : " ") + ) + : ""} + + + + {data.trainNum} + {isConcatNear ? ` + ${nearTrainIDList}` : ""} + + + {data.limited != undefined && + getType(data.limited.split(":")[0]) && + !data.limited.split(":")[1].match("サンポート") && ( + { + LayoutAnimation.easeInEaseOut(); //setLoadingDelayData(true); + navigate("trainbase", { + info: "train.html?tn=" + data.trainNum, + from, + }); + SheetManager.hide("EachTrainInfo"); + }} + /> + )} + + + ) : ( + + ) + } + longHeader={ + from == "AllTrainDiagramView" ? ( + <> + ) : ( + + ) + } + topStickyContent={ + + } + > + {headStation && !isConcatNear && ( + { + const array = openBackTrainInfo( + headStation, + trainData, + showNearTrain + ); + if (!array) return; + setTrainData(array); + setIsConcatNear(true); + }} + style={{ + padding: 10, + flexDirection: "row", + borderColor: "blue", + borderWidth: 1, + margin: 10, + borderRadius: 5, + alignItems: "center", + }} + > + + 「本当の始発駅」を表示 + + + )} + {/* + ほげほげふがふが */} + {trainData.length == 0 && trueTrainID && ( + replaceSpecialTrainDetail(trueTrainID)} + style={{ + padding: 10, + flexDirection: "row", + borderColor: "blue", + borderWidth: 1, + margin: 10, + borderRadius: 5, + alignItems: "center", + }} + > + + 本来の列車情報を表示 + + + )} + {trainData.map((i, index) => + i.split(",")[1] == "提" ? ( + + ) : ( + + ) + )} + {tailStation && !isConcatNear && ( + { + const array = openBackTrainInfo( + tailStation, + trainData, + showNearTrain + ); + + if (!array) return; + setTrainData(array); + setIsConcatNear(true); + }} + style={{ + padding: 10, + flexDirection: "row", + borderColor: "blue", + borderWidth: 1, + margin: 10, + borderRadius: 5, + alignItems: "center", + }} + > + + 「本当の終着駅」を表示 + + + )} + + + + + + + + + + ); +}; + +const styles = StyleSheet.create({ + header: { + justifyContent: "center", + alignItems: "center", + left: 0, + right: 0, + //paddingTop: 10, + position: "absolute", + zIndex: 1, + backgroundColor: "f0f0f0", + }, + headerText: { + color: "#fff", + fontSize: 25, + fontWeight: "bold", + textAlign: "center", + }, +}); diff --git a/components/ActionSheetComponents/JRSTraInfo.js b/components/ActionSheetComponents/JRSTraInfo.js index 05c2123..03bb430 100644 --- a/components/ActionSheetComponents/JRSTraInfo.js +++ b/components/ActionSheetComponents/JRSTraInfo.js @@ -12,6 +12,8 @@ import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons"; import ActionSheet, { 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"; export const JRSTraInfo = () => { const { getTime, delayData, loadingDelayData, setLoadingDelayData } = @@ -19,6 +21,20 @@ export const JRSTraInfo = () => { const actionSheetRef = useRef(null); const scrollHandlers = useScrollHandlers("scrollview-1", actionSheetRef); const insets = useSafeAreaInsets(); + const viewShot = useRef(null); + + const onCapture = async () => { + const url = await viewShot.current.capture(); + + const ok = await Sharing.isAvailableAsync(); + if (ok) { + await Sharing.shareAsync( + "file://" + url, + (options = { mimeType: "image/jpeg", dialogTitle: "Share this image" }) + ); + } + }; + return ( { borderWidth: 1, }} > - + - - - - 列車遅延速報EX - - - {/* {doFetch()}}> - 最新の情報へ更新 - */} - - {getTime - ? getTime.toLocaleTimeString("ja-JP").split(":")[0] + - ":" + - getTime.toLocaleTimeString("ja-JP").split(":")[1] - : NaN}{" "} - - { - LayoutAnimation.easeInEaseOut(), setLoadingDelayData(true); - }} - /> - - + style={{ height: 26, width: "100%", backgroundColor: "#0099CC" }} + > + + - {loadingDelayData ? ( - - - - ) : delayData ? ( - delayData.map((d) => { - let data = d.split(" "); - return ( - - - {data[0].replace("\n", "")} - - {data[1]} - {data[3]} - - ); - }) - ) : ( - 現在、5分以上の遅れはありません。 - )} + + 列車遅延速報EX + + + {/* {doFetch()}}> + 最新の情報へ更新 + */} + + {getTime + ? getTime.toLocaleTimeString("ja-JP").split(":")[0] + + ":" + + getTime.toLocaleTimeString("ja-JP").split(":")[1] + : NaN}{" "} + + { + LayoutAnimation.easeInEaseOut(), setLoadingDelayData(true); + }} + /> + + + {loadingDelayData ? ( + + + + ) : delayData ? ( + delayData.map((d) => { + let data = d.split(" "); + return ( + + + {data[0].replace("\n", "")} + + {data[1]} + {data[3]} + + ); + }) + ) : ( + 現在、5分以上の遅れはありません。 + )} + - - - 列車遅延情報EXについて - - - 列車遅延情報をJR四国公式列車運行情報より5分毎に取得します。Twitterにて投稿している内容と同一のものとなります。 - - + + + 列車遅延情報EXについて + + + 列車遅延情報をJR四国公式列車運行情報より5分毎に取得します。Twitterにて投稿している内容と同一のものとなります。 + + + + + { margin: 10, borderRadius: 5, alignItems: "center", + backgroundColor: "#0099CC", + flex: 1, }} onPress={() => Linking.openURL("https://mstdn.y-zu.org/@JRSTraInfoEX") @@ -140,14 +178,30 @@ export const JRSTraInfo = () => { - MastodonBOTはこちら! + MastodonBOT - - → - - + + + + ); diff --git a/components/DynamicHeaderScrollView.js b/components/DynamicHeaderScrollView.js new file mode 100644 index 0000000..106e95a --- /dev/null +++ b/components/DynamicHeaderScrollView.js @@ -0,0 +1,106 @@ +import { ScrollView, View, Animated, Platform } from "react-native"; +import React, { useRef } from "react"; + +export const DynamicHeaderScrollView = (props) => { + const { + Max_Header_Height = 200, + Min_Header_Height = 80, + children, + scrollViewProps = {}, + containerProps = {}, + shortHeader = <>, + longHeader = <>, + topStickyContent, + styles, + } = props; + const scrollOffsetY = useRef(new Animated.Value(0)).current; + + const Scroll_Distance = Max_Header_Height - Min_Header_Height; + + const animatedHeaderHeight = scrollOffsetY.interpolate({ + inputRange: [Scroll_Distance, Scroll_Distance + 30], + outputRange: [Max_Header_Height, 0], + extrapolate: "clamp", + }); + const animatedHeaderHeight2 = scrollOffsetY.interpolate({ + inputRange: [Scroll_Distance, Scroll_Distance + 30], + outputRange: [Max_Header_Height, Min_Header_Height], + extrapolate: "clamp", + }); + const animatedHeaderVisible = scrollOffsetY.interpolate({ + inputRange: [Scroll_Distance - 30, Scroll_Distance], + outputRange: [1, 0], + extrapolate: "clamp", + }); + const animatedHeaderVisible2 = scrollOffsetY.interpolate({ + inputRange: [Scroll_Distance - 30, Scroll_Distance + 30], + outputRange: [0, 1], + extrapolate: "clamp", + }); + return ( + + + + {shortHeader} + + + {longHeader} + + + + + {topStickyContent && ( + + {topStickyContent} + + )} + {children} + + + ); +}; diff --git a/components/trainMenu.js b/components/trainMenu.js index 3069e1d..3702c6f 100644 --- a/components/trainMenu.js +++ b/components/trainMenu.js @@ -6,10 +6,11 @@ export default function TrainMenu({ navigation: { navigate }, webview, stationData, + style, }) { const mapRef = useRef(); return ( - + ); }) )} - - - navigate("howto", { - info: "https://train.jr-shikoku.co.jp/usage.htm", - }) - } + {navigate && ( + + + navigate("howto", { + info: "https://train.jr-shikoku.co.jp/usage.htm", + }) + } + > + 使い方 + + navigate("favoriteList")} + > + お気に入り + + + Linking.openURL( + "https://nexcloud.haruk.in/apps/forms/ZRHjWFF7znr5Xjr2" + ) + } + > + フィードバック + + + )} + {navigate && ( + navigate("Apps")} > - 使い方 - - navigate("favoriteList")} - > - お気に入り - - - Linking.openURL( - "https://nexcloud.haruk.in/apps/forms/ZRHjWFF7znr5Xjr2" - ) - } - > - この機能のフィードバック - - - navigate("Apps")} - > - - - 閉じる - - - + + + 閉じる + + + + )} ); } @@ -115,14 +120,14 @@ const UsefulBox = (props) => { style={{ flex: flex, backgroundColor: backgroundColor, - padding: 10, + padding: 5, alignItems: "center", margin: 2, }} onPress={onPressButton} > - + {children} diff --git a/eas.json b/eas.json index 2c0a80c..fe14a1e 100644 --- a/eas.json +++ b/eas.json @@ -29,6 +29,12 @@ }, "production4.6": { "channel": "costoco" + }, + "beta5.0": { + "channel": "dshopping" + }, + "production5.0": { + "channel": "dmm" } }, "submit": { diff --git a/lib/eachTrainInfoCoreLib/findReversalPoints.js b/lib/eachTrainInfoCoreLib/findReversalPoints.js new file mode 100644 index 0000000..05f6f55 --- /dev/null +++ b/lib/eachTrainInfoCoreLib/findReversalPoints.js @@ -0,0 +1,113 @@ +// arrayは現在位置の駅ID(駅在宅の場合は1つの配列、駅間の場合は2つの配列) +// stopStationIDListは停車駅の駅IDの配列 [Y01,Y02,Y05,...] +export const findReversalPoints = (array, stopStationIDList) => { + try { + if (!stopStationIDList) return []; + // arrayが二次元配列だったら早期リターン + if (!array instanceof Array) return []; + if (!array) return []; + if (array[0] instanceof Array) return []; + const arrayNumber = array.map((d) => ({ + line: d + .split("") + .filter((s) => "A" < s && s < "Z") + .join(""), + ID: d + .split("") + .filter((s) => "0" <= s && s <= "9") + .join(""), + })); + const stopStationIDListNumber = stopStationIDList.map((d) => { + if (!d) return { line: [], ID: [] }; + return { + line: d + .split("") + .filter((s) => "A" < s && s < "Z") + .join(""), + ID: d + .split("") + .filter((s) => "0" <= s && s <= "9") + .join(""), + }; + }); + // 完全一致 + if (array.length == 1) { + const index = stopStationIDList.indexOf(array[0]); + if (index != -1) return [index]; + // 通過駅の場合 + for (let i = 0; i < stopStationIDListNumber.length - 1; i++) { + if (stopStationIDListNumber[i].ID < arrayNumber[0].ID) { + if (stopStationIDListNumber[i + 1].ID > arrayNumber[0].ID) { + return [i + 1]; + } + } + if (stopStationIDListNumber[i].ID > arrayNumber[0].ID) { + if (stopStationIDListNumber[i + 1].ID < arrayNumber[0].ID) { + return [i + 1]; + } + } + } + } + // 駅間の場合 + if (array.length == 2) { + const index1 = stopStationIDList.indexOf(array[0]); + const index2 = stopStationIDList.indexOf(array[1]); + if (index1 != -1 && index2 != -1) { + // 駅間で通過駅も無い場合 + if (index1 < index2) { + if (index1 + 1 == index2) { + return [index2]; + } else { + const returnArray = []; + for (let i = index1 + 1; i <= index2; i++) { + returnArray.push(i); + } + return returnArray; + } + } + if (index1 > index2) { + if (index2 + 1 == index1) return [index1]; + else { + const returnArray = []; + for (let i = index2 + 1; i <= index1; i++) { + returnArray.push(i); + } + return returnArray; + } + } + } else { + const getNearStationID = (stationID) => { + for (let i = 0; i <= stopStationIDListNumber.length; i++) { + if (stopStationIDListNumber[i].ID < stationID) { + if (stopStationIDListNumber[i + 1].ID > stationID) { + return i + 1; + } + } + if (stopStationIDListNumber[i].ID > stationID) { + if (stopStationIDListNumber[i + 1].ID < stationID) { + return i + 1; + } + } + } + }; + let newIndex1 = index1; + let newIndex2 = index2; + if (index1 == -1) { + newIndex1 = getNearStationID(arrayNumber[0].ID); + } + if (index2 == -1) { + newIndex2 = getNearStationID(arrayNumber[1].ID); + } + if (newIndex1 && newIndex2) { + return [newIndex1, newIndex2]; + } + + // 通過駅の場合 + } + + return []; + } + } catch (e) { + console.log(e); + } +}; diff --git a/lib/eachTrainInfoCoreLib/getStationData.js b/lib/eachTrainInfoCoreLib/getStationData.js new file mode 100644 index 0000000..20b386a --- /dev/null +++ b/lib/eachTrainInfoCoreLib/getStationData.js @@ -0,0 +1,15 @@ +// 駅名から駅情報を取得する +//stationName: 駅名 +//stationList: 駅情報リスト +export const getStationData = (stationName, stationList) => { + const Stations = stationList.map((a) => + a.filter((d) => d.StationName == stationName) + ); + const Station = + Stations && + Stations.reduce((newArray, e) => { + return newArray.concat(e); + }, []); + if (!Station[0]) return []; + return Station.map((d) => d.StationNumber)[0]; +}; diff --git a/lib/eachTrainInfoCoreLib/getType.js b/lib/eachTrainInfoCoreLib/getType.js new file mode 100644 index 0000000..d989461 --- /dev/null +++ b/lib/eachTrainInfoCoreLib/getType.js @@ -0,0 +1,11 @@ +// 種別判定 +export const getType = (string) => { + switch (string) { + case "express": + return "特急"; + case "rapid": + return "快速"; + default: + return ""; + } +}; diff --git a/lib/eachTrainInfoCoreLib/migrateTrainName.js b/lib/eachTrainInfoCoreLib/migrateTrainName.js new file mode 100644 index 0000000..88e0a26 --- /dev/null +++ b/lib/eachTrainInfoCoreLib/migrateTrainName.js @@ -0,0 +1,7 @@ +// Description: 電車名の変換を行う。 +// マリンライナーやマリン表記をマリンライナーに変換する。 +export const migrateTrainName = (string) => { + return string + .replace("マリン", "マリンライナー") + .replace("ライナーライナー", "ライナー"); +}; diff --git a/lib/eachTrainInfoCoreLib/openBackTrainInfo.js b/lib/eachTrainInfoCoreLib/openBackTrainInfo.js new file mode 100644 index 0000000..8b5944b --- /dev/null +++ b/lib/eachTrainInfoCoreLib/openBackTrainInfo.js @@ -0,0 +1,68 @@ +export const openBackTrainInfo = (stationInfo, trainData, showNearTrain) => { + const migrationArray = (stationInfo) => { + const mainTrainStationPosition = trainData.findIndex( + (d) => d.split(",")[0] == stationInfo + ); + + const relationMain = (() => { + if (mainTrainStationPosition == 0) return "head"; + if (mainTrainStationPosition == trainData.length - 1) return "tail"; + return "middle"; + })(); + + const subTrainStationPosition = showNearTrain.findIndex( + (d) => d.split(",")[0] == stationInfo + ); + const relationSub = (() => { + if (subTrainStationPosition == 0) return "head"; + if (subTrainStationPosition == showNearTrain.length - 1) return "tail"; + return "middle"; + })(); + + switch (relationMain) { + case "head": + if (relationSub == "head") { + return; + } else if (relationSub == "tail") { + return [ + ...showNearTrain.slice(0, subTrainStationPosition), + ...trainData, + ]; + } else if (relationSub == "middle") { + return [ + ...showNearTrain.slice(0, subTrainStationPosition), + ...trainData, + ]; + } else return; + case "tail": + if (relationSub == "head") { + return [ + ...trainData.slice(0, mainTrainStationPosition), + ...showNearTrain, + ]; + } else if (relationSub == "tail") { + return; + } else if (relationSub == "middle") { + return [ + ...trainData.slice(0, mainTrainStationPosition), + ...showNearTrain.slice(subTrainStationPosition), + ]; + } else return; + case "middle": + if (relationSub == "head") { + return [ + ...trainData.slice(0, mainTrainStationPosition), + ...showNearTrain, + ]; + } else if (relationSub == "tail") { + return [ + ...showNearTrain.slice(0, subTrainStationPosition), + ...trainData.slice(mainTrainStationPosition), + ]; + } else return; + } + }; + const array = migrationArray(stationInfo); + if (!array) return null; + return array; +}; diff --git a/lib/eachTrainInfoCoreLib/searchSpecialTrain.js b/lib/eachTrainInfoCoreLib/searchSpecialTrain.js new file mode 100644 index 0000000..ec0e53d --- /dev/null +++ b/lib/eachTrainInfoCoreLib/searchSpecialTrain.js @@ -0,0 +1,13 @@ +// S列番の列車からDやMの列車を検索する +export const searchSpecialTrain = (trainNum, trainList) => { + const searchBase = trainNum.replace("S", "").replace("X", ""); + const search = (text) => { + const TD = trainList[searchBase + text]; + if (TD) { + return true; + } + return false; + }; + if (search("D")) return searchBase + "D"; + if (search("M")) return searchBase + "M"; +}; diff --git a/package.json b/package.json index 483733c..bb9b5d2 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "expo-font": "~11.4.0", "expo-location": "~16.1.0", "expo-notifications": "~0.20.1", + "expo-sharing": "~11.5.0", "expo-updates": "~0.18.17", "expo-web-browser": "~12.3.2", "firebase": "8.2.3", @@ -45,6 +46,7 @@ "react-native-svg": "13.9.0", "react-native-svg-uri": "^1.2.3", "react-native-vector-icons": "^8.1.0", + "react-native-view-shot": "3.7.0", "react-native-webview": "^13.6.3" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 25ac5f9..f14e0f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3439,6 +3439,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base64-arraybuffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc" + integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ== + base64-js@^1.1.2, base64-js@^1.2.3, base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -4202,6 +4207,13 @@ crypto-random-string@^2.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== +css-line-break@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-line-break/-/css-line-break-2.1.0.tgz#bfef660dfa6f5397ea54116bb3cb4873edbc4fa0" + integrity sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w== + dependencies: + utrie "^1.0.2" + css-select@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" @@ -4881,6 +4893,11 @@ expo-notifications@~0.20.1: fs-extra "^9.1.0" uuid "^3.4.0" +expo-sharing@~11.5.0: + version "11.5.0" + resolved "https://registry.yarnpkg.com/expo-sharing/-/expo-sharing-11.5.0.tgz#a8cad65874d882b7f75b12856b4ef55ea9b60a2d" + integrity sha512-uerM5YH1FKDZXfkP9ORebvlMVOPP/AfoYgYBez6a8G9fztNYHnRCA6mgK+3aQmpnb3ltmjnAZC39kH18bTNcVw== + expo-structured-headers@~3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/expo-structured-headers/-/expo-structured-headers-3.3.0.tgz#9f0b041a1d243a22a4a23d9eb19f02ace3c5258c" @@ -5653,6 +5670,14 @@ hosted-git-info@^4.0.1, hosted-git-info@^4.0.2: dependencies: lru-cache "^6.0.0" +html2canvas@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/html2canvas/-/html2canvas-1.4.1.tgz#7cef1888311b5011d507794a066041b14669a543" + integrity sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA== + dependencies: + css-line-break "^2.1.0" + text-segmentation "^1.0.3" + http-cache-semantics@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" @@ -8858,6 +8883,13 @@ react-native-vector-icons@^8.1.0: prop-types "^15.7.2" yargs "^16.1.1" +react-native-view-shot@3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/react-native-view-shot/-/react-native-view-shot-3.7.0.tgz#0c773500e7aac5d115a9dee3b83fa5156c950ed0" + integrity sha512-tQruLNjs7Ee/p6xUgJqF6glnatHaq/UqaIQ6KdYIFG0+XpUZdhqmEM4WMLsYfayfFEhdlF86G1S3eXMOfDNzFg== + dependencies: + html2canvas "^1.4.1" + react-native-webview@^13.6.3: version "13.6.3" resolved "https://registry.yarnpkg.com/react-native-webview/-/react-native-webview-13.6.3.tgz#f3d26e942ef5cc5a07547f2e47903aa81a68e25e" @@ -9913,6 +9945,13 @@ terser@^5.15.0: commander "^2.20.0" source-map-support "~0.5.20" +text-segmentation@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/text-segmentation/-/text-segmentation-1.0.3.tgz#52a388159efffe746b24a63ba311b6ac9f2d7943" + integrity sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw== + dependencies: + utrie "^1.0.2" + text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -10267,6 +10306,13 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== +utrie@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/utrie/-/utrie-1.0.2.tgz#d42fe44de9bc0119c25de7f564a6ed1b2c87a645" + integrity sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw== + dependencies: + base64-arraybuffer "^1.0.2" + uuid@9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5"