Files
jrshikoku/components/AllTrainDiagramView.js
harukin-expo-dev-env 980b251d43 getStringConfigを移動
2025-08-08 09:25:40 +00:00

300 lines
9.2 KiB
JavaScript
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, { useState, useEffect } from "react";
import {
View,
Text,
TouchableOpacity,
FlatList,
KeyboardAvoidingView,
TextInput,
Platform,
Keyboard,
ScrollView,
Linking,
Image,
} from "react-native";
import { useAllTrainDiagram } from "../stateBox/useAllTrainDiagram";
import { customTrainDataDetector } from "./custom-train-data";
import { getTrainType } from "../lib/getTrainType";
import { SheetManager } from "react-native-actions-sheet";
import { useNavigation } from "@react-navigation/native";
import { BigButton } from "./atom/BigButton";
import { Switch } from "react-native-elements";
import { migrateTrainName } from "@/lib/eachTrainInfoCoreLib/migrateTrainName";
import { OneManText } from "./ActionSheetComponents/EachTrainInfoCore/HeaderTextParts/OneManText";
import { getStringConfig } from "@/lib/getStringConfig";
export default function AllTrainDiagramView() {
const { goBack, navigate } = useNavigation();
const { keyList, allTrainDiagram, allCustomTrainData } = useAllTrainDiagram();
const [input, setInput] = useState(""); // 文字入力
const [keyBoardVisible, setKeyBoardVisible] = useState(false);
const [useStationName, setUseStationName] = useState(false);
const [useRegex, setUseRegex] = useState(false);
const regexTextStyle = {
color: "white",
fontSize: 20,
margin: 3,
padding: 3,
};
const regexTextButtonStyle = {
...regexTextStyle,
borderWidth: 1,
borderColor: "white",
borderRadius: 3,
};
useEffect(() => {
const showSubscription = Keyboard.addListener("keyboardDidShow", () => {
setKeyBoardVisible(true);
});
const hideSubscription = Keyboard.addListener("keyboardDidHide", () => {
setKeyBoardVisible(false);
});
return () => {
showSubscription.remove();
hideSubscription.remove();
};
}, []);
const openTrainInfo = (d) => {
const train = customTrainDataDetector(d, allCustomTrainData);
let TrainNumber = "";
if (train.trainNumDistance != undefined) {
const timeInfo =
parseInt(d.replace("M", "").replace("D", "")) - train.trainNumDistance;
TrainNumber = timeInfo + "号";
}
const type = getTrainType(train.type).data;
const limited = `${type}:${train.trainName}${TrainNumber}`;
const payload = {
data: { trainNum: d, limited },
navigate,
from: "AllTrainIDList",
};
SheetManager.show("EachTrainInfo", {
payload,
});
};
const Item = ({ id, openTrainInfo }) => {
const { img, trainName, type, trainNumDistance, infogram } =
customTrainDataDetector(id, allCustomTrainData);
const [typeString, fontAvailable, isOneMan] = getStringConfig(type, id);
const trainNameString = (() => {
switch (true) {
case trainName !== "":
// 特急の場合は、列車名を取得
// 列番対称データがある場合はそれから列車番号を取得
const distance = trainNumDistance;
const number =
distance !== null ? ` ${parseInt(id) - distance}` : "";
return trainName + number;
case allTrainDiagram[id] === undefined:
return "";
default:
// 行先がある場合は、行先を取得
const s = allTrainDiagram[id].split("#");
const hoge = s[s.length - 2].split(",")[0];
return migrateTrainName(hoge + "行き");
}
})();
return (
<TouchableOpacity
style={{
padding: 5,
flexDirection: "row",
borderColor: "white",
borderWidth: 1,
margin: 5,
borderRadius: 5,
alignItems: "center",
}}
onPress={() => openTrainInfo(id)}
>
{img && (
<Image
source={{ uri: img }}
style={{ width: 20, height: 20, marginLeft: 10, marginRight: 10 }}
/>
)}
{typeString && (
<Text
style={{
fontSize: 20,
color: "white",
fontFamily: fontAvailable ? "JR-Nishi" : undefined,
fontWeight: !fontAvailable ? "bold" : undefined,
marginRight: 5,
}}
>
{typeString}
</Text>
)}
{isOneMan && <OneManText />}
{trainNameString && (
<Text style={{ fontSize: 20, fontWeight: "bold", color: "white" }}>
{trainNameString}
</Text>
)}
<View style={{ flex: 1 }} />
<Text style={{ fontSize: 20, fontWeight: "bold", color: "white" }}>
{id}
</Text>
</TouchableOpacity>
);
};
return (
<View style={{ backgroundColor: "#0099CC", height: "100%" }}>
<FlatList
contentContainerStyle={{ justifyContent: "flex-end", flexGrow: 1 }}
style={{ flex: 1 }}
data={keyList?.filter((d) => {
if (useStationName) {
const ls = input.split(",").map((stationName) => {
return allTrainDiagram[d].includes(stationName);
});
return !ls.includes(false);
}
if (useRegex) {
try {
const regex = new RegExp(input);
return regex.test(d);
} catch (e) {
return false;
}
}
return d.includes(input);
})}
renderItem={({ item }) => <Item {...{ openTrainInfo, id: item }} />}
ListEmptyComponent={
<View style={{ flex: 1, alignItems: "center", marginTop: 50 }}>
<Text style={{ color: "white", fontSize: 20 }}>
検索結果がありません
</Text>
</View>
}
keyExtractor={(item) => item}
//initialNumToRender={100}
/>
<KeyboardAvoidingView
behavior="padding"
keyboardVerticalOffset={80}
enabled={Platform.OS === "ios"}
>
<View style={{ height: 35, flexDirection: "row" }}>
<Switch
value={useRegex}
onValueChange={() => {
setUseRegex(!useRegex);
setUseStationName(false);
}}
color="red"
style={{ margin: 5 }}
/>
<Text style={{ color: "white", fontSize: 20, margin: 5 }}>
正規表現を使用
</Text>
<Switch
value={useStationName}
onValueChange={() => {
setUseRegex(false);
setUseStationName(!useStationName);
}}
color="red"
style={{ margin: 5 }}
/>
<Text style={{ color: "white", fontSize: 20, margin: 5 }}>
駅名で検索
</Text>
</View>
<ScrollView
style={{
height: 35,
flexDirection: "row",
backgroundColor: "#0099CC",
margin: 5,
display: useRegex ? "flex" : "none",
}}
horizontal={true}
>
<Text style={regexTextStyle}>正規表現のサンプル</Text>
<Text style={regexTextButtonStyle} onPress={() => setInput("D")}>
気動車を選択
</Text>
<Text
style={regexTextButtonStyle}
onPress={() => setInput("3\\d\\d\\dM")}
>
マリンライナーを選択
</Text>
<Text
style={regexTextButtonStyle}
onPress={() => setInput("[4,5]\\d\\d\\d[D,M]")}
>
ワンマン列車を選択
</Text>
<Text
style={regexTextButtonStyle}
onPress={() => setInput("^\\d?\\dM")}
>
しおかぜを選択
</Text>
<Text
style={regexTextButtonStyle}
onPress={() => setInput("^\\d?[0,2,4,6,8]D")}
>
下り南風を選択
</Text>
<Text
style={regexTextButtonStyle}
onPress={() => setInput("^([\\d])+\\1")}
>
数字が二桁揃っている列車を選択
</Text>
<Text
style={{ ...regexTextButtonStyle, backgroundColor: "green" }}
onPress={() =>
Linking.openURL(
"https://qiita.com/tossh/items/635aea9a529b9deb3038"
)
}
>
参考資料(Qiita)
</Text>
</ScrollView>
<View
style={{
height: 35,
margin: 5,
alignItems: "center",
backgroundColor: "#F4F4F4",
flexDirection: "row",
paddingLeft: 10,
paddingRight: 10,
borderRadius: 25,
borderColor: "#F4F4F4",
}}
>
<TextInput
placeholder="列番を入力してフィルタリングします。"
onFocus={() => setKeyBoardVisible(true)}
onEndEditing={() => {}}
onChange={(ret) => setInput(ret.nativeEvent.text)}
value={input}
style={{ flex: 1 }}
/>
</View>
</KeyboardAvoidingView>
<BigButton
onPress={goBack}
string="閉じる"
style={{
display:
Platform.OS === "ios" ? "flex" : keyBoardVisible ? "none" : "flex",
}}
/>
</View>
);
}