jrshikoku/Apps.js

513 lines
14 KiB
JavaScript

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";
import { injectJavascriptData } from "./lib/webViewInjectjavascript";
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);
const [mapSwitch, setMapSwitch] = useState(undefined);
const [stationMenu, setStationMenu] = useState(undefined);
const [LoadError, setLoadError] = useState(false);
//列車情報表示関連
const [trainInfo, setTrainInfo] = useState({
trainNum: undefined,
limited: undefined,
trainData: undefined,
});
//駅情報画面用
const [originalStationList, setOriginalStationList] = useState();
const [trainMenu, setTrainMenu] = useState("true");
let once = false;
useEffect(() => {
getStationList().then(setOriginalStationList);
}, []);
//地図表示テキスト
const injectJavascript = injectJavascriptData(
mapSwitch,
iconSetting,
stationMenu,
trainMenu
);
useEffect(() => {
//ニュース表示
AS.getItem("status")
.then((d) => {
if (d != news) navigate("news");
})
.catch(() => navigate("news"));
}, []);
useEffect(() => {
//列車アイコンスイッチ
AS.getItem("iconSwitch")
.then((d) => {
if (d) {
setIconSetting(d);
} else {
AS.setItem("iconSwitch", "true").then(Updates.reloadAsync);
}
})
.catch(() => AS.setItem("iconSwitch", "true").then(Updates.reloadAsync));
}, []);
useEffect(() => {
//地図スイッチ
AS.getItem("mapSwitch")
.then((d) => {
if (d) {
setMapSwitch(d);
} else {
AS.setItem("mapSwitch", "false").then(Updates.reloadAsync);
}
})
.catch(() => AS.setItem("mapSwitch", "false").then(Updates.reloadAsync));
}, []);
useEffect(() => {
//駅メニュースイッチ
AS.getItem("stationSwitch")
.then((d) => {
if (d) {
setStationMenu(d);
} else {
AS.setItem("stationSwitch", "true").then(Updates.reloadAsync);
}
})
.catch(() =>
AS.setItem("stationSwitch", "true").then(Updates.reloadAsync)
);
}, []);
useEffect(() => {
//列車メニュースイッチ
AS.getItem("trainSwitch")
.then((d) => {
if (d) {
setTrainMenu(d);
} else {
AS.setItem("trainSwitch", "true").then(Updates.reloadAsync);
}
})
.catch(() => AS.setItem("trainSwitch", "true").then(Updates.reloadAsync));
}, []);
const onMessage = (event) => {
if (event.nativeEvent.data.includes("train.html")) {
navigate("trainbase", { info: event.nativeEvent.data, from: "Train" });
return;
}
if (!originalStationList) {
alert("駅名標データを取得中...");
return;
}
const dataSet = JSON.parse(event.nativeEvent.data);
switch (dataSet.type) {
case "LoadError": {
setLoadError(true);
return;
}
case "PopUpMenu":
{
const selectedStationPDFAddress = dataSet.pdf;
const findStationEachLine = (selectLine) => {
let NearStation = selectLine.filter(
(d) => d.StationTimeTable == selectedStationPDFAddress
);
return NearStation;
};
let returnDataBase = lineList
.map((d) => findStationEachLine(originalStationList[d]))
.filter((d) => d.length > 0)
.reduce((pre, current) => {
pre.push(...current);
return pre;
}, []);
if (returnDataBase.length) {
const payload = {
currentStation: returnDataBase,
originalStationList: originalStationList,
navigate: navigate,
goTo: "Apps",
useShow: () =>
SheetManager.show("StationDetailView", {
payload,
}),
onExit: () => {
SheetManager.hide("StationDetailView");
},
};
SheetManager.show("StationDetailView", {
payload,
});
}
}
return;
case "ShowTrainTimeInfo": {
const { trainNum, limited } = dataSet;
//alert(trainNum, limited);
LayoutAnimation.easeInEaseOut();
setTrainInfo({
trainNum,
limited,
trainData: checkDuplicateTrainData(
currentTrain.filter((a) => a.num == trainNum)
),
}); //遅延情報は未実装
if (isLandscape) return;
const payload = {
data: {
trainNum,
limited,
},
navigate,
originalStationList,
openStationACFromEachTrainInfo,
};
SheetManager.show("EachTrainInfo", {
payload,
});
return;
}
default: {
return;
}
}
};
const onNavigationStateChange = (event) => {
if (event.url != urlcache) {
//URL二重判定回避
urlcache = event.url;
if (event.url.includes("https://train.jr-shikoku.co.jp/usage.htm")) {
if (Platform.OS === "android") navigate("howto", { info: event.url });
webview?.current.goBack();
//Actions.howto();
} else if (
event.url.includes("https://train.jr-shikoku.co.jp/train.html")
) {
//Actions.trainbase({info: event.url});
if (Platform.OS === "android")
navigate("trainbase", { info: event.url });
webview?.current.goBack();
}
}
};
function sleep(waitSec, callbackFunc) {
// 経過時間(秒)
var spanedSec = 0;
// 1秒間隔で無名関数を実行
var id = setInterval(function () {
spanedSec++;
// 経過時間 >= 待機時間の場合、待機終了。
if (spanedSec >= waitSec) {
// タイマー停止
clearInterval(id);
// 完了時、コールバック関数を実行
if (callbackFunc) callbackFunc();
}
}, 1);
}
const openStationACFromEachTrainInfo = async (stationName) => {
await SheetManager.hide("EachTrainInfo");
const findStationEachLine = (selectLine) => {
let NearStation = selectLine.filter((d) => d.Station_JP == stationName);
return NearStation;
};
let returnDataBase = lineList
.map((d) => findStationEachLine(originalStationList[d]))
.filter((d) => d.length > 0)
.reduce((pre, current) => {
pre.push(...current);
return pre;
}, []);
if (returnDataBase.length) {
const payload = {
currentStation: returnDataBase,
originalStationList: originalStationList,
navigate: navigate,
goTo: "Apps",
useShow: () =>
SheetManager.show("StationDetailView", {
payload,
}),
onExit: () => {
SheetManager.hide("StationDetailView");
},
};
SheetManager.show("StationDetailView", {
payload,
});
} else {
SheetManager.hide("StationDetailView");
}
};
return (
<View
style={{
height: "100%",
paddingTop: Platform.OS == "ios" ? Constants.statusBarHeight : 0,
flexDirection: isLandscape ? "row" : "column",
}}
onLayout={handleLayout}
>
{!trainInfo.trainNum && isLandscape ? (
<TrainMenu
webview={webview}
stationData={stationData}
navigation={{ navigate: null }}
style={{
width: (width / 100) * 40,
height: "100%",
flexDirection: "column-reverse",
}}
/>
) : null}
{/* {Status} */}
<WebView
useWebKit
ref={webview}
source={{ uri: "https://train.jr-shikoku.co.jp/sp.html" }}
originWhitelist={[
"https://train.jr-shikoku.co.jp",
"https://train.jr-shikoku.co.jp/sp.html",
]}
mixedContentMode={"compatibility"}
javaScriptEnabled
allowsBackForwardNavigationGestures
setSupportMultipleWindows
onNavigationStateChange={onNavigationStateChange}
onMessage={onMessage}
injectedJavaScript={injectJavascript}
onLoadEnd={() => {
if (once) return () => {};
if (!stationData) return () => {};
if (favoriteStation.length > 0) {
const getStationLine = (now) => {
const returnData = Object.keys(stationData).filter((d) => {
const cache = stationData[d].findIndex(
(data) => data.Station_JP == now.Station_JP
);
return cache != -1;
});
return returnData[0];
};
const lineName = getStationLine(favoriteStation[0][0]);
webview.current?.injectJavaScript(
`MoveDisplayStation('${lineName}_${favoriteStation[0][0].MyStation}_${favoriteStation[0][0].Station_JP}')`
);
once = true;
}
}}
/>
{isLandscape && trainInfo.trainNum && (
<View
style={{
width: (width / 100) * 40,
height: height,
flexDirection: "column",
}}
>
<EachTrainInfoCore
{...{
data: trainInfo.trainNum ? trainInfo : undefined,
navigate,
originalStationList,
openStationACFromEachTrainInfo,
from: "Train",
setTrainInfo,
}}
/>
</View>
)}
{isLandscape || (
<MapsButton
onPress={() => navigate("trainMenu", { webview })}
top={Platform.OS == "ios" ? Constants.statusBarHeight : 0}
mapSwitch={mapSwitch == "true" ? "flex" : "none"}
/>
)}
{isLandscape && trainInfo.trainNum && (
<LandscapeBackButton
onPress={() => {
LayoutAnimation.easeInEaseOut();
setTrainInfo({
trainNum: undefined,
limited: undefined,
trainData: undefined,
});
}}
top={Platform.OS == "ios" ? Constants.statusBarHeight : 0}
/>
)}
<ReloadButton
onPress={() => webview.current.reload()}
top={Platform.OS == "ios" ? Constants.statusBarHeight : 0}
right={isLandscape && trainInfo.trainNum ? (width / 100) * 40 : 0}
LoadError={LoadError}
/>
</View>
);
}
const MapsButton = ({ onPress, top, mapSwitch }) => {
const styles = {
touch: {
position: "absolute",
top,
left: 10,
width: 50,
height: 50,
backgroundColor: "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
borderRadius: 50,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
display: mapSwitch,
},
text: {
textAlign: "center",
width: "auto",
height: "auto",
textAlignVertical: "center",
fontWeight: "bold",
color: "white",
},
};
return (
<TouchableOpacity onPress={onPress} style={styles.touch}>
<View style={{ flex: 1 }} />
<Text style={styles.text}></Text>
<View style={{ flex: 1 }} />
</TouchableOpacity>
);
};
const LandscapeBackButton = ({ onPress, top }) => {
const styles = {
touch: {
position: "absolute",
top,
left: 10,
width: 50,
height: 50,
backgroundColor: "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
borderRadius: 50,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
display: "flex",
},
text: {
textAlign: "center",
width: "auto",
height: "auto",
textAlignVertical: "center",
fontWeight: "bold",
color: "white",
},
};
return (
<TouchableOpacity onPress={onPress} style={styles.touch}>
<View style={{ flex: 1 }} />
<Ionicons name="arrow-back" color="white" size={30} />
<View style={{ flex: 1 }} />
</TouchableOpacity>
);
};
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",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
borderRadius: 50,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
display: mapSwitch,
},
text: {
textAlign: "center",
width: "auto",
height: "auto",
textAlignVertical: "center",
fontWeight: "bold",
color: "white",
},
};
return (
<TouchableOpacity onPress={onPress} style={styles.touch}>
<View style={{ flex: 1 }} />
<Ionicons name="reload" color="white" size={30} />
<View style={{ flex: 1 }} />
</TouchableOpacity>
);
};