Files
jrshikoku/components/ActionSheetComponents/EachTrainInfoCore/HeaderText.tsx

314 lines
9.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { FC, useMemo, useState } 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";
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 { limited, trainNum } = data;
const { fixed } = useThemeColors();
const { updatePermission } = useTrainMenu();
const { allCustomTrainData, getTodayOperationByTrainId } =
useAllTrainDiagram();
const { expoPushToken } = useNotification();
const {
getUnyohubByTrainNumber,
getUnyohubEntriesByTrainNumber,
useUnyohub: unyohubEnabled,
} = useUnyohub();
const { getElesiteEntriesByTrainNumber, useElesite: elesiteEnabled } =
useElesite();
// 追加ソースのON/OFFをここで管理将来ソースが増えたらここに足す
const additionalSources = {
unyohub: unyohubEnabled,
elesite: elesiteEnabled,
};
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 elesiteEntries = getElesiteEntriesByTrainNumber(trainNum);
// 車番(formations)が空でないエントリが1件以上あれば「運用Hub情報あり」と判定
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 [isWrapped, setIsWrapped] = useState(false);
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}
/>
<View
style={{
flexDirection: "row",
alignItems: "center",
marginBottom: 2,
}}
>
<Text
style={{
fontSize: 20,
color: fixed.textOnPrimary,
fontFamily: fontAvailable ? "JR-Nishi" : undefined,
fontWeight: !fontAvailable ? "bold" : undefined,
marginRight: 5,
}}
>
{isWrapped ? typeName.replace(/(.{2})/g, "$1\n").trim() : typeName}
</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={() => {
if (!trainInfoUrl) return;
const uri = trainInfoUrl.includes("pdf")
? getPDFViewURL(trainInfoUrl)
: trainInfoUrl;
navigate("generalWebView", { uri, useExitButton: true });
SheetManager.hide("EachTrainInfo");
}}
disabled={!trainInfoUrl}
>
<Text
style={{
...textConfig,
color: fixed.textOnPrimary,
...(trainName.length > 10 ? { fontSize: 16 } : {}),
flexShrink: 1,
}}
onTextLayout={(e) => {
if (e.nativeEvent.lines.length > 1) setIsWrapped(true);
}}
>
{trainName}
</Text>
<InfogramText infogram={infogram} />
</TouchableOpacity>
<View style={{ flex: 1 }} />
<Text style={{ ...textConfig, 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,
unyohubEntries,
elesiteEntries,
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>
);
};