Files
jrshikoku/components/ActionSheetComponents/EachTrainInfoCore/HeaderText.tsx
2025-12-31 06:46:38 +00:00

257 lines
7.5 KiB
TypeScript

import React, { CSSProperties, FC, useEffect, useMemo, useState } 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 { TrainViewIcon } from "./trainViewIcon";
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 { FontAwesome, MaterialCommunityIcons } from "@expo/vector-icons";
import { getPDFViewURL } from "@/lib/getPdfViewURL";
import { widthPercentageToDP } from "react-native-responsive-screen";
import type { NavigateFunction } from "@/types";
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 [
typeName,
trainName,
fontAvailable,
isOneMan,
infogram,
priority,
uwasa,
trainInfoUrl,
] = useMemo(() => {
const {
type,
train_name,
train_num_distance,
infogram,
priority,
uwasa,
train_info_url,
to_data,
} = customTrainDataDetector(trainNum, allCustomTrainData);
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,
];
case trainData[trainData.length - 1] === undefined:
return [
typeString,
"",
fontAvailable,
isOneMan,
infogram,
priority,
uwasa,
train_info_url,
];
case to_data && to_data !== "":
// 行先がある場合は、行先を取得
return [
typeString,
to_data + "行き",
fontAvailable,
isOneMan,
infogram,
priority,
uwasa,
train_info_url,
];
default:
// 行先がある場合は、行先を取得
return [
typeString,
migrateTrainName(
trainData[trainData.length - 1].split(",")[0] + "行き"
),
fontAvailable,
isOneMan,
infogram,
priority,
uwasa,
train_info_url,
];
}
}, [trainData]);
const todayOperation = getTodayOperationByTrainId(trainNum).filter(d=> d.state !== 100);
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}
/>
<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>
{(priority > 200 || todayOperation?.length > 0) && (
<FontAwesome
name="commenting-o"
size={20}
color="white"
style={{ marginLeft: 5 }}
onPress={() => {
// 列番が奇数か偶数かで表示順を逆転
const trainNumInt = parseInt(trainNum, 10);
const ops = todayOperation ? [...todayOperation] : [];
const displayOps = trainNumInt % 2 === 0 ? ops : ops.reverse();
const directionText = trainNumInt % 2 === 0
? '←進行方向'
: '進行方向→';
alert(
`[このアイコン、列車データはコミュニティによってリアルタイム追加されています。]\n使用車両情報:\n${displayOps
.map((op) => op.unit_ids)
.join("+")}\n${directionText}\n投稿者メモ:\n${uwasa || "なし"}`
);
}}
/>
)}
<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>
<TrainViewIcon {...{ data, navigate, from }} />
</View>
);
};