295 lines
8.4 KiB
TypeScript
295 lines
8.4 KiB
TypeScript
import React, { FC, useMemo } from "react";
|
||
import {
|
||
Text,
|
||
View,
|
||
TextStyle,
|
||
TouchableOpacity,
|
||
useWindowDimensions,
|
||
} from "react-native";
|
||
import { SheetManager } from "react-native-actions-sheet";
|
||
import { migrateTrainName } from "../../../lib/eachTrainInfoCoreLib/migrateTrainName";
|
||
import { TrainIconStatus } from "./trainIconStatus";
|
||
import { OneManText } from "./HeaderTextParts/OneManText";
|
||
import { customTrainDataDetector } from "@/components/custom-train-data";
|
||
import { InfogramText } from "@/components/ActionSheetComponents/EachTrainInfoCore/HeaderTextParts/InfogramText";
|
||
import { useTrainMenu } from "@/stateBox/useTrainMenu";
|
||
import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
|
||
import { useNotification } from "@/stateBox/useNotifications";
|
||
import { getStringConfig } from "@/lib/getStringConfig";
|
||
import { MaterialCommunityIcons } from "@expo/vector-icons";
|
||
import { getPDFViewURL } from "@/lib/getPdfViewURL";
|
||
import type { NavigateFunction } from "@/types";
|
||
import { useUnyohub } from "@/stateBox/useUnyohub";
|
||
|
||
type Props = {
|
||
data: { trainNum: string; limited: string };
|
||
trainData: string[];
|
||
showHeadStation: number[];
|
||
showTailStation: number[];
|
||
headStation: { id: string }[];
|
||
tailStation: { id: string }[];
|
||
navigate: NavigateFunction;
|
||
from: string;
|
||
fontLoaded: boolean;
|
||
scrollHandlers: any;
|
||
};
|
||
|
||
const textConfig: TextStyle = {
|
||
fontSize: 17,
|
||
fontWeight: "bold",
|
||
color: "white",
|
||
};
|
||
|
||
export const HeaderText: FC<Props> = ({
|
||
data,
|
||
trainData,
|
||
showHeadStation,
|
||
showTailStation,
|
||
headStation,
|
||
tailStation,
|
||
navigate,
|
||
from,
|
||
scrollHandlers,
|
||
}) => {
|
||
const { limited, trainNum } = data;
|
||
|
||
const { height, width } = useWindowDimensions();
|
||
const { updatePermission } = useTrainMenu();
|
||
const { allCustomTrainData, getTodayOperationByTrainId } =
|
||
useAllTrainDiagram();
|
||
const { expoPushToken } = useNotification();
|
||
const { getUnyohubByTrainNumber, getUnyohubEntriesByTrainNumber, useUnyohub: unyohubEnabled } = useUnyohub();
|
||
|
||
// 追加ソースのON/OFFをここで管理(将来ソースが増えたらここに足す)
|
||
const additionalSources = {
|
||
unyohub: unyohubEnabled,
|
||
// exampleSource: exampleEnabled,
|
||
};
|
||
const hasAdditionalSources = Object.values(additionalSources).some(Boolean);
|
||
|
||
// 列車名、種別、フォントの取得
|
||
const [
|
||
typeName,
|
||
trainName,
|
||
fontAvailable,
|
||
isOneMan,
|
||
infogram,
|
||
priority,
|
||
uwasa,
|
||
trainInfoUrl,
|
||
directions,
|
||
customTrainData,
|
||
] = useMemo(() => {
|
||
const result = customTrainDataDetector(trainNum, allCustomTrainData);
|
||
const {
|
||
type,
|
||
train_name,
|
||
train_num_distance,
|
||
infogram,
|
||
priority,
|
||
uwasa,
|
||
train_info_url,
|
||
to_data,
|
||
directions,
|
||
} = result;
|
||
const [typeString, fontAvailable, isOneMan] = getStringConfig(
|
||
type,
|
||
trainNum,
|
||
);
|
||
switch (true) {
|
||
case train_name !== "":
|
||
return [
|
||
typeString,
|
||
train_name +
|
||
(train_num_distance !== "" && !isNaN(parseInt(train_num_distance))
|
||
? ` ${parseInt(trainNum) - parseInt(train_num_distance)}号`
|
||
: ""),
|
||
fontAvailable,
|
||
isOneMan,
|
||
infogram,
|
||
priority,
|
||
uwasa,
|
||
train_info_url,
|
||
directions,
|
||
result,
|
||
];
|
||
case trainData[trainData.length - 1] === undefined:
|
||
return [
|
||
typeString,
|
||
"",
|
||
fontAvailable,
|
||
isOneMan,
|
||
infogram,
|
||
priority,
|
||
uwasa,
|
||
train_info_url,
|
||
directions,
|
||
result,
|
||
];
|
||
case to_data && to_data !== "":
|
||
return [
|
||
typeString,
|
||
to_data + "行き",
|
||
fontAvailable,
|
||
isOneMan,
|
||
infogram,
|
||
priority,
|
||
uwasa,
|
||
train_info_url,
|
||
directions,
|
||
result,
|
||
];
|
||
default:
|
||
return [
|
||
typeString,
|
||
migrateTrainName(
|
||
trainData[trainData.length - 1].split(",")[0] + "行き",
|
||
),
|
||
fontAvailable,
|
||
isOneMan,
|
||
infogram,
|
||
priority,
|
||
uwasa,
|
||
train_info_url,
|
||
directions,
|
||
result,
|
||
];
|
||
}
|
||
}, [trainData]);
|
||
|
||
const todayOperation = getTodayOperationByTrainId(trainNum).filter(
|
||
(d) => d.state !== 100,
|
||
);
|
||
|
||
let iconTrainDirection =
|
||
parseInt(trainNum.replace(/[^\d]/g, "")) % 2 == 0 ? true : false;
|
||
if (directions != undefined) {
|
||
iconTrainDirection = directions ? true : false;
|
||
}
|
||
|
||
const unyohubFormation = getUnyohubByTrainNumber(trainNum);
|
||
const unyohubEntries = getUnyohubEntriesByTrainNumber(trainNum);
|
||
|
||
const hasExtraInfo =
|
||
priority > 200 || todayOperation?.length > 0 || !!unyohubFormation;
|
||
|
||
return (
|
||
<View
|
||
style={{ padding: 10, flexDirection: "row", alignItems: "center" }}
|
||
onTouchStart={() =>
|
||
scrollHandlers.ref.current?.scrollTo({ y: 0, animated: true })
|
||
}
|
||
>
|
||
<TrainIconStatus
|
||
data={data}
|
||
navigate={navigate}
|
||
from={from}
|
||
todayOperation={todayOperation}
|
||
direction={iconTrainDirection}
|
||
/>
|
||
<TouchableOpacity
|
||
style={{
|
||
borderRadius: 5,
|
||
flexDirection: "row",
|
||
alignItems: "center",
|
||
...(trainInfoUrl
|
||
? {
|
||
borderWidth: 0,
|
||
borderBottomWidth: 1,
|
||
borderStyle: "solid",
|
||
borderColor: "white",
|
||
}
|
||
: {}),
|
||
}}
|
||
onPress={() => {
|
||
if (!trainInfoUrl) return;
|
||
const uri = trainInfoUrl.includes("pdf")
|
||
? getPDFViewURL(trainInfoUrl)
|
||
: trainInfoUrl;
|
||
navigate("generalWebView", { uri, useExitButton: true });
|
||
SheetManager.hide("EachTrainInfo");
|
||
}}
|
||
disabled={!trainInfoUrl}
|
||
>
|
||
<Text
|
||
style={{
|
||
fontSize: 20,
|
||
color: "white",
|
||
fontFamily: fontAvailable ? "JR-Nishi" : undefined,
|
||
fontWeight: !fontAvailable ? "bold" : undefined,
|
||
marginRight: 5,
|
||
}}
|
||
>
|
||
{typeName}
|
||
</Text>
|
||
{isOneMan && <OneManText />}
|
||
<Text
|
||
style={{
|
||
...textConfig,
|
||
...(trainName.length > 10 ? { fontSize: 14 } : {}),
|
||
maxWidth: width * 0.6,
|
||
}}
|
||
>
|
||
{trainName}
|
||
</Text>
|
||
<InfogramText infogram={infogram} />
|
||
{/* {trainInfoUrl && (
|
||
<MaterialCommunityIcons
|
||
name={"open-in-new"}
|
||
color="white"
|
||
size={15}
|
||
/>
|
||
)} */}
|
||
</TouchableOpacity>
|
||
|
||
<View style={{ flex: 1 }} />
|
||
<TouchableOpacity
|
||
onLongPress={() => {
|
||
if (!updatePermission) return;
|
||
const uri = `https://jr-shikoku-data-system.pages.dev/trainData/${trainNum}?userID=${expoPushToken}&from=eachTrainInfo`;
|
||
navigate("generalWebView", { uri, useExitButton: false });
|
||
SheetManager.hide("EachTrainInfo");
|
||
}}
|
||
disabled={!updatePermission}
|
||
>
|
||
<Text style={textConfig}>
|
||
{showHeadStation.map((d) => `${headStation[d].id} + `)}
|
||
{trainNum}
|
||
{showTailStation.map((d) => ` + ${tailStation[d].id}`)}
|
||
</Text>
|
||
</TouchableOpacity>
|
||
<MaterialCommunityIcons
|
||
name="database"
|
||
color={hasExtraInfo ? "yellow" : "white"}
|
||
size={30}
|
||
style={{ margin: 5 }}
|
||
onPress={() => {
|
||
if (hasAdditionalSources) {
|
||
(SheetManager.show as any)("TrainDataSources", {
|
||
payload: {
|
||
trainNum,
|
||
unyohubEntries,
|
||
todayOperation,
|
||
navigate,
|
||
expoPushToken,
|
||
priority,
|
||
direction: iconTrainDirection,
|
||
customTrainData,
|
||
typeName,
|
||
trainName,
|
||
departureStation: trainData[0]?.split(",")[0] ?? "",
|
||
destinationStation: trainData[trainData.length - 1]?.split(",")[0] ?? "",
|
||
},
|
||
});
|
||
} else {
|
||
// 追加ソースが全てオフ → 元の挙動(直接 DB ページを開く)
|
||
const uri = `https://jr-shikoku-data-system.pages.dev/trainData/${trainNum}?userID=${expoPushToken}&from=eachTrainInfo`;
|
||
navigate("generalWebView", { uri, useExitButton: false });
|
||
SheetManager.hide("EachTrainInfo");
|
||
}
|
||
}}
|
||
/>
|
||
</View>
|
||
);
|
||
};
|