145 lines
4.1 KiB
TypeScript
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",
|
|
},
|
|
});
|