Files

350 lines
10 KiB
TypeScript

import React, { FC, useMemo } from "react";
import { Text, View, TextStyle, TouchableOpacity } 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";
import { useElesite } from "@/stateBox/useElesite";
import { useThemeColors } from "@/lib/theme";
import { formatWrappedTrainType, shouldWrapTrainType } from "@/lib/trainTypeWrap";
import { useResponsive } from "@/lib/responsive";
import { normalizeIconDisplayMode } from "@/lib/iconDisplayMode";
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;
scrollRef: any;
};
const textConfig: TextStyle = {
fontSize: 17,
fontWeight: "bold",
};
export const HeaderText: FC<Props> = ({
data,
trainData,
showHeadStation,
showTailStation,
headStation,
tailStation,
navigate,
from,
scrollRef,
}) => {
const { trainNum } = data;
const { fixed } = useThemeColors();
const { fontScale } = useResponsive();
const { iconSetting } = useTrainMenu();
const { allCustomTrainData, getTodayOperationByTrainId } =
useAllTrainDiagram();
const { expoPushToken } = useNotification();
const {
getUnyohubByTrainNumber,
getUnyohubEntriesByTrainNumber,
useUnyohub: unyohubEnabled,
unyohubData,
} = useUnyohub();
const { getElesiteEntriesByTrainNumber, useElesite: elesiteEnabled } =
useElesite();
const iconDisplayMode = normalizeIconDisplayMode(iconSetting);
const additionalSources = {
unyohub: unyohubEnabled,
elesite: elesiteEnabled,
};
const hasAdditionalSources = Object.values(additionalSources).some(Boolean);
const [
typeName,
trainName,
fontFamily,
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, fontFamily, 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)}号`
: ""),
fontFamily,
isOneMan,
infogram,
priority,
uwasa,
train_info_url,
directions,
result,
];
case trainData[trainData.length - 1] === undefined:
return [
typeString,
"",
fontFamily,
isOneMan,
infogram,
priority,
uwasa,
train_info_url,
directions,
result,
];
case to_data && to_data !== "":
return [
typeString,
`${to_data}行き`,
fontFamily,
isOneMan,
infogram,
priority,
uwasa,
train_info_url,
directions,
result,
];
default:
return [
typeString,
migrateTrainName(
`${trainData[trainData.length - 1].split(",")[0]}行き`,
),
fontFamily,
isOneMan,
infogram,
priority,
uwasa,
train_info_url,
directions,
result,
];
}
}, [trainData, trainNum, allCustomTrainData]);
const allTodayOperation = getTodayOperationByTrainId(trainNum) ?? [];
const todayOperation = allTodayOperation.filter((d) => d.state !== 100);
let iconTrainDirection =
parseInt(trainNum.replace(/[^\d]/g, "")) % 2 == 0 ? true : false;
if (directions != undefined) {
iconTrainDirection = directions ? true : false;
}
const unyohubLookupNum = customTrainData?.train_number_override || trainNum;
const isFreightRetsuban = unyohubLookupNum.includes("レ");
const unyohubTrainNumForSourceScreen = isFreightRetsuban
? unyohubLookupNum.replace(/レ/g, "")
: unyohubLookupNum;
const freightUnyohubCandidates = (() => {
const digits = unyohubTrainNumForSourceScreen.replace(/[^\d]/g, "");
const candidates = new Set<string>();
if (!digits) return candidates;
candidates.add(digits);
if (/^\d{2}$/.test(digits)) {
candidates.add(`30${digits}`);
candidates.add(`90${digits}`);
} else if (/^(30|90)\d{2}$/.test(digits)) {
candidates.add(digits.slice(-2));
}
return candidates;
})();
const unyohubFormation = getUnyohubByTrainNumber(unyohubLookupNum);
const unyohubEntries = isFreightRetsuban
? unyohubData.filter((unyo) =>
unyo.trains?.some(
(t) => !!t.train_number && freightUnyohubCandidates.has(t.train_number),
),
)
: getUnyohubEntriesByTrainNumber(unyohubTrainNumForSourceScreen);
const elesiteEntries = getElesiteEntriesByTrainNumber(trainNum);
const hasUnyohubFormation = unyohubEntries.some(
(e) => !!e.formations && e.formations.trim() !== "",
);
const hasElesiteFormation = elesiteEntries.some(
(e) => (e.formation_config?.units?.length ?? 0) > 0,
);
const hasExtraInfo =
priority > 200 ||
todayOperation.length > 0 ||
hasUnyohubFormation ||
hasElesiteFormation;
const wrapType = shouldWrapTrainType(typeName, trainName);
const openTrainInfoUrl = () => {
if (!trainInfoUrl) return;
const uri = trainInfoUrl.includes("pdf")
? getPDFViewURL(trainInfoUrl)
: trainInfoUrl;
navigate("generalWebView", { uri, useExitButton: true });
SheetManager.hide("EachTrainInfo");
};
return (
<View
style={{
padding: 10,
flexDirection: "row",
alignItems: "center",
width: "100%",
}}
onTouchStart={() =>
scrollRef.current?.scrollTo({ y: 0, animated: true })
}
>
<TrainIconStatus
data={data}
navigate={navigate}
from={from}
todayOperation={todayOperation}
direction={iconTrainDirection}
iconDisplayMode={iconDisplayMode}
/>
<View
style={{
flexDirection: "row",
alignItems: "center",
marginBottom: 2,
}}
>
<Text
numberOfLines={wrapType ? 2 : 1}
style={{
fontSize: fontScale(20),
color: fixed.textOnPrimary,
fontFamily,
fontWeight: fontFamily ? undefined : "bold",
marginRight: 5,
flexShrink: 0,
...(wrapType
? { width: fontScale(44), lineHeight: fontScale(22) }
: {}),
}}
>
{wrapType ? formatWrappedTrainType(typeName) : typeName}
{fontFamily === "JR-WEST-PLUS" ? (
<Text style={{ fontFamily: "DiaPro", fontSize: 7 }}>{"\u00A0"}</Text>
) : null}
</Text>
{isOneMan && <OneManText />}
</View>
<TouchableOpacity
style={{
borderRadius: 5,
flexDirection: "row",
alignItems: "center",
flexShrink: 1,
flexWrap: "wrap",
...(trainInfoUrl
? {
borderWidth: 0,
borderBottomWidth: 1,
borderStyle: "solid",
borderColor: fixed.textOnPrimary,
}
: {}),
}}
onPress={openTrainInfoUrl}
disabled={!trainInfoUrl}
>
<Text
style={{
...textConfig,
color: fixed.textOnPrimary,
...(trainName.length > 10
? { fontSize: fontScale(16) }
: { fontSize: fontScale(17) }),
flexShrink: 1,
}}
>
{trainName}
</Text>
<InfogramText infogram={infogram} />
</TouchableOpacity>
<View style={{ flex: 1 }} />
<Text style={{ ...textConfig, fontSize: fontScale(17), color: fixed.textOnPrimary }}>
{showHeadStation.map((d) => `${headStation[d].id} + `)}
{trainNum}
{showTailStation.map((d) => ` + ${tailStation[d].id}`)}
</Text>
<MaterialCommunityIcons
name="database"
color={hasExtraInfo ? "yellow" : fixed.textOnPrimary}
size={30}
style={{ margin: 5 }}
onPress={() => {
if (hasAdditionalSources) {
(SheetManager.show as any)("TrainDataSources", {
payload: {
trainNum,
unyohubTrainNum: unyohubTrainNumForSourceScreen,
unyohubEntries,
elesiteEntries,
todayOperation,
navigate,
expoPushToken,
priority,
direction: iconTrainDirection,
customTrainData,
typeName,
trainName,
departureStation: trainData[0]?.split(",")[0] ?? "",
destinationStation:
trainData[trainData.length - 1]?.split(",")[0] ?? "",
},
});
} else {
const uri = `https://jr-shikoku-data-system.pages.dev/trainData/${trainNum}?userID=${expoPushToken}&from=eachTrainInfo`;
navigate("generalWebView", { uri, useExitButton: false });
SheetManager.hide("EachTrainInfo");
}
}}
/>
</View>
);
};