Files
jrshikoku/components/ActionSheetComponents/EachTrainInfoCore.tsx

342 lines
11 KiB
TypeScript

import React, { useEffect, useRef, useState } from "react";
import {
View,
Text,
TouchableOpacity,
StyleSheet,
useWindowDimensions,
BackHandler,
Linking,
} from "react-native";
import { SheetManager } from "react-native-actions-sheet";
import { getTrainType } from "../../lib/getTrainType";
import { customTrainDataDetector } from "../custom-train-data";
import { useDeviceOrientationChange } from "../../stateBox/useDeviceOrientationChange";
import { EachStopList } from "./EachTrainInfo/EachStopList";
import { DataConnectedButton } from "./EachTrainInfo/DataConnectedButton";
import { DynamicHeaderScrollView } from "../DynamicHeaderScrollView";
import { LongHeader } from "./EachTrainInfo/LongHeader";
import { ShortHeader } from "./EachTrainInfo/ShortHeader";
import { ScrollStickyContent } from "./EachTrainInfo/ScrollStickyContent";
import { ShowSpecialTrain } from "./EachTrainInfo/ShowSpecialTrain";
import { useTrainMenu } from "../../stateBox/useTrainMenu";
import { HeaderText } from "./EachTrainInfoCore/HeaderText";
import { useStationList } from "../../stateBox/useStationList";
import { useThemeColors } from "@/lib/theme";
import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
// Custom hooks
import { useTrainDiagramData } from "./EachTrainInfoCore/hooks/useTrainDiagramData";
import { useThroughStations } from "./EachTrainInfoCore/hooks/useThroughStations";
import { useNearbyTrains } from "./EachTrainInfoCore/hooks/useNearbyTrains";
import { useStopStationIDs } from "./EachTrainInfoCore/hooks/useStopStationIDs";
import { useTrainPosition } from "./EachTrainInfoCore/hooks/useTrainPosition";
import { useAutoScroll } from "./EachTrainInfoCore/hooks/useAutoScroll";
import { useExtendedStations } from "./EachTrainInfoCore/hooks/useExtendedStations";
export const EachTrainInfoCore = ({
actionSheetRef,
data,
openStationACFromEachTrainInfo,
from,
navigate,
}) => {
const { stationList } = useStationList();
const { allCustomTrainData } = useAllTrainDiagram();
const { colors, fixed } = useThemeColors();
const { setTrainInfo } = useTrainMenu();
const { height } = useWindowDimensions();
const { isLandscape } = useDeviceOrientationChange();
const scrollRef = useRef<any>(null);
// Custom hooks for data management
const { trainData, setTrainData, trueTrainID } = useTrainDiagramData(
data.trainNum
);
const { trainDataWithThrough, haveThrough } = useThroughStations(trainData);
const { headStation, tailStation, nearTrainIDList } = useNearbyTrains(
data.trainNum,
trainData
);
const stopStationIDList = useStopStationIDs(trainDataWithThrough);
const { currentTrainData, currentPosition, points, pointsDisplay } =
useTrainPosition(data.trainNum, stopStationIDList);
const {
showHeadStation,
showTailStation,
extendToHeadStation,
extendToTailStation,
} = useExtendedStations(trainData, setTrainData);
// UI state
const [showThrew, setShowThrew] = useState(false);
const [isJumped, setIsJumped] = useState(false);
// Auto scroll to current position
useAutoScroll(
points,
trainDataWithThrough,
scrollRef,
isJumped,
setIsJumped,
setShowThrew
);
// Back button handler
useEffect(() => {
const backAction = () => {
SheetManager.hide("EachTrainInfo");
return true;
};
const backHandler = BackHandler.addEventListener(
"hardwareBackPress",
backAction
);
return () => backHandler.remove();
}, []);
const customTrainType = getTrainType({
type: customTrainDataDetector(data.trainNum, allCustomTrainData).type,
});
const openTrainInfo = (trainNum) => {
const train = customTrainDataDetector(trainNum, allCustomTrainData);
let trainNumber = "";
if (train.train_num_distance && !isNaN(Number(train.train_num_distance))) {
const numericPart = parseInt(trainNum.replace("M", "").replace("D", ""));
trainNumber = `${numericPart - Number(train.train_num_distance)}`;
}
const limitedData = getTrainType({ type: train.type });
const payload = {
data: {
trainNum,
limited: `${limitedData.data}:${train.train_name}${trainNumber}`,
},
navigate,
from: from === "LED" ? "LED2" : "NearTrainDiagramView",
};
if (isLandscape) {
setTrainInfo(payload.data);
} else {
SheetManager.hide("EachTrainInfo").then(() => {
setTimeout(() => {
SheetManager.show("EachTrainInfo", { payload });
}, 200);
});
}
};
return (
<View
style={{
backgroundColor: fixed.primary,
borderTopLeftRadius: 5,
borderTopRightRadius: 5,
borderColor: colors.border,
borderWidth: 1,
}}
>
<View style={{ height: 26, width: "100%" }}>
<View
style={{
height: 6,
width: 45,
borderRadius: 100,
backgroundColor: colors.borderLight,
marginVertical: 10,
alignSelf: "center",
}}
/>
</View>
<HeaderText
data={data}
trainData={trainData}
showHeadStation={showHeadStation}
showTailStation={showTailStation}
headStation={headStation}
tailStation={tailStation}
navigate={navigate}
from={from}
fontLoaded={true}
scrollRef={scrollRef}
/>
<DynamicHeaderScrollView
from={from}
styles={styles as any}
scrollRef={scrollRef}
containerProps={{
style: {
maxHeight: isLandscape ? height - 94 : (height / 100) * 70,
backgroundColor:
customTrainType.data === "notService" ? "#777777ff" : colors.surface,
},
}}
shortHeader={
<ShortHeader
{...{
currentTrainData,
currentPosition,
nearTrainIDList,
openTrainInfo,
navigate,
}}
/>
}
longHeader={
<LongHeader
{...{
currentTrainData,
currentPosition,
nearTrainIDList,
openTrainInfo,
navigate,
}}
/>
}
topStickyContent={
<ScrollStickyContent
{...{ currentTrainData, showThrew, setShowThrew, haveThrough }}
/>
}
>
{customTrainType.data === "notService" && (
<Text style={{ backgroundColor: colors.surface, fontWeight: "bold" }}>
</Text>
)}
{headStation.length > 0 &&
headStation.map(
(item, index) =>
!showHeadStation.includes(index) && (
<TouchableOpacity
onPress={() =>
extendToHeadStation(item.station, item.dia, index)
}
style={[styles.extendStationButton, { borderColor: colors.textAccent }]}
key={`${item.station}-head${index}`}
>
<Text style={[styles.extendStationText, { color: colors.text }]}>
</Text>
</TouchableOpacity>
)
)}
<ShowSpecialTrain
isTrainDataNothing={trainData.length === 0}
setTrainData={setTrainData}
trueTrainID={trueTrainID}
/>
{!trainData.length && (
<TouchableOpacity
onPress={() =>
Linking.openURL(`https://twitter.com/search?q=${data.trainNum}`)
}
style={[styles.twitterSearchButton, { borderColor: colors.textAccent, backgroundColor: colors.backgroundOverlay }]}
>
<Text style={[styles.extendStationText, { color: colors.text }]}>Twitterで検索</Text>
</TouchableOpacity>
)}
{trainDataWithThrough.map((item, index, array) =>
item.split(",")[1] === "増" || item.split(",")[1] === "解" ? (
<DataConnectedButton
i={item}
key={`${item}-data`}
openTrainInfo={openTrainInfo}
/>
) : item.split(",")[1].includes(".") ? (
<React.Fragment key={`${item}-skip`} />
) : (
<EachStopList
i={item}
index={index}
stationList={stationList as any}
points={pointsDisplay?.[index] || false}
currentTrainData={currentTrainData as any}
openStationACFromEachTrainInfo={openStationACFromEachTrainInfo}
showThrew={showThrew}
array={array}
isNotService={customTrainType.data === "notService"}
key={`${item}-stop`}
/>
)
)}
<Text style={[styles.customDataNote, { color: colors.textSecondary }]}>
,
</Text>
{tailStation.length > 0 &&
tailStation.map(
({ station, dia }, index) =>
!showTailStation.includes(index) && (
<TouchableOpacity
onPress={() => extendToTailStation(station, dia, index)}
style={[styles.extendStationButton, { borderColor: colors.textAccent }]}
key={`${station}-tail${index}`}
>
<Text style={[styles.extendStationText, { color: colors.text }]}>
</Text>
</TouchableOpacity>
)
)}
<View style={[styles.bottomSpacer, { borderBottomColor: colors.borderLight }]} />
</DynamicHeaderScrollView>
</View>
);
};
const styles = StyleSheet.create({
header: {
justifyContent: "center",
alignItems: "center",
left: 0,
right: 0,
position: "absolute",
zIndex: 1,
backgroundColor: "f0f0f0",
},
headerText: {
color: "#fff",
fontSize: 25,
fontWeight: "bold",
textAlign: "center",
},
extendStationButton: {
padding: 10,
flexDirection: "row",
borderColor: "blue",
borderWidth: 1,
margin: 10,
borderRadius: 5,
alignItems: "center",
},
extendStationText: {
fontSize: 18,
fontWeight: "bold",
},
twitterSearchButton: {
padding: 10,
flexDirection: "row",
borderColor: "blue",
borderWidth: 1,
margin: 10,
borderRadius: 5,
alignItems: "center",
backgroundColor: "#ffffffc2",
},
customDataNote: {
},
bottomSpacer: {
flexDirection: "row",
padding: 8,
borderBottomWidth: 1,
borderBottomColor: "#f0f0f0",
flex: 1,
},
});