fix(review): address CodeRabbit feedback

- swap direct i18next t imports for the useTranslation hook so the four
  touched components re-render on language change
- localize the buffer seconds unit via a buffer_seconds key instead of a
  literal trailing s
- reword the useAppRouter guard comment to match its real scope
This commit is contained in:
Gauvino
2026-06-12 15:00:49 +02:00
parent 2af252d639
commit 3247bf709c
7 changed files with 17 additions and 10 deletions

View File

@@ -6,7 +6,6 @@ import type {
MediaSourceInfo,
} from "@jellyfin/sdk/lib/generated-client/models";
import { Image } from "expo-image";
import { t } from "i18next";
import { useAtom } from "jotai";
import React, {
useCallback,
@@ -15,6 +14,7 @@ import React, {
useRef,
useState,
} from "react";
import { useTranslation } from "react-i18next";
import {
ActivityIndicator,
Dimensions,
@@ -73,6 +73,7 @@ const ARTWORK_SIZE = SCREEN_WIDTH - 80;
type ViewMode = "player" | "queue";
export default function NowPlayingScreen() {
const { t } = useTranslation();
const [api] = useAtom(apiAtom);
const [user] = useAtom(userAtom);
const router = useRouter();
@@ -721,6 +722,7 @@ const QueueView: React.FC<QueueViewProps> = ({
onRemoveFromQueue,
onReorderQueue,
}) => {
const { t } = useTranslation();
const renderQueueItem = useCallback(
({ item, drag, isActive, getIndex }: RenderItemParams<BaseItemDto>) => {
const index = getIndex() ?? 0;

View File

@@ -1,7 +1,7 @@
import { Ionicons } from "@expo/vector-icons";
import { BottomSheetScrollView } from "@gorhom/bottom-sheet";
import { t } from "i18next";
import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { Platform, StyleSheet, TouchableOpacity, View } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { Text } from "@/components/common/Text";
@@ -210,6 +210,7 @@ const PlatformDropdownComponent = ({
expoUIConfig,
bottomSheetConfig,
}: PlatformDropdownProps) => {
const { t } = useTranslation();
const { showModal, hideModal, isVisible } = useGlobalModal();
// Handle controlled open state for Android

View File

@@ -1,6 +1,6 @@
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client";
import { t } from "i18next";
import React from "react";
import { useTranslation } from "react-i18next";
import { Animated, Pressable, StyleSheet, View } from "react-native";
import { Text } from "@/components/common/Text";
import { useTVFocusAnimation } from "@/components/tv/hooks/useTVFocusAnimation";
@@ -23,6 +23,7 @@ export const TVGuideProgramCell: React.FC<TVGuideProgramCellProps> = ({
disabled = false,
refSetter,
}) => {
const { t } = useTranslation();
const typography = useScaledTVTypography();
const { focused, handleFocus, handleBlur } = useTVFocusAnimation({
scaleAmount: 1,

View File

@@ -1,9 +1,9 @@
import { Ionicons } from "@expo/vector-icons";
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { Image } from "expo-image";
import { t } from "i18next";
import { useAtomValue } from "jotai";
import React, { useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import {
Animated,
Easing,
@@ -107,6 +107,7 @@ export const TVPosterCard: React.FC<TVPosterCardProps> = ({
scaleAmount = 1.05,
imageUrlGetter,
}) => {
const { t } = useTranslation();
const api = useAtomValue(apiAtom);
const posterSizes = useScaledTVPosterSizes();
const typography = useScaledTVTypography();

View File

@@ -344,8 +344,9 @@ export const TechnicalInfoOverlay: FC<TechnicalInfoOverlayProps> = memo(
)}
{info?.cacheSeconds !== undefined && (
<Text style={textStyle}>
{t("player.technical_info.buffer")} {info.cacheSeconds.toFixed(1)}
s
{t("player.technical_info.buffer_seconds", {
seconds: info.cacheSeconds.toFixed(1),
})}
</Text>
)}
{info?.voDriver && (

View File

@@ -31,9 +31,10 @@ export function useAppRouter() {
const push = useCallback(
(href: Parameters<typeof router.push>[0]) => {
// Duplicate-screen guard: a push blurs the source screen synchronously in
// the navigation state (only the native render is slow). A second tap then
// sees an unfocused screen and is dropped. Resets automatically on return.
// Rapid-push guard: a push blurs the source screen synchronously in the
// navigation state (only the native render is slow). Any further push from
// this screen — duplicate or not — is dropped until focus returns, so taps
// fired before the pushed screen renders can't stack screens.
// No navigation context => nothing to guard (deep-link pushes from root).
if (navigation?.isFocused?.() === false) return;
if (typeof href === "string") {

View File

@@ -631,7 +631,7 @@
"audio": "Audio:",
"subtitle": "Subtitle:",
"bitrate": "Bitrate:",
"buffer": "Buffer:",
"buffer_seconds": "Buffer: {{seconds}}s",
"vo": "VO:",
"dropped_frames": "Dropped: {{count}} frames",
"loading": "Loading..."