fix(review): address second CodeRabbit pass

- streamystats: derive toggle enablement from the same effective URL the
  input renders (locked admin URL no longer disables every switch)
- FilterSheet: use the deep-equality rule for toggling that rendering
  already uses — option objects are recreated across renders
- DownloadCard: take t from useTranslation so badge labels re-render on
  language change
- fileOperations: count trickplay bytes in the storage total, matching
  the per-item size model
- PendingAccountSaveModal: warn instead of silently swallowing a failed
  account save
This commit is contained in:
Gauvino
2026-06-12 16:23:08 +02:00
parent 3247bf709c
commit 599096f883
5 changed files with 22 additions and 11 deletions

View File

@@ -58,7 +58,12 @@ export default function StreamystatsPage() {
pluginSettings?.streamyStatsPromotedWatchlists?.locked === true;
const hideWatchlistsTabLocked =
pluginSettings?.hideWatchlistsTab?.locked === true;
const isStreamystatsEnabled = !!url;
// The input renders the locked admin URL; enablement must follow the same
// effective value or every toggle stays disabled until local state syncs.
const effectiveUrl = isUrlLocked
? (settings?.streamyStatsServerUrl ?? "")
: url;
const isStreamystatsEnabled = !!effectiveUrl;
const onSave = useCallback(() => {
const cleanUrl = url.endsWith("/") ? url.slice(0, -1) : url;
@@ -155,9 +160,7 @@ export default function StreamystatsPage() {
placeholder={t(
"home.settings.plugins.streamystats.server_url_placeholder",
)}
value={
isUrlLocked ? (settings?.streamyStatsServerUrl ?? "") : url
}
value={effectiveUrl}
keyboardType='url'
returnKeyType='done'
autoCapitalize='none'

View File

@@ -37,7 +37,7 @@ export const PendingAccountSaveModal: React.FC = () => {
const serverName = pending?.serverName;
setPending(null);
saveCurrentAccount({ securityType, pinCode, serverName }).catch(
() => {},
(error) => console.warn("Failed to save account:", error),
);
}}
/>

View File

@@ -1,7 +1,7 @@
import { Ionicons } from "@expo/vector-icons";
import { Image } from "expo-image";
import { t } from "i18next";
import { useMemo } from "react";
import { useTranslation } from "react-i18next";
import {
ActivityIndicator,
TouchableOpacity,
@@ -35,6 +35,7 @@ interface DownloadCardProps extends TouchableOpacityProps {
}
export const DownloadCard = ({ process, ...props }: DownloadCardProps) => {
const { t } = useTranslation();
const { cancelDownload } = useDownload();
const router = useRouter();
const queryClient = useNetworkAwareQueryClient();

View File

@@ -193,15 +193,19 @@ export const FilterSheet = <T,>({
<View key={index}>
<TouchableOpacity
onPress={() => {
// Match the deep-equality rule used to render the selected
// state below — option objects are recreated across renders,
// so reference checks would re-add an already selected item.
const isSelected = values.some((value) => isEqual(value, item));
if (multiple) {
if (!values.includes(item)) set(values.concat(item));
else set(values.filter((v) => v !== item));
if (!isSelected) set(values.concat(item));
else set(values.filter((value) => !isEqual(value, item)));
setTimeout(() => {
setOpen(false);
}, 250);
} else {
if (!values.includes(item)) {
if (!isSelected) {
set([item]);
setTimeout(() => {
setOpen(false);

View File

@@ -97,6 +97,9 @@ export function getDownloadedItemSize(id: string): number {
export function calculateTotalDownloadedSize(): number {
const items = getAllDownloadedItems();
return items.reduce((sum, item) => {
// Trickplay bytes count too — getDownloadedItemSize models per-item size
// as video + trickplay, the total must match.
const trickplaySize = item.trickPlayData?.size ?? 0;
// Read the live file size on disk so the total reflects actual usage and
// self-heals items whose stored videoFileSize is 0 (old schema, or
// `fileInfo.size` was undefined at download time). Fall back to the stored
@@ -105,12 +108,12 @@ export function calculateTotalDownloadedSize(): number {
try {
const file = new File(filePathToUri(item.videoFilePath));
if (file.exists) {
return sum + (file.size ?? item.videoFileSize ?? 0);
return sum + (file.size ?? item.videoFileSize ?? 0) + trickplaySize;
}
} catch (error) {
console.warn("Failed to stat downloaded file for size:", error);
}
}
return sum + (item.videoFileSize ?? 0);
return sum + (item.videoFileSize ?? 0) + trickplaySize;
}, 0);
}