Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| daf261b4f8 | |||
| 50fa4de919 | |||
| ab2061b2bd |
@@ -17,6 +17,7 @@ import { useUnyohub } from "@/stateBox/useUnyohub";
|
||||
import { useElesite } from "@/stateBox/useElesite";
|
||||
import { useThemeColors } from "@/lib/theme";
|
||||
import { useResponsive } from "@/lib/responsive";
|
||||
import { normalizeIconDisplayMode } from "@/lib/iconDisplayMode";
|
||||
|
||||
type Props = {
|
||||
data: { trainNum: string; limited: string };
|
||||
@@ -47,11 +48,11 @@ export const HeaderText: FC<Props> = ({
|
||||
from,
|
||||
scrollRef,
|
||||
}) => {
|
||||
const { limited, trainNum } = data;
|
||||
const { trainNum } = data;
|
||||
|
||||
const { fixed } = useThemeColors();
|
||||
const { fontScale } = useResponsive();
|
||||
const { updatePermission } = useTrainMenu();
|
||||
const { iconSetting } = useTrainMenu();
|
||||
const { allCustomTrainData, getTodayOperationByTrainId } =
|
||||
useAllTrainDiagram();
|
||||
const { expoPushToken } = useNotification();
|
||||
@@ -63,15 +64,14 @@ export const HeaderText: FC<Props> = ({
|
||||
} = useUnyohub();
|
||||
const { getElesiteEntriesByTrainNumber, useElesite: elesiteEnabled } =
|
||||
useElesite();
|
||||
const iconDisplayMode = normalizeIconDisplayMode(iconSetting);
|
||||
|
||||
// 追加ソースのON/OFFをここで管理(将来ソースが増えたらここに足す)
|
||||
const additionalSources = {
|
||||
unyohub: unyohubEnabled,
|
||||
elesite: elesiteEnabled,
|
||||
};
|
||||
const hasAdditionalSources = Object.values(additionalSources).some(Boolean);
|
||||
|
||||
// 列車名、種別、フォントの取得
|
||||
const [
|
||||
typeName,
|
||||
trainName,
|
||||
@@ -133,7 +133,7 @@ export const HeaderText: FC<Props> = ({
|
||||
case to_data && to_data !== "":
|
||||
return [
|
||||
typeString,
|
||||
to_data + "行き",
|
||||
`${to_data}行き`,
|
||||
fontAvailable,
|
||||
isOneMan,
|
||||
infogram,
|
||||
@@ -147,7 +147,7 @@ export const HeaderText: FC<Props> = ({
|
||||
return [
|
||||
typeString,
|
||||
migrateTrainName(
|
||||
trainData[trainData.length - 1].split(",")[0] + "行き",
|
||||
`${trainData[trainData.length - 1].split(",")[0]}行き`,
|
||||
),
|
||||
fontAvailable,
|
||||
isOneMan,
|
||||
@@ -161,7 +161,7 @@ export const HeaderText: FC<Props> = ({
|
||||
}
|
||||
}, [trainData, trainNum, allCustomTrainData]);
|
||||
|
||||
const allTodayOperation = getTodayOperationByTrainId(trainNum);
|
||||
const allTodayOperation = getTodayOperationByTrainId(trainNum) ?? [];
|
||||
const todayOperation = allTodayOperation.filter((d) => d.state !== 100);
|
||||
|
||||
let iconTrainDirection =
|
||||
@@ -198,7 +198,6 @@ export const HeaderText: FC<Props> = ({
|
||||
: getUnyohubEntriesByTrainNumber(unyohubTrainNumForSourceScreen);
|
||||
const elesiteEntries = getElesiteEntriesByTrainNumber(trainNum);
|
||||
|
||||
// 車番(formations) がある場合のみ「運用Hub情報あり」と判定
|
||||
const hasUnyohubFormation = unyohubEntries.some(
|
||||
(e) => !!e.formations && e.formations.trim() !== "",
|
||||
);
|
||||
@@ -208,12 +207,21 @@ export const HeaderText: FC<Props> = ({
|
||||
|
||||
const hasExtraInfo =
|
||||
priority > 200 ||
|
||||
todayOperation?.length > 0 ||
|
||||
todayOperation.length > 0 ||
|
||||
hasUnyohubFormation ||
|
||||
hasElesiteFormation;
|
||||
|
||||
const [isWrapped, setIsWrapped] = useState(false);
|
||||
|
||||
const openTrainInfoUrl = () => {
|
||||
if (!trainInfoUrl) return;
|
||||
const uri = trainInfoUrl.includes("pdf")
|
||||
? getPDFViewURL(trainInfoUrl)
|
||||
: trainInfoUrl;
|
||||
navigate("generalWebView", { uri, useExitButton: true });
|
||||
SheetManager.hide("EachTrainInfo");
|
||||
};
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
@@ -232,6 +240,7 @@ export const HeaderText: FC<Props> = ({
|
||||
from={from}
|
||||
todayOperation={todayOperation}
|
||||
direction={iconTrainDirection}
|
||||
iconDisplayMode={iconDisplayMode}
|
||||
/>
|
||||
|
||||
<View
|
||||
@@ -270,26 +279,21 @@ export const HeaderText: FC<Props> = ({
|
||||
}
|
||||
: {}),
|
||||
}}
|
||||
onPress={() => {
|
||||
if (!trainInfoUrl) return;
|
||||
const uri = trainInfoUrl.includes("pdf")
|
||||
? getPDFViewURL(trainInfoUrl)
|
||||
: trainInfoUrl;
|
||||
navigate("generalWebView", { uri, useExitButton: true });
|
||||
SheetManager.hide("EachTrainInfo");
|
||||
}}
|
||||
onPress={openTrainInfoUrl}
|
||||
disabled={!trainInfoUrl}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
...textConfig,
|
||||
color: fixed.textOnPrimary,
|
||||
...(trainName.length > 10 ? { fontSize: fontScale(16) } : { fontSize: fontScale(17) }),
|
||||
...(trainName.length > 10
|
||||
? { fontSize: fontScale(16) }
|
||||
: { fontSize: fontScale(17) }),
|
||||
flexShrink: 1,
|
||||
}}
|
||||
onTextLayout={(e) => {
|
||||
if (e.nativeEvent.lines.length > 1) setIsWrapped(true);
|
||||
}}
|
||||
if (e.nativeEvent.lines.length > 1) setIsWrapped(true);
|
||||
}}
|
||||
>
|
||||
{trainName}
|
||||
</Text>
|
||||
@@ -328,7 +332,6 @@ export const HeaderText: FC<Props> = ({
|
||||
},
|
||||
});
|
||||
} 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");
|
||||
|
||||
@@ -3,13 +3,14 @@ import { Text } from "react-native";
|
||||
import { useThemeColors } from "@/lib/theme";
|
||||
type props = {
|
||||
infogram: string;
|
||||
fontSize?: number;
|
||||
}
|
||||
export const InfogramText: FC<props> = ({infogram}) => {
|
||||
export const InfogramText: FC<props> = ({infogram, fontSize = 20}) => {
|
||||
const { fixed } = useThemeColors();
|
||||
return (
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 20,
|
||||
fontSize,
|
||||
color: fixed.textOnPrimary,
|
||||
fontFamily: "JNR-font",
|
||||
}}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
import React, { ComponentProps, FC } from "react";
|
||||
import { Image, TouchableOpacity, View } from "react-native";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import type { TrainIconEntry } from "@/lib/trainIconEntries";
|
||||
|
||||
type StackVariant = "header" | "list";
|
||||
type StatusIcon = ComponentProps<typeof Ionicons>;
|
||||
|
||||
type Props = {
|
||||
entries: TrainIconEntry[];
|
||||
direction?: boolean;
|
||||
hidden?: boolean;
|
||||
onPressEntry?: (entry: TrainIconEntry, index: number) => void;
|
||||
statusIcon?: StatusIcon;
|
||||
variant?: StackVariant;
|
||||
};
|
||||
|
||||
const iconSize = {
|
||||
header: {
|
||||
width: 24,
|
||||
height: 30,
|
||||
stackedWidth: 12,
|
||||
stackedHeight: 15,
|
||||
marginRight: 5,
|
||||
stackedMarginLeft: -10,
|
||||
stackedMarginTop: 10,
|
||||
statusSize: 24,
|
||||
},
|
||||
list: {
|
||||
width: 20,
|
||||
height: 22,
|
||||
stackedWidth: 10,
|
||||
stackedHeight: 12,
|
||||
marginRight: 2,
|
||||
stackedMarginLeft: -8,
|
||||
stackedMarginTop: 8,
|
||||
statusSize: 18,
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const TrainIconStack: FC<Props> = ({
|
||||
entries,
|
||||
direction,
|
||||
hidden = false,
|
||||
onPressEntry,
|
||||
statusIcon,
|
||||
variant = "header",
|
||||
}) => {
|
||||
const size = iconSize[variant];
|
||||
|
||||
return (
|
||||
<View style={{ flexDirection: "row", alignItems: "flex-start" }}>
|
||||
{entries.map((entry, index) => {
|
||||
const trainIcon = direction
|
||||
? entry.vehicle_info_img
|
||||
: entry.vehicle_info_right_img || entry.vehicle_info_img;
|
||||
if (!trainIcon) return null;
|
||||
|
||||
const content = (
|
||||
<View>
|
||||
<View style={{ opacity: hidden ? 0 : 1 }}>
|
||||
<Image
|
||||
source={{ uri: trainIcon }}
|
||||
style={{
|
||||
height: index > 0 ? size.stackedHeight : size.height,
|
||||
width: index > 0 ? size.stackedWidth : size.width,
|
||||
marginRight: size.marginRight,
|
||||
marginLeft: index > 0 ? size.stackedMarginLeft : 0,
|
||||
marginTop: index > 0 ? size.stackedMarginTop : 0,
|
||||
}}
|
||||
resizeMethod="resize"
|
||||
/>
|
||||
</View>
|
||||
{statusIcon && hidden && (
|
||||
<View style={{ position: "absolute", top: 0, left: 0 }}>
|
||||
<Ionicons {...statusIcon} size={size.statusSize} />
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
|
||||
if (!onPressEntry) {
|
||||
return <View key={`${trainIcon}-${index}`}>{content}</View>;
|
||||
}
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
key={`${trainIcon}-${index}`}
|
||||
onPress={() => onPressEntry(entry, index)}
|
||||
disabled={!entry.vehicle_info_url}
|
||||
>
|
||||
{content}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
@@ -1,5 +1,4 @@
|
||||
import React, { ComponentProps, FC, useEffect, useState } from "react";
|
||||
import { View, Image, TouchableOpacity } from "react-native";
|
||||
import React, { ComponentProps, FC, useEffect, useMemo, useState } from "react";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import dayjs from "dayjs";
|
||||
import { SheetManager } from "react-native-actions-sheet";
|
||||
@@ -8,6 +7,9 @@ import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
|
||||
import { useInterval } from "@/lib/useInterval";
|
||||
import type { NavigateFunction } from "@/types";
|
||||
import { OperationLogs } from "@/lib/CommonTypes";
|
||||
import type { IconDisplayMode } from "@/lib/iconDisplayMode";
|
||||
import { resolveTrainIconEntries } from "@/lib/trainIconEntries";
|
||||
import { TrainIconStack } from "./TrainIconStack";
|
||||
|
||||
type GlyphNames = ComponentProps<typeof Ionicons>["name"];
|
||||
|
||||
@@ -17,94 +19,54 @@ type Props = {
|
||||
from: string;
|
||||
todayOperation: OperationLogs[];
|
||||
direction?: boolean;
|
||||
iconDisplayMode: IconDisplayMode;
|
||||
};
|
||||
type apt = {
|
||||
name: GlyphNames;
|
||||
color: string;
|
||||
};
|
||||
export const TrainIconStatus: FC<Props> = (props) => {
|
||||
const { data, navigate, from, todayOperation, direction } = props;
|
||||
const {
|
||||
data,
|
||||
navigate,
|
||||
from,
|
||||
todayOperation,
|
||||
direction,
|
||||
iconDisplayMode,
|
||||
} = props;
|
||||
const [anpanmanStatus, setAnpanmanStatus] = useState<apt>();
|
||||
const { allCustomTrainData } = useAllTrainDiagram();
|
||||
const [trainIconData, setTrainIcon] = useState<
|
||||
{ vehicle_info_img: string;vehicle_info_right_img: string; vehicle_info_url: string }[]
|
||||
>([]);
|
||||
const customTrainData = useMemo(
|
||||
() => customTrainDataDetector(data.trainNum, allCustomTrainData),
|
||||
[data.trainNum, allCustomTrainData],
|
||||
);
|
||||
const trainIconData = useMemo(
|
||||
() =>
|
||||
data.trainNum
|
||||
? resolveTrainIconEntries({
|
||||
trainNum: data.trainNum,
|
||||
customTrainData,
|
||||
todayOperation,
|
||||
iconDisplayMode,
|
||||
})
|
||||
: [],
|
||||
[data.trainNum, customTrainData, todayOperation, iconDisplayMode],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!data.trainNum) return;
|
||||
const { train_info_img: vehicle_info_img, vehicle_info_url } =
|
||||
customTrainDataDetector(data.trainNum, allCustomTrainData);
|
||||
if (todayOperation.length !== 0) {
|
||||
const returnData =
|
||||
todayOperation
|
||||
.sort((a, b) => {
|
||||
// trainIdからカンマ以降の数字を抽出する関数
|
||||
const extractOrderNumber = (trainId: string): number => {
|
||||
const parts = trainId.split(',');
|
||||
if (parts.length > 1) {
|
||||
const num = parseInt(parts[1].trim(), 10);
|
||||
return isNaN(num) ? Infinity : num;
|
||||
}
|
||||
return Infinity; // カンマなし = 末尾に移動
|
||||
};
|
||||
|
||||
// data.trainNumと一致するtrainIdを探す関数
|
||||
const findMatchingTrainId = (operation: OperationLogs): string | null => {
|
||||
const allTrainIds = [
|
||||
...(operation.train_ids || []),
|
||||
...(operation.related_train_ids || []),
|
||||
];
|
||||
|
||||
// data.trainNumの接頭辞と一致するものを探す
|
||||
for (const trainId of allTrainIds) {
|
||||
const prefix = trainId.split(',')[0]; // カンマ前の部分
|
||||
if (prefix === data.trainNum) {
|
||||
return trainId;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const aTrainId = findMatchingTrainId(a);
|
||||
const bTrainId = findMatchingTrainId(b);
|
||||
|
||||
// マッチしたものがない場合は元の順序を保持
|
||||
if (!aTrainId || !bTrainId) {
|
||||
return aTrainId ? -1 : bTrainId ? 1 : 0;
|
||||
}
|
||||
|
||||
const aOrder = extractOrderNumber(aTrainId);
|
||||
const bOrder = extractOrderNumber(bTrainId);
|
||||
|
||||
return aOrder - bOrder;
|
||||
})
|
||||
.map((op) => ({
|
||||
vehicle_info_img: op.vehicle_img || vehicle_info_img,
|
||||
vehicle_info_right_img: op.vehicle_img_right || op.vehicle_img || vehicle_info_img,
|
||||
vehicle_info_url: op.vehicle_info_url,
|
||||
})) || [];
|
||||
setTrainIcon(returnData);
|
||||
} else if (vehicle_info_img) {
|
||||
setTrainIcon([{ vehicle_info_img, vehicle_info_right_img: vehicle_info_img, vehicle_info_url }]);
|
||||
}
|
||||
|
||||
// アンパンマンステータスAPIのエンドポイント判定
|
||||
let anpanmanApiPath: string | null = null;
|
||||
switch (data.trainNum) {
|
||||
// 予讃線 → yosan-anpanman
|
||||
// しおかぜ 8000 アンパン
|
||||
case "10M":
|
||||
case "22M":
|
||||
case "9M":
|
||||
case "21M":
|
||||
// いしづち 8000 アンパン
|
||||
case "1010M":
|
||||
case "1022M":
|
||||
case "1009M":
|
||||
case "1021M":
|
||||
// いしづち 三桁 アンパン
|
||||
case "1041M":
|
||||
case "1044M":
|
||||
// 宇和海 2000 アンパン
|
||||
case "1058D":
|
||||
case "1066D":
|
||||
case "1074D":
|
||||
@@ -113,8 +75,6 @@ export const TrainIconStatus: FC<Props> = (props) => {
|
||||
case "1067D":
|
||||
anpanmanApiPath = "yosan-anpanman";
|
||||
break;
|
||||
// 土讃線 → dosan-anpanman
|
||||
// 南風 2700 アンパン
|
||||
case "32D":
|
||||
case "36D":
|
||||
case "44D":
|
||||
@@ -132,12 +92,12 @@ export const TrainIconStatus: FC<Props> = (props) => {
|
||||
fetch(
|
||||
`https://n8n.haruk.in/webhook/${anpanmanApiPath}?trainNum=${
|
||||
data.trainNum
|
||||
}&month=${dayjs().format("M")}&day=${dayjs().format("D")}`,{ cache: "no-store" }
|
||||
}&month=${dayjs().format("M")}&day=${dayjs().format("D")}`,
|
||||
{ cache: "no-store" },
|
||||
)
|
||||
.then((d) => d.json())
|
||||
.then((d) => {
|
||||
if (d.trainStatus == "〇" || d.trainStatus == "○") {
|
||||
//setAnpanmanStatus({name:"checkmark-circle-outline",color:"blue"});
|
||||
} else if (d.trainStatus == "▲") {
|
||||
setAnpanmanStatus({ name: "warning-outline", color: "yellow" });
|
||||
} else if (d.trainStatus == "×") {
|
||||
@@ -146,11 +106,8 @@ export const TrainIconStatus: FC<Props> = (props) => {
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
}, [data.trainNum, allCustomTrainData, todayOperation]);
|
||||
}, [data.trainNum, allCustomTrainData, todayOperation, iconDisplayMode]);
|
||||
|
||||
// JSスレッドでの点滅(useInterval + useState)
|
||||
// reanimated の withRepeat はUIスレッドで毎フレーム更新し続けるため
|
||||
// ActionSheetのスプリングアニメーションと競合する
|
||||
const [showIcon, setShowIcon] = useState(false);
|
||||
useInterval(() => {
|
||||
if (anpanmanStatus) {
|
||||
@@ -159,47 +116,18 @@ export const TrainIconStatus: FC<Props> = (props) => {
|
||||
}, 1000, !!anpanmanStatus);
|
||||
|
||||
return (
|
||||
<>
|
||||
{trainIconData.map(
|
||||
({ vehicle_info_img: trainIcon, vehicle_info_right_img: trainIconRight, vehicle_info_url: address }, index) => (
|
||||
<TouchableOpacity
|
||||
key={`${trainIcon}-${index}`}
|
||||
onPress={() => {
|
||||
navigate("howto", {
|
||||
info: address,
|
||||
goTo: from == "LED" ? "menu" : from,
|
||||
});
|
||||
SheetManager.hide("EachTrainInfo");
|
||||
}}
|
||||
disabled={!address}
|
||||
>
|
||||
<View>
|
||||
<View style={{ opacity: anpanmanStatus && showIcon ? 0 : 1 }}>
|
||||
<Image
|
||||
source={{ uri: direction ? trainIcon : trainIconRight || trainIcon }}
|
||||
style={{
|
||||
height: index > 0 ? 15 : 30,
|
||||
width: index > 0 ? 12 : 24,
|
||||
marginRight: 5,
|
||||
marginLeft: index > 0 ? -10 : 0,
|
||||
marginTop: index > 0 ? 10 : 0,
|
||||
}}
|
||||
resizeMethod="resize"
|
||||
/>
|
||||
</View>
|
||||
{anpanmanStatus && showIcon && (
|
||||
<View style={{ position: "absolute", top: 0, left: 0 }}>
|
||||
<Ionicons
|
||||
{...anpanmanStatus}
|
||||
size={24}
|
||||
style={{ marginRight: 5 }}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
<TrainIconStack
|
||||
entries={trainIconData}
|
||||
direction={direction}
|
||||
hidden={!!anpanmanStatus && showIcon}
|
||||
statusIcon={anpanmanStatus}
|
||||
onPressEntry={(entry) => {
|
||||
navigate("howto", {
|
||||
info: entry.vehicle_info_url,
|
||||
goTo: from == "LED" ? "menu" : from,
|
||||
});
|
||||
SheetManager.hide("EachTrainInfo");
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
TextInput,
|
||||
ScrollView,
|
||||
Linking,
|
||||
Image,
|
||||
} from "react-native";
|
||||
import { useAllTrainDiagram } from "../stateBox/useAllTrainDiagram";
|
||||
import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs";
|
||||
@@ -24,10 +23,17 @@ import { Switch } from "@rneui/themed";
|
||||
import { migrateTrainName } from "@/lib/eachTrainInfoCoreLib/migrateTrainName";
|
||||
import { OneManText } from "./ActionSheetComponents/EachTrainInfoCore/HeaderTextParts/OneManText";
|
||||
import { getStringConfig } from "@/lib/getStringConfig";
|
||||
import { useTrainMenu } from "@/stateBox/useTrainMenu";
|
||||
import { normalizeIconDisplayMode } from "@/lib/iconDisplayMode";
|
||||
import { InfogramText } from "./ActionSheetComponents/EachTrainInfoCore/HeaderTextParts/InfogramText";
|
||||
import { resolveTrainIconEntries } from "@/lib/trainIconEntries";
|
||||
import { TrainIconStack } from "./ActionSheetComponents/EachTrainInfoCore/TrainIconStack";
|
||||
|
||||
export const AllTrainDiagramView: FC = () => {
|
||||
const { colors, fixed } = useThemeColors();
|
||||
const { goBack, navigate } = useNavigation<any>();
|
||||
const { iconSetting } = useTrainMenu();
|
||||
const iconDisplayMode = normalizeIconDisplayMode(iconSetting);
|
||||
const tabBarHeight = useBottomTabBarHeight();
|
||||
const {
|
||||
keyList,
|
||||
@@ -80,9 +86,27 @@ export const AllTrainDiagramView: FC = () => {
|
||||
openTrainInfo: (d: string) => void;
|
||||
};
|
||||
const Item: FC<ItemProps> = ({ id, openTrainInfo }) => {
|
||||
const { train_info_img, train_name, type, train_num_distance, to_data } =
|
||||
customTrainDataDetector(id, allCustomTrainData);
|
||||
const todayOperation = getTodayOperationByTrainId(id).filter(d=> d.state !== 100);
|
||||
const customTrainData = customTrainDataDetector(id, allCustomTrainData);
|
||||
const {
|
||||
train_name,
|
||||
type,
|
||||
train_num_distance,
|
||||
to_data,
|
||||
infogram,
|
||||
directions,
|
||||
} = customTrainData;
|
||||
const todayOperation = (getTodayOperationByTrainId(id) ?? []).filter(d=> d.state !== 100);
|
||||
const trainIconData = resolveTrainIconEntries({
|
||||
trainNum: id,
|
||||
customTrainData,
|
||||
todayOperation,
|
||||
iconDisplayMode,
|
||||
});
|
||||
let iconTrainDirection =
|
||||
parseInt(id.replace(/[^\d]/g, "")) % 2 == 0 ? true : false;
|
||||
if (directions != undefined) {
|
||||
iconTrainDirection = directions ? true : false;
|
||||
}
|
||||
const [isWrapped, setIsWrapped] = useState(false);
|
||||
|
||||
const [typeString, fontAvailable, isOneMan] = getStringConfig(type, id);
|
||||
@@ -124,29 +148,11 @@ export const AllTrainDiagramView: FC = () => {
|
||||
onPress={() => openTrainInfo(id)}
|
||||
>
|
||||
<View style={{ marginHorizontal: 5, flexDirection: "row" }}>
|
||||
{todayOperation.length > 0
|
||||
? todayOperation.map((operation, index) => (
|
||||
<Image
|
||||
key={index}
|
||||
source={{ uri: operation.vehicle_img || train_info_img }}
|
||||
style={{
|
||||
width: 20,
|
||||
height: 22,
|
||||
marginHorizontal: 2,
|
||||
display: index == 0 ? "flex" : "none", //暫定対応:複数アイコンがある場合は最初のアイコンのみ表示
|
||||
}}
|
||||
/>
|
||||
))
|
||||
: train_info_img && (
|
||||
<Image
|
||||
source={{ uri: train_info_img }}
|
||||
style={{
|
||||
width: 20,
|
||||
height: 22,
|
||||
marginHorizontal: 2,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<TrainIconStack
|
||||
entries={trainIconData}
|
||||
direction={iconTrainDirection}
|
||||
variant="list"
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View
|
||||
@@ -173,22 +179,33 @@ export const AllTrainDiagramView: FC = () => {
|
||||
)}
|
||||
{isOneMan && <OneManText />}
|
||||
</View>
|
||||
{trainNameString && (
|
||||
<Text
|
||||
{(trainNameString || infogram) && (
|
||||
<View
|
||||
style={{
|
||||
fontSize: 20,
|
||||
fontWeight: "bold",
|
||||
color: fixed.textOnPrimary,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
flexShrink: 1,
|
||||
}}
|
||||
onTextLayout={(e) => {
|
||||
if (e.nativeEvent.lines.length > 1) {
|
||||
setIsWrapped(true);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{trainNameString}
|
||||
</Text>
|
||||
{trainNameString && (
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 20,
|
||||
fontWeight: "bold",
|
||||
color: fixed.textOnPrimary,
|
||||
flexShrink: 1,
|
||||
}}
|
||||
onTextLayout={(e) => {
|
||||
if (e.nativeEvent.lines.length > 1) {
|
||||
setIsWrapped(true);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{trainNameString}
|
||||
</Text>
|
||||
)}
|
||||
{infogram ? <InfogramText infogram={infogram} fontSize={18} /> : null}
|
||||
</View>
|
||||
)}
|
||||
<View style={{ flex: 1 }} />
|
||||
<Text style={{ fontSize: 20, fontWeight: "bold", color: fixed.textOnPrimary }}>
|
||||
|
||||
@@ -26,6 +26,8 @@ import { Ionicons } from "@expo/vector-icons";
|
||||
import dayjs from "dayjs";
|
||||
import { useTrainMenu } from "@/stateBox/useTrainMenu";
|
||||
import { useThemeColors } from "@/lib/theme";
|
||||
import { normalizeIconDisplayMode } from "@/lib/iconDisplayMode";
|
||||
import { resolveTrainDataIcon } from "@/lib/trainDataIcon";
|
||||
import {
|
||||
startTrainFollowActivity,
|
||||
updateTrainFollowActivity,
|
||||
@@ -48,8 +50,9 @@ export const FixedTrain: FC<props> = ({ trainID }) => {
|
||||
setFixedPositionSize,
|
||||
} = useCurrentTrain();
|
||||
|
||||
const { mapSwitch } = useTrainMenu();
|
||||
const { mapSwitch, iconSetting } = useTrainMenu();
|
||||
const { allCustomTrainData, allTrainDiagram } = useAllTrainDiagram();
|
||||
const iconDisplayMode = normalizeIconDisplayMode(iconSetting);
|
||||
|
||||
const [liveNotifyId, setLiveNotifyId] = useState<string | null>(null);
|
||||
const liveNotifyIdRef = useRef<string | null>(null);
|
||||
@@ -59,11 +62,12 @@ export const FixedTrain: FC<props> = ({ trainID }) => {
|
||||
const [customData, setCustomData] = useState<CustomTrainData>(
|
||||
getCurrentTrainData(trainID, currentTrain, allCustomTrainData)
|
||||
);
|
||||
const customTrainIcon = resolveTrainDataIcon(customData, iconDisplayMode);
|
||||
useEffect(() => {
|
||||
setCustomData(
|
||||
getCurrentTrainData(trainID, currentTrain, allCustomTrainData)
|
||||
);
|
||||
}, [currentTrain, trainID]);
|
||||
}, [currentTrain, trainID, allCustomTrainData]);
|
||||
useEffect(() => {
|
||||
const stationData = getCurrentStationData(trainID);
|
||||
if (stationData) {
|
||||
@@ -555,7 +559,7 @@ export const FixedTrain: FC<props> = ({ trainID }) => {
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
source={{ uri: customData.train_info_img || "" }}
|
||||
source={{ uri: customTrainIcon }}
|
||||
width={fixedPositionSize === 226 ? 23 : 14}
|
||||
height={fixedPositionSize === 226 ? 26 : 17}
|
||||
style={{ margin: 5 }}
|
||||
|
||||
@@ -32,15 +32,34 @@ export const LayoutSettings = ({
|
||||
<SheetHeaderItem title="レイアウト設定" LeftItem={{ title: "< 設定", onPress: goBack }} />
|
||||
<ScrollView style={{ flex: 1, backgroundColor: colors.background }}>
|
||||
<View style={{ flex: 1 }}>
|
||||
<SwitchArea
|
||||
str="列車アイコン表示"
|
||||
bool={iconSetting}
|
||||
setBool={setIconSetting}
|
||||
falseImage={require("../../assets/configuration/icon_default.jpg")}
|
||||
trueImage={require("../../assets/configuration/icon_original.jpg")}
|
||||
falseText={"本家\n(文字アイコン)"}
|
||||
trueText={"オリジナル\n(車種アイコン)"}
|
||||
/>
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: "#00000010",
|
||||
borderRadius: 10,
|
||||
margin: 5,
|
||||
}}
|
||||
>
|
||||
<TripleSwitchArea
|
||||
str="列車アイコン表示"
|
||||
bool={iconSetting}
|
||||
setBool={setIconSetting}
|
||||
firstItem={{
|
||||
firstImage: require("../../assets/configuration/icon_default.jpg"),
|
||||
firstText: "本家\n(文字アイコン)",
|
||||
firstValue: "default",
|
||||
}}
|
||||
secondItem={{
|
||||
secondImage: require("../../assets/configuration/icon_original.jpg"),
|
||||
secondText: "オリジナル\n(車種アイコン)",
|
||||
secondValue: "original",
|
||||
}}
|
||||
thirdItem={{
|
||||
thirdImage: require("../../assets/relationLogo/unyohub_logo.webp"),
|
||||
thirdText: "鉄道運用Hub\n(Hubアイコン)",
|
||||
thirdValue: "hub",
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
<SwitchArea
|
||||
str="列車表示"
|
||||
bool={uiSetting}
|
||||
|
||||
@@ -24,13 +24,17 @@ import { LauncherIconSettings } from "./LauncherIconSettings";
|
||||
import { DataSourceSettings } from "./DataSourceSettings";
|
||||
import { FelicaHistoryPage } from "./FelicaHistoryPage";
|
||||
import { SoundSettings } from "./SoundSettings";
|
||||
import {
|
||||
normalizeIconDisplayMode,
|
||||
type IconDisplayMode,
|
||||
} from "@/lib/iconDisplayMode";
|
||||
|
||||
const Stack = createStackNavigator();
|
||||
export default function Setting(props) {
|
||||
const {
|
||||
navigation: { navigate },
|
||||
} = props;
|
||||
const [iconSetting, setIconSetting] = useState(false);
|
||||
const [iconSetting, setIconSetting] = useState<IconDisplayMode>("original");
|
||||
const [mapSwitch, setMapSwitch] = useState(false);
|
||||
const [stationMenu, setStationMenu] = useState(false);
|
||||
const [usePDFView, setUsePDFView] = useState(false);
|
||||
@@ -40,7 +44,9 @@ export default function Setting(props) {
|
||||
const [startPage, setStartPage] = useState(false);
|
||||
const [uiSetting, setUiSetting] = useState("tokyo");
|
||||
useLayoutEffect(() => {
|
||||
AS.getItem(STORAGE_KEYS.ICON_SWITCH).then(setIconSetting);
|
||||
AS.getItem(STORAGE_KEYS.ICON_SWITCH).then((value) =>
|
||||
setIconSetting(normalizeIconDisplayMode(value)),
|
||||
);
|
||||
AS.getItem(STORAGE_KEYS.MAP_SWITCH).then(setMapSwitch);
|
||||
AS.getItem(STORAGE_KEYS.STATION_SWITCH).then(setStationMenu);
|
||||
AS.getItem(STORAGE_KEYS.USE_PDF_VIEW).then(setUsePDFView);
|
||||
|
||||
@@ -45,6 +45,7 @@ export type CustomTrainData = {
|
||||
type: trainTypeID;
|
||||
train_name: string;
|
||||
train_info_img: string;
|
||||
train_info_img_hub?: string | null;
|
||||
train_info_url: string;
|
||||
infogram: string;
|
||||
via_data: string;
|
||||
@@ -96,6 +97,8 @@ export type OperationLogs = {
|
||||
unit_ids?: string[];
|
||||
vehicle_img: string;
|
||||
vehicle_img_right: string;
|
||||
vehicle_img_hub?: string | null;
|
||||
vehicle_img_right_hub?: string | null;
|
||||
vehicle_info_url: string;
|
||||
related_train_ids?: string[];
|
||||
state: number | null;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
export type IconDisplayMode = "default" | "original" | "hub";
|
||||
|
||||
export const normalizeIconDisplayMode = (
|
||||
value: unknown,
|
||||
): IconDisplayMode => {
|
||||
if (value === "hub") return "hub";
|
||||
if (value === "default" || value === "false" || value === false) {
|
||||
return "default";
|
||||
}
|
||||
return "original";
|
||||
};
|
||||
|
||||
export const isHubIconDisplayMode = (value: unknown): boolean =>
|
||||
normalizeIconDisplayMode(value) === "hub";
|
||||
|
||||
export const usesCustomTrainIcons = (value: unknown): boolean =>
|
||||
normalizeIconDisplayMode(value) !== "default";
|
||||
@@ -0,0 +1,60 @@
|
||||
import type { OperationLogs } from "@/lib/CommonTypes";
|
||||
import {
|
||||
normalizeIconDisplayMode,
|
||||
type IconDisplayMode,
|
||||
} from "@/lib/iconDisplayMode";
|
||||
|
||||
type OperationIconPair = {
|
||||
forward: string;
|
||||
rear: string;
|
||||
};
|
||||
|
||||
export const resolveOperationIconPair = (
|
||||
operation: Pick<
|
||||
OperationLogs,
|
||||
| "vehicle_img"
|
||||
| "vehicle_img_right"
|
||||
| "vehicle_img_hub"
|
||||
| "vehicle_img_right_hub"
|
||||
>,
|
||||
iconDisplayMode: IconDisplayMode,
|
||||
fallback = "",
|
||||
): OperationIconPair => {
|
||||
if (iconDisplayMode === "hub") {
|
||||
return {
|
||||
forward: operation.vehicle_img_hub || operation.vehicle_img || fallback,
|
||||
rear:
|
||||
operation.vehicle_img_right_hub ||
|
||||
operation.vehicle_img_hub ||
|
||||
operation.vehicle_img_right ||
|
||||
operation.vehicle_img ||
|
||||
fallback,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
forward: operation.vehicle_img || fallback,
|
||||
rear: operation.vehicle_img_right || operation.vehicle_img || fallback,
|
||||
};
|
||||
};
|
||||
|
||||
export const resolveDirectionalOperationIcon = (
|
||||
operation: Pick<
|
||||
OperationLogs,
|
||||
| "vehicle_img"
|
||||
| "vehicle_img_right"
|
||||
| "vehicle_img_hub"
|
||||
| "vehicle_img_right_hub"
|
||||
>,
|
||||
iconDisplayModeValue: unknown,
|
||||
direction: boolean,
|
||||
fallback = "",
|
||||
): string => {
|
||||
const iconDisplayMode = normalizeIconDisplayMode(iconDisplayModeValue);
|
||||
const { forward, rear } = resolveOperationIconPair(
|
||||
operation,
|
||||
iconDisplayMode,
|
||||
fallback,
|
||||
);
|
||||
return direction ? forward || rear : rear || forward;
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { CustomTrainData } from "@/lib/CommonTypes";
|
||||
import {
|
||||
normalizeIconDisplayMode,
|
||||
type IconDisplayMode,
|
||||
} from "@/lib/iconDisplayMode";
|
||||
|
||||
export const resolveTrainDataIcon = (
|
||||
trainData: Pick<CustomTrainData, "train_info_img" | "train_info_img_hub">,
|
||||
iconDisplayMode: IconDisplayMode,
|
||||
fallback = "",
|
||||
): string => {
|
||||
if (iconDisplayMode === "hub") {
|
||||
return trainData.train_info_img_hub || trainData.train_info_img || fallback;
|
||||
}
|
||||
|
||||
return trainData.train_info_img || fallback;
|
||||
};
|
||||
|
||||
export const resolveTrainDataIconFromValue = (
|
||||
trainData: Pick<CustomTrainData, "train_info_img" | "train_info_img_hub">,
|
||||
iconDisplayModeValue: unknown,
|
||||
fallback = "",
|
||||
): string =>
|
||||
resolveTrainDataIcon(
|
||||
trainData,
|
||||
normalizeIconDisplayMode(iconDisplayModeValue),
|
||||
fallback,
|
||||
);
|
||||
@@ -0,0 +1,97 @@
|
||||
import type { CustomTrainData, OperationLogs } from "@/lib/CommonTypes";
|
||||
import type { IconDisplayMode } from "@/lib/iconDisplayMode";
|
||||
import { resolveOperationIconPair } from "@/lib/operationLogIcon";
|
||||
import { resolveTrainDataIcon } from "@/lib/trainDataIcon";
|
||||
|
||||
export type TrainIconEntry = {
|
||||
vehicle_info_img: string;
|
||||
vehicle_info_right_img: string;
|
||||
vehicle_info_url: string;
|
||||
};
|
||||
|
||||
type TrainDataForIcon = Pick<
|
||||
CustomTrainData,
|
||||
"train_info_img" | "train_info_img_hub" | "vehicle_info_url"
|
||||
>;
|
||||
|
||||
const extractOrderNumber = (trainId: string): number => {
|
||||
const parts = trainId.split(",");
|
||||
if (parts.length <= 1) return Infinity;
|
||||
|
||||
const num = parseInt(parts[1].trim(), 10);
|
||||
return isNaN(num) ? Infinity : num;
|
||||
};
|
||||
|
||||
const findMatchingTrainId = (
|
||||
operation: OperationLogs,
|
||||
trainNum: string,
|
||||
): string | null => {
|
||||
const allTrainIds = [
|
||||
...(operation.train_ids || []),
|
||||
...(operation.related_train_ids || []),
|
||||
];
|
||||
|
||||
for (const trainId of allTrainIds) {
|
||||
const prefix = trainId.split(",")[0];
|
||||
if (prefix === trainNum) return trainId;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export const sortOperationsForTrainIcon = (
|
||||
operations: OperationLogs[],
|
||||
trainNum: string,
|
||||
): OperationLogs[] =>
|
||||
[...operations].sort((a, b) => {
|
||||
const aTrainId = findMatchingTrainId(a, trainNum);
|
||||
const bTrainId = findMatchingTrainId(b, trainNum);
|
||||
|
||||
if (!aTrainId || !bTrainId) {
|
||||
return aTrainId ? -1 : bTrainId ? 1 : 0;
|
||||
}
|
||||
|
||||
return extractOrderNumber(aTrainId) - extractOrderNumber(bTrainId);
|
||||
});
|
||||
|
||||
export const resolveTrainIconEntries = ({
|
||||
trainNum,
|
||||
customTrainData,
|
||||
todayOperation,
|
||||
iconDisplayMode,
|
||||
}: {
|
||||
trainNum: string;
|
||||
customTrainData: TrainDataForIcon;
|
||||
todayOperation: OperationLogs[];
|
||||
iconDisplayMode: IconDisplayMode;
|
||||
}): TrainIconEntry[] => {
|
||||
const fallbackIcon = resolveTrainDataIcon(customTrainData, iconDisplayMode);
|
||||
|
||||
if (todayOperation.length > 0) {
|
||||
return sortOperationsForTrainIcon(todayOperation, trainNum)
|
||||
.map((operation) => {
|
||||
const { forward, rear } = resolveOperationIconPair(
|
||||
operation,
|
||||
iconDisplayMode,
|
||||
fallbackIcon,
|
||||
);
|
||||
|
||||
return {
|
||||
vehicle_info_img: forward,
|
||||
vehicle_info_right_img: rear,
|
||||
vehicle_info_url: operation.vehicle_info_url,
|
||||
};
|
||||
})
|
||||
.filter((entry) => entry.vehicle_info_img || entry.vehicle_info_right_img);
|
||||
}
|
||||
|
||||
if (!fallbackIcon) return [];
|
||||
|
||||
return [
|
||||
{
|
||||
vehicle_info_img: fallbackIcon,
|
||||
vehicle_info_right_img: fallbackIcon,
|
||||
vehicle_info_url: customTrainData.vehicle_info_url || "",
|
||||
},
|
||||
];
|
||||
};
|
||||
@@ -3,6 +3,11 @@ import { TRAIN_TYPE_CONFIG } from './webview/trainTypeConfig';
|
||||
import { TRAIN_ICON_MAP, TRAIN_ICON_REGEX } from './webview/trainIconMap';
|
||||
import { STATION_DATA } from './webview/stationData';
|
||||
import { generateXhrInterceptorJs, MockApiConfig } from './mockApi/webviewXhrInterceptor';
|
||||
import {
|
||||
isHubIconDisplayMode,
|
||||
normalizeIconDisplayMode,
|
||||
usesCustomTrainIcons,
|
||||
} from './iconDisplayMode';
|
||||
import dosan from '@/assets/originData/dosan';
|
||||
import dosan2 from '@/assets/originData/dosan2';
|
||||
import koutoku from '@/assets/originData/koutoku';
|
||||
@@ -16,7 +21,7 @@ import yosan from '@/assets/originData/yosan';
|
||||
export interface InjectJavascriptOptions {
|
||||
/** 地図スイッチ ("true" | "false") */
|
||||
mapSwitch: string;
|
||||
/** 列車アイコン表示スイッチ ("true" | "false") */
|
||||
/** 列車アイコン表示モード ("default" | "original" | "hub") */
|
||||
iconSetting: string;
|
||||
/** 駅メニュースイッチ ("true" | "false") */
|
||||
stationMenu: string;
|
||||
@@ -63,6 +68,9 @@ export const injectJavascriptData = ({
|
||||
diagramTodayUrl,
|
||||
mockApiConfig,
|
||||
}: InjectJavascriptOptions): string => {
|
||||
const iconDisplayMode = normalizeIconDisplayMode(iconSetting);
|
||||
const preferHubTrainIcon = isHubIconDisplayMode(iconDisplayMode);
|
||||
const useVehicleIcons = usesCustomTrainIcons(iconDisplayMode);
|
||||
const MARINE_STATION_SEQUENCE = [
|
||||
"岡山", "大元", "備前西市", "妹尾", "早島", "茶屋町", "植松", "木見", "上の町",
|
||||
"児島", "坂出", "鴨川", "国分", "端岡", "鬼無", "高松",
|
||||
@@ -626,17 +634,22 @@ export const injectJavascriptData = ({
|
||||
`;
|
||||
// 左か右かを判定してアイコンを設置する
|
||||
const trainIcon = `
|
||||
const _preferHubTrainIcon = ${preferHubTrainIcon};
|
||||
const setStationIcon = (setIconElem,img,hasProblem,backCount = 100) =>{
|
||||
const position = setIconElem.getAttribute("style").includes("left");
|
||||
const isHubDataset = _preferHubTrainIcon && typeof img === "string" && img.includes("unyohub-icon-dataset/");
|
||||
let marginData = ${uiSetting === "tokyo" ? `"5px"`: `"2px"`};
|
||||
let backgroundColor = "transparent";
|
||||
let heightData = "22px";
|
||||
let widthData = isHubDataset ? "18px" : "auto";
|
||||
let transformData = isHubDataset ? "scale(1.15)" : "none";
|
||||
if(backCount == 0){
|
||||
marginData = position ? ${uiSetting === "tokyo" ? `"0px 0px -10px 0px" : "-10px 0px 0px 0px"`: `"0px 2px 0px 0px" : "0px 2px 0px 0px"`};
|
||||
heightData = "16px";
|
||||
widthData = isHubDataset ? "13px" : "auto";
|
||||
}
|
||||
|
||||
setIconElem.insertAdjacentHTML('beforebegin', "<img src="+img+" style='float:"+(position ? 'left' : 'right')+";height:"+heightData+";margin: "+marginData+";background-color: "+backgroundColor+";'>");
|
||||
setIconElem.insertAdjacentHTML('beforebegin', "<img src="+img+" style='float:"+(position ? 'left' : 'right')+";height:"+heightData+";width:"+widthData+";object-fit:contain;transform:"+transformData+";transform-origin:center center;margin: "+marginData+";background-color: "+backgroundColor+";'>");
|
||||
if (backCount == 0 || backCount == 100) setIconElem.remove();
|
||||
}
|
||||
|
||||
@@ -650,6 +663,16 @@ export const injectJavascriptData = ({
|
||||
if (new RegExp(pattern).test(列番データ)) return url;
|
||||
}
|
||||
};
|
||||
|
||||
const pickOperationTrainIcon = (operation, direction) => {
|
||||
const forward = _preferHubTrainIcon
|
||||
? (operation.vehicle_img_hub || operation.vehicle_img)
|
||||
: operation.vehicle_img;
|
||||
const rear = _preferHubTrainIcon
|
||||
? (operation.vehicle_img_right_hub || operation.vehicle_img_hub || operation.vehicle_img_right || operation.vehicle_img)
|
||||
: (operation.vehicle_img_right || operation.vehicle_img);
|
||||
return direction ? (forward || rear) : (rear || forward);
|
||||
};
|
||||
`;
|
||||
|
||||
const normal_train_name = `
|
||||
@@ -1159,7 +1182,7 @@ const setStrings = () =>{
|
||||
var TrainType = undefined;
|
||||
setTrainMenuDialog(element)
|
||||
|
||||
${iconSetting == "true" ? `
|
||||
${useVehicleIcons ? `
|
||||
let trainIconUrl = [];
|
||||
operationList
|
||||
.sort((a,b)=>sortOperationalList(a,b,列番データ.toString()))
|
||||
@@ -1173,14 +1196,8 @@ const setStrings = () =>{
|
||||
if(directions != null && directions != undefined){
|
||||
iconTrainDirection = directions ? true : false;
|
||||
}
|
||||
if(iconTrainDirection){
|
||||
if(e.vehicle_img) trainIconUrl.push(e.vehicle_img);
|
||||
else if(e.vehicle_img_right) trainIconUrl.push(e.vehicle_img_right);
|
||||
}else{
|
||||
if(e.vehicle_img_right) trainIconUrl.push(e.vehicle_img_right);
|
||||
else if(e.vehicle_img) trainIconUrl.push(e.vehicle_img);
|
||||
}
|
||||
|
||||
const iconUrl = pickOperationTrainIcon(e, iconTrainDirection);
|
||||
if(iconUrl) trainIconUrl.push(iconUrl);
|
||||
}
|
||||
} else if (e.related_train_ids?.length > 0) {
|
||||
const trainIds = e.related_train_ids.map(
|
||||
@@ -1192,13 +1209,8 @@ const setStrings = () =>{
|
||||
if(directions != null && directions != undefined){
|
||||
iconTrainDirection = directions ? true : false;
|
||||
}
|
||||
if(iconTrainDirection){
|
||||
if(e.vehicle_img) trainIconUrl.push(e.vehicle_img);
|
||||
else if(e.vehicle_img_right) trainIconUrl.push(e.vehicle_img_right);
|
||||
}else{
|
||||
if(e.vehicle_img_right) trainIconUrl.push(e.vehicle_img_right);
|
||||
else if(e.vehicle_img) trainIconUrl.push(e.vehicle_img);
|
||||
}
|
||||
const iconUrl = pickOperationTrainIcon(e, iconTrainDirection);
|
||||
if(iconUrl) trainIconUrl.push(iconUrl);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1212,7 +1224,8 @@ const setStrings = () =>{
|
||||
}
|
||||
else{
|
||||
if(trainDataList.find(e => e.train_id === 列番データ) !== undefined){
|
||||
const trainIconUrl = [trainDataList.find(e => e.train_id === 列番データ).train_info_img];
|
||||
const trainData = trainDataList.find(e => e.train_id === 列番データ);
|
||||
const trainIconUrl = [_preferHubTrainIcon ? (trainData.train_info_img_hub || trainData.train_info_img) : trainData.train_info_img];
|
||||
if(trainIconUrl.length > 0){
|
||||
trainIconUrl.forEach((url,index,array) => {
|
||||
if(url && url != ""){
|
||||
|
||||
@@ -24,7 +24,7 @@ const noUserscript = args.includes('--no-userscript');
|
||||
|
||||
const options = {
|
||||
mapSwitch: 'false',
|
||||
iconSetting: 'true',
|
||||
iconSetting: 'original',
|
||||
stationMenu: 'false',
|
||||
trainMenu: 'false',
|
||||
uiSetting: (process.env.UI ?? 'tokyo') as string,
|
||||
|
||||
@@ -37,6 +37,10 @@ import {
|
||||
import { useNotification } from "../stateBox/useNotifications";
|
||||
import { useThemeColors } from "@/lib/theme";
|
||||
import { STORAGE_KEYS } from "@/constants/storage";
|
||||
import {
|
||||
normalizeIconDisplayMode,
|
||||
type IconDisplayMode,
|
||||
} from "@/lib/iconDisplayMode";
|
||||
import {
|
||||
getBackendApiBaseUrl,
|
||||
getDiagramTodayUrl,
|
||||
@@ -124,7 +128,9 @@ export const TrainMenuProvider: FC<props> = ({ children }) => {
|
||||
}, []);
|
||||
type boolType = "true" | "false" | undefined;
|
||||
//画面表示関連
|
||||
const [iconSetting, setIconSetting] = useState<boolType>(undefined);
|
||||
const [iconSetting, setIconSetting] = useState<IconDisplayMode | undefined>(
|
||||
undefined,
|
||||
);
|
||||
const [mapSwitch, setMapSwitch] = useState<boolType>(undefined);
|
||||
const [stationMenu, setStationMenu] = useState<boolType>(undefined);
|
||||
const [LoadError, setLoadError] = useState(false);
|
||||
@@ -335,8 +341,8 @@ export const TrainMenuProvider: FC<props> = ({ children }) => {
|
||||
//列車アイコンスイッチ
|
||||
ASCore({
|
||||
k: STORAGE_KEYS.ICON_SWITCH,
|
||||
s: setIconSetting,
|
||||
d: "true",
|
||||
s: (value) => setIconSetting(normalizeIconDisplayMode(value)),
|
||||
d: "original",
|
||||
u: true,
|
||||
});
|
||||
//地図スイッチ
|
||||
|
||||
Reference in New Issue
Block a user