fix(tvOS): Patches for udp and screens menu button handling (#1564)

This commit is contained in:
Steve Byatt
2026-05-20 14:30:40 +01:00
committed by GitHub
parent e84cea6427
commit 4bef386b82
11 changed files with 210 additions and 331 deletions

View File

@@ -1,18 +1,10 @@
import { Ionicons } from "@expo/vector-icons";
import { t } from "i18next";
import React, { useEffect, useRef, useState } from "react";
import {
Animated,
BackHandler,
Easing,
Platform,
Pressable,
ScrollView,
View,
} from "react-native";
import React, { useCallback, useState } from "react";
import { ScrollView, View } from "react-native";
import { Button } from "@/components/Button";
import { Text } from "@/components/common/Text";
import { useScaledTVTypography } from "@/constants/TVTypography";
import { useTVBackPress } from "@/hooks/useTVBackPress";
import { TVInput } from "./TVInput";
import { TVSaveAccountToggle } from "./TVSaveAccountToggle";
@@ -30,68 +22,6 @@ interface TVAddUserFormProps {
disabled?: boolean;
}
const TVBackButton: React.FC<{
onPress: () => void;
label: string;
disabled?: boolean;
}> = ({ onPress, label, disabled = false }) => {
const [isFocused, setIsFocused] = useState(false);
const scale = useRef(new Animated.Value(1)).current;
const animateFocus = (focused: boolean) => {
Animated.timing(scale, {
toValue: focused ? 1.05 : 1,
duration: 150,
easing: Easing.out(Easing.quad),
useNativeDriver: true,
}).start();
};
return (
<Pressable
onPress={onPress}
onFocus={() => {
setIsFocused(true);
animateFocus(true);
}}
onBlur={() => {
setIsFocused(false);
animateFocus(false);
}}
style={{ alignSelf: "flex-start", marginBottom: 40 }}
disabled={disabled}
focusable={!disabled}
>
<Animated.View
style={{
transform: [{ scale }],
flexDirection: "row",
alignItems: "center",
paddingVertical: 8,
paddingHorizontal: 12,
borderRadius: 8,
backgroundColor: isFocused ? "#fff" : "rgba(255, 255, 255, 0.15)",
}}
>
<Ionicons
name='chevron-back'
size={28}
color={isFocused ? "#000" : "#fff"}
/>
<Text
style={{
color: isFocused ? "#000" : "#fff",
fontSize: 20,
marginLeft: 4,
}}
>
{label}
</Text>
</Animated.View>
</Pressable>
);
};
export const TVAddUserForm: React.FC<TVAddUserFormProps> = ({
serverName,
serverAddress,
@@ -116,23 +46,13 @@ export const TVAddUserForm: React.FC<TVAddUserFormProps> = ({
const isDisabled = disabled || loading;
// Handle Android TV back button, needed as an "override"
useEffect(() => {
if (!Platform.isTV) return;
const handleBack = useCallback(() => {
if (isDisabled) return false;
onBack();
return true;
}, [isDisabled, onBack]);
const handleBackPress = () => {
if (disabled) return false;
onBack();
return true;
};
const subscription = BackHandler.addEventListener(
"hardwareBackPress",
handleBackPress,
);
return () => subscription.remove();
}, [onBack, disabled]);
useTVBackPress(() => handleBack(), [handleBack]);
return (
<ScrollView
@@ -152,13 +72,6 @@ export const TVAddUserForm: React.FC<TVAddUserFormProps> = ({
paddingHorizontal: 60,
}}
>
{/* Back Button */}
<TVBackButton
onPress={onBack}
label={t("common.back")}
disabled={isDisabled}
/>
{/* Title */}
<Text
style={{