fix: scaling

Hopefully fixing scaling across different TV types for android/ios
Test for login screen at the moment

Signed-off-by: Lance Chant <13349722+lancechant@users.noreply.github.com>
This commit is contained in:
Lance Chant
2026-01-23 13:32:29 +02:00
parent 3a4042efd5
commit 566ff485fb
6 changed files with 163 additions and 38 deletions

View File

@@ -14,6 +14,7 @@ import {
TouchableOpacity,
View,
} from "react-native";
import { fontSize, size } from "react-native-responsive-sizes";
import { useHaptic } from "@/hooks/useHaptic";
import { Loader } from "./Loader";
@@ -140,11 +141,15 @@ export const Button: React.FC<PropsWithChildren<ButtonProps>> = ({
}}
>
<View
className={`rounded-2xl py-5 items-center justify-center
className={`rounded-2xl items-center justify-center
${colorClasses}
${className}`}
style={{ paddingVertical: size(20) }}
>
<Text className={`${textColorClass} text-xl font-bold`}>
<Text
className={`${textColorClass} font-bold`}
style={{ fontSize: fontSize(20) }}
>
{children}
</Text>
</View>

View File

@@ -4,7 +4,7 @@ export function Text(props: TextProps) {
if (Platform.isTV)
return (
<RNText
allowFontScaling={false}
allowFontScaling={true}
style={[{ color: "white" }, style]}
{...otherProps}
/>

View File

@@ -6,6 +6,7 @@ import {
TextInput,
type TextInputProps,
} from "react-native";
import { fontSize, size } from "react-native-responsive-sizes";
interface TVInputProps extends TextInputProps {
label?: string;
@@ -58,8 +59,8 @@ export const TVInput: React.FC<TVInputProps> = ({
<Animated.View
style={{
transform: [{ scale }],
borderRadius: 10,
borderWidth: 3,
borderRadius: size(20),
borderWidth: size(6),
borderColor: isFocused ? "#FFFFFF" : "#333333",
}}
>
@@ -69,8 +70,8 @@ export const TVInput: React.FC<TVInputProps> = ({
allowFontScaling={false}
style={[
{
height: 68,
fontSize: 24,
height: size(200),
fontSize: fontSize(12),
color: "#FFFFFF",
},
style,

View File

@@ -13,6 +13,7 @@ import {
ScrollView,
View,
} from "react-native";
import { fontSize, size } from "react-native-responsive-sizes";
import { z } from "zod";
import { Button } from "@/components/Button";
import { Text } from "@/components/common/Text";
@@ -66,7 +67,7 @@ const TVBackButton: React.FC<{
setIsFocused(false);
animateFocus(false);
}}
style={{ alignSelf: "flex-start", marginBottom: 40 }}
style={{ alignSelf: "flex-start", marginBottom: size(40) }}
disabled={disabled}
focusable={!disabled}
>
@@ -75,26 +76,25 @@ const TVBackButton: React.FC<{
transform: [{ scale }],
flexDirection: "row",
alignItems: "center",
paddingVertical: 8,
paddingHorizontal: 12,
borderRadius: 8,
paddingHorizontal: size(12),
borderRadius: size(8),
backgroundColor: isFocused
? "rgba(168, 85, 247, 0.2)"
: "transparent",
borderWidth: 2,
borderWidth: size(2),
borderColor: isFocused ? Colors.primary : "transparent",
}}
>
<Ionicons
name='chevron-back'
size={28}
size={size(28)}
color={isFocused ? "#FFFFFF" : Colors.primary}
/>
<Text
style={{
color: isFocused ? "#FFFFFF" : Colors.primary,
fontSize: 20,
marginLeft: 4,
fontSize: fontSize(14),
marginLeft: size(4),
}}
>
{label}
@@ -463,7 +463,7 @@ export const TVLogin: React.FC = () => {
flexGrow: 1,
justifyContent: "center",
alignItems: "center",
paddingVertical: 60,
paddingVertical: size(20),
}}
showsVerticalScrollIndicator={false}
>
@@ -471,7 +471,7 @@ export const TVLogin: React.FC = () => {
style={{
width: "100%",
maxWidth: 800,
paddingHorizontal: 60,
paddingHorizontal: size(40),
}}
>
{/* Back Button */}
@@ -484,10 +484,10 @@ export const TVLogin: React.FC = () => {
{/* Title */}
<Text
style={{
fontSize: 48,
fontSize: fontSize(12),
fontWeight: "bold",
color: "#FFFFFF",
marginBottom: 8,
marginBottom: size(8),
}}
>
{serverName ? (
@@ -501,16 +501,18 @@ export const TVLogin: React.FC = () => {
</Text>
<Text
style={{
fontSize: 18,
fontSize: fontSize(14),
color: "#9CA3AF",
marginBottom: 40,
marginBottom: size(40),
}}
>
{api.basePath}
</Text>
{/* Username Input - extra padding for focus scale */}
<View style={{ marginBottom: 24, paddingHorizontal: 8 }}>
<View
style={{ marginBottom: size(24), paddingHorizontal: size(8) }}
>
<TVInput
placeholder={t("login.username_placeholder")}
value={credentials.username}
@@ -527,7 +529,9 @@ export const TVLogin: React.FC = () => {
</View>
{/* Password Input */}
<View style={{ marginBottom: 32, paddingHorizontal: 8 }}>
<View
style={{ marginBottom: size(32), paddingHorizontal: size(8) }}
>
<TVInput
placeholder={t("login.password_placeholder")}
value={credentials.password}
@@ -543,7 +547,9 @@ export const TVLogin: React.FC = () => {
</View>
{/* Save Account Toggle */}
<View style={{ marginBottom: 40, paddingHorizontal: 8 }}>
<View
style={{ marginBottom: size(40), paddingHorizontal: size(8) }}
>
<TVSaveAccountToggle
value={saveAccount}
onValueChange={setSaveAccount}
@@ -553,7 +559,7 @@ export const TVLogin: React.FC = () => {
</View>
{/* Login Button */}
<View style={{ marginBottom: 16 }}>
<View style={{ marginBottom: size(16) }}>
<Button
onPress={handleLogin}
loading={loading}
@@ -579,9 +585,11 @@ export const TVLogin: React.FC = () => {
style={{ flex: 1 }}
contentContainerStyle={{
flexGrow: 1,
justifyContent: "center",
// justifyContent: "center",
alignItems: "center",
paddingVertical: 60,
justifyContent: "flex-start",
paddingTop: size(40),
paddingBottom: size(40),
}}
showsVerticalScrollIndicator={false}
>
@@ -589,14 +597,14 @@ export const TVLogin: React.FC = () => {
style={{
width: "100%",
maxWidth: 800,
paddingHorizontal: 60,
paddingHorizontal: size(60),
}}
>
{/* Logo */}
<View style={{ alignItems: "center", marginBottom: 16 }}>
<View style={{ alignItems: "center", marginBottom: size(16) }}>
<Image
source={require("@/assets/images/icon-tvos.png")}
style={{ width: 150, height: 150 }}
style={{ width: size(300), height: size(300) }}
contentFit='contain'
/>
</View>
@@ -604,28 +612,30 @@ export const TVLogin: React.FC = () => {
{/* Title */}
<Text
style={{
fontSize: 48,
fontSize: fontSize(24),
fontWeight: "bold",
color: "#FFFFFF",
textAlign: "center",
marginBottom: 8,
marginBottom: size(8),
}}
>
Streamyfin
</Text>
<Text
style={{
fontSize: 20,
fontSize: fontSize(20),
color: "#9CA3AF",
textAlign: "center",
marginBottom: 40,
marginBottom: size(40),
}}
>
{t("server.enter_url_to_jellyfin_server")}
</Text>
{/* Server URL Input - extra padding for focus scale */}
<View style={{ marginBottom: 24, paddingHorizontal: 8 }}>
<View
style={{ marginBottom: size(24), paddingHorizontal: size(8) }}
>
<TVInput
placeholder={t("server.server_url_placeholder")}
value={serverURL}
@@ -640,7 +650,7 @@ export const TVLogin: React.FC = () => {
</View>
{/* Connect Button */}
<View style={{ marginBottom: 24 }}>
<View style={{ marginBottom: size(12) }}>
<Button
onPress={() => handleConnect(serverURL)}
loading={loadingServerCheck}
@@ -651,7 +661,7 @@ export const TVLogin: React.FC = () => {
</View>
{/* Previous Servers */}
<View style={{ paddingHorizontal: 8 }}>
<View style={{ paddingHorizontal: size(8) }}>
<TVPreviousServersList
onServerSelect={(s) => handleConnect(s.address)}
onQuickLogin={handleQuickLoginWithSavedCredential}