fix(watch-connectivity): improve WCSession lifecycle and message reliability
This commit is contained in:
@@ -23,8 +23,9 @@ export function PreSwimScreen() {
|
||||
const navigation = useNavigation<NativeStackNavigationProp<RootStackParamList>>();
|
||||
const route = useRoute<RouteProp<RootStackParamList, "PreSwim">>();
|
||||
const [workout, setWorkout] = useState<WorkoutWithSets | null>(null);
|
||||
const [syncResult, setSyncResult] = useState<"sent" | "error" | null>(null);
|
||||
const { isSyncing, sendWorkoutToWatch } = useSyncWorkout();
|
||||
const { status, isPaired, isInstalled } = useWatchConnection();
|
||||
const { status, isPaired, isInstalled, isReady } = useWatchConnection();
|
||||
|
||||
useEffect(() => {
|
||||
loadWorkout();
|
||||
@@ -38,7 +39,7 @@ export function PreSwimScreen() {
|
||||
const handleStartSwim = async () => {
|
||||
if (!workout) return;
|
||||
|
||||
if (status !== "connected") {
|
||||
if (!isReady) {
|
||||
navigation.navigate("PostSwim", { workoutId: route.params.workoutId });
|
||||
return;
|
||||
}
|
||||
@@ -51,11 +52,11 @@ export function PreSwimScreen() {
|
||||
);
|
||||
|
||||
if ("error" in result) {
|
||||
navigation.navigate("PostSwim", { workoutId: route.params.workoutId });
|
||||
setSyncResult("error");
|
||||
return;
|
||||
}
|
||||
|
||||
navigation.navigate("PostSwim", { workoutId: route.params.workoutId });
|
||||
setSyncResult("sent");
|
||||
};
|
||||
|
||||
if (!workout) {
|
||||
@@ -66,6 +67,46 @@ export function PreSwimScreen() {
|
||||
);
|
||||
}
|
||||
|
||||
if (syncResult === "sent") {
|
||||
return (
|
||||
<View className="flex-1 bg-white p-4 items-center justify-center">
|
||||
<View className="bg-green-50 rounded-2xl p-6 items-center mb-6 w-full">
|
||||
<Text className="text-4xl mb-3">⌚</Text>
|
||||
<Text className="text-xl font-bold text-green-800 mb-2">Workout sent to Watch!</Text>
|
||||
<Text className="text-green-600 text-center">
|
||||
Open the SwimBuddy app on your Apple Watch to start tracking.
|
||||
</Text>
|
||||
</View>
|
||||
<Pressable
|
||||
onPress={() => navigation.popToTop()}
|
||||
className="bg-slate-900 rounded-2xl py-4 items-center w-full"
|
||||
>
|
||||
<Text className="text-white font-bold text-lg">Done</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
if (syncResult === "error") {
|
||||
return (
|
||||
<View className="flex-1 bg-white p-4 items-center justify-center">
|
||||
<View className="bg-red-50 rounded-2xl p-6 items-center mb-6 w-full">
|
||||
<Text className="text-4xl mb-3">⚠️</Text>
|
||||
<Text className="text-xl font-bold text-red-800 mb-2">Failed to send</Text>
|
||||
<Text className="text-red-600 text-center">
|
||||
Could not send workout to Watch. Starting without Watch instead.
|
||||
</Text>
|
||||
</View>
|
||||
<Pressable
|
||||
onPress={() => navigation.navigate("PostSwim", { workoutId: route.params.workoutId })}
|
||||
className="bg-sky-500 rounded-2xl py-4 items-center w-full"
|
||||
>
|
||||
<Text className="text-white font-bold text-lg">Start Without Watch</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View className="flex-1 bg-white p-4">
|
||||
<View className="items-center mb-6">
|
||||
@@ -112,14 +153,16 @@ export function PreSwimScreen() {
|
||||
<View className="bg-slate-50 rounded-2xl p-3 mb-6 flex-row items-center gap-3">
|
||||
<View
|
||||
className={`w-3 h-3 rounded-full ${
|
||||
status === "connected" ? "bg-green-500" : "bg-slate-300"
|
||||
isReady ? "bg-green-500" : isPaired ? "bg-yellow-500" : "bg-slate-300"
|
||||
}`}
|
||||
/>
|
||||
<Text className="text-sm text-slate-600">
|
||||
{status === "connected"
|
||||
? "Apple Watch connected"
|
||||
{isReady
|
||||
? "Apple Watch ready"
|
||||
: isPaired
|
||||
? "Watch paired but not connected"
|
||||
? isInstalled
|
||||
? "Watch paired but not in range"
|
||||
: "Watch paired, app not installed"
|
||||
: "No Watch paired"}
|
||||
</Text>
|
||||
</View>
|
||||
@@ -135,14 +178,14 @@ export function PreSwimScreen() {
|
||||
<ActivityIndicator color="#fff" />
|
||||
) : (
|
||||
<Text className="text-white font-bold text-lg">
|
||||
{status === "connected" ? "Send to Watch & Start" : "Start Without Watch"}
|
||||
{isReady ? "Send to Watch & Start" : "Start Without Watch"}
|
||||
</Text>
|
||||
)}
|
||||
</Pressable>
|
||||
|
||||
<Text className="text-slate-400 text-xs text-center mt-3">
|
||||
{status === "connected"
|
||||
? "Workout will be sent to your Apple Watch"
|
||||
{isReady
|
||||
? "Workout will be synced to your Apple Watch"
|
||||
: "Workout will be tracked on this device"}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user