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"