Files
streamyfin/components/video-player/controls/VideoScalingModeSelector.tsx
Uruk b7db06f53d docs: update README and fix typos across codebase
Enhances README with comprehensive feature categorization including Media Playback, Media Management, and Advanced Features sections

Expands documentation for music library support, search providers (Marlin, Streamystats, Jellysearch), and plugin functionality

Updates FAQ section with more detailed answers about library visibility, downloads, subtitles, TV platform support, and Seerr integration

Corrects typos throughout the application:
- Fixes "liraries" to "libraries" in hide libraries settings
- Changes "centralised" to "centralized" for consistency
- Updates "Jellyseerr" references to "Seerr" throughout codebase

Adds missing translations for player settings including aspect ratio options, alignment controls, and MPV subtitle customization

Improves consistency in capitalization and punctuation across translation strings
2026-01-12 09:41:24 +01:00

108 lines
2.6 KiB
TypeScript

import { Ionicons } from "@expo/vector-icons";
import React, { useMemo } from "react";
import { useTranslation } from "react-i18next";
import { Platform, View } from "react-native";
import {
type OptionGroup,
PlatformDropdown,
} from "@/components/PlatformDropdown";
import { useHaptic } from "@/hooks/useHaptic";
export type AspectRatio = "default" | "16:9" | "4:3" | "1:1" | "21:9";
interface AspectRatioSelectorProps {
currentRatio: AspectRatio;
onRatioChange: (ratio: AspectRatio) => void;
disabled?: boolean;
}
interface AspectRatioOption {
id: AspectRatio;
label: string;
descriptionKey: string;
}
export const AspectRatioSelector: React.FC<AspectRatioSelectorProps> = ({
currentRatio,
onRatioChange,
disabled = false,
}) => {
const lightHapticFeedback = useHaptic("light");
const { t } = useTranslation();
const handleRatioSelect = (ratio: AspectRatio) => {
onRatioChange(ratio);
lightHapticFeedback();
};
const ASPECT_RATIO_OPTIONS: AspectRatioOption[] = [
{
id: "default",
label: t("player.aspect_ratio_original"),
descriptionKey: "player.aspect_ratio_original_description",
},
{
id: "16:9",
label: "16:9",
descriptionKey: "player.aspect_ratio_16_9_description",
},
{
id: "4:3",
label: "4:3",
descriptionKey: "player.aspect_ratio_4_3_description",
},
{
id: "1:1",
label: "1:1",
descriptionKey: "player.aspect_ratio_1_1_description",
},
{
id: "21:9",
label: "21:9",
descriptionKey: "player.aspect_ratio_21_9_description",
},
];
const optionGroups = useMemo<OptionGroup[]>(() => {
return [
{
options: ASPECT_RATIO_OPTIONS.map((option) => ({
type: "radio" as const,
label: option.label,
value: option.id,
selected: option.id === currentRatio,
onPress: () => handleRatioSelect(option.id),
disabled,
})),
},
];
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentRatio, disabled]);
const trigger = useMemo(
() => (
<View
className='aspect-square flex flex-col rounded-xl items-center justify-center p-2'
style={{ opacity: disabled ? 0.5 : 1 }}
>
<Ionicons name='crop-outline' size={24} color='white' />
</View>
),
[disabled],
);
// Hide on TV platforms
if (Platform.isTV) return null;
return (
<PlatformDropdown
title={t("player.aspect_ratio_title")}
groups={optionGroups}
trigger={trigger}
bottomSheetConfig={{
enablePanDownToClose: true,
}}
/>
);
};