Files

145 lines
4.1 KiB
TypeScript

import React, { FC, useCallback, useEffect } from "react";
import { Platform, TouchableOpacity, Text, StyleSheet } from "react-native";
import { useTrainFollowActivity } from "@/lib/useTrainFollowActivity";
import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
import { trainDataType } from "@/lib/trainPositionTextArray";
type Props = {
currentTrainData: trainDataType;
currentPosition: string[] | undefined;
};
export const LiveActivityButton: FC<Props> = ({
currentTrainData,
currentPosition,
}) => {
const liveActivity = useTrainFollowActivity();
const { allTrainDiagram } = useAllTrainDiagram();
const onLine = !!currentPosition?.toString().length;
const handleLiveActivity = useCallback(async () => {
if (liveActivity.status === "active") {
await liveActivity.end();
return;
}
if (!onLine) return;
const diagramStr: string =
(allTrainDiagram as Record<string, string>)[currentTrainData?.num] ?? "";
const stations = diagramStr
.split("#")
.filter(Boolean)
.map((s) => s.split(",")[0]);
const destination =
stations.length > 0 ? stations[stations.length - 1] : "";
const curSt = currentPosition?.[0] ?? currentTrainData?.Pos ?? "";
const curIdx = stations.indexOf(curSt);
const nextSt =
curIdx >= 0 && curIdx + 1 < stations.length
? stations[curIdx + 1]
: currentPosition?.[1] ?? "";
await liveActivity.start({
trainNumber: currentTrainData?.num ?? "",
lineName: currentTrainData?.Line ?? "",
destination,
currentStation: curSt,
nextStation: nextSt,
delayMinutes:
typeof currentTrainData?.delay === "number"
? currentTrainData.delay
: 0,
scheduledArrival: "",
});
}, [
liveActivity,
onLine,
allTrainDiagram,
currentTrainData,
currentPosition,
]);
// 列車位置が変わったら Live Activity を自動更新
useEffect(() => {
if (liveActivity.status !== "active") return;
if (!currentTrainData?.Pos) return;
const diagramStr: string =
(allTrainDiagram as Record<string, string>)[currentTrainData?.num] ?? "";
const stations = diagramStr
.split("#")
.filter(Boolean)
.map((s) => s.split(",")[0]);
const curSt = currentPosition?.[0] ?? currentTrainData.Pos;
const curIdx = stations.indexOf(curSt);
const nextSt =
curIdx >= 0 && curIdx + 1 < stations.length
? stations[curIdx + 1]
: currentPosition?.[1] ?? "";
liveActivity.update({
currentStation: curSt,
nextStation: nextSt,
delayMinutes:
typeof currentTrainData.delay === "number"
? currentTrainData.delay
: 0,
scheduledArrival: "",
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
currentTrainData?.Pos,
currentTrainData?.delay,
currentPosition?.toString(),
]);
if (Platform.OS !== "ios" || !liveActivity.available || !onLine) {
return null;
}
return (
<TouchableOpacity
onPress={handleLiveActivity}
disabled={liveActivity.status === "loading"}
style={[
styles.liveActivityButton,
liveActivity.status === "active" && styles.liveActivityButtonActive,
]}
>
<Text style={styles.liveActivityButtonText}>
{liveActivity.status === "active"
? "🔴 列車追従 Live Activity 終了"
: liveActivity.status === "loading"
? "⏳ 開始中..."
: "🟢 列車追従 Live Activity 開始"}
</Text>
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
liveActivityButton: {
marginHorizontal: 10,
marginVertical: 6,
paddingVertical: 10,
paddingHorizontal: 16,
borderRadius: 10,
backgroundColor: "rgba(0, 153, 204, 0.12)",
borderWidth: 1,
borderColor: "rgba(0, 153, 204, 0.5)",
alignItems: "center",
},
liveActivityButtonActive: {
backgroundColor: "rgba(220, 50, 50, 0.1)",
borderColor: "rgba(220, 50, 50, 0.5)",
},
liveActivityButtonText: {
fontSize: 14,
fontWeight: "600",
color: "#0099cc",
},
});