mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-05-30 18:48:30 +01:00
chore: upgrade Biome to 2.4.16, clean up lint, and fix TV password modal (#1598)
This commit is contained in:
@@ -414,7 +414,7 @@ export const PlayButton: React.FC<Props> = ({
|
||||
]);
|
||||
|
||||
const derivedTargetWidth = useDerivedValue(() => {
|
||||
if (!item || !item.RunTimeTicks) return 0;
|
||||
if (!item?.RunTimeTicks) return 0;
|
||||
const userData = item.UserData;
|
||||
if (userData?.PlaybackPositionTicks) {
|
||||
return userData.PlaybackPositionTicks > 0
|
||||
|
||||
@@ -78,7 +78,7 @@ export const PlayButton: React.FC<Props> = ({
|
||||
};
|
||||
|
||||
const derivedTargetWidth = useDerivedValue(() => {
|
||||
if (!item || !item.RunTimeTicks) return 0;
|
||||
if (!item?.RunTimeTicks) return 0;
|
||||
const userData = item.UserData;
|
||||
if (userData?.PlaybackPositionTicks) {
|
||||
return userData.PlaybackPositionTicks > 0
|
||||
|
||||
@@ -116,7 +116,7 @@ export const DownloadCard = ({ process, ...props }: DownloadCardProps) => {
|
||||
}, [process?.progress]);
|
||||
|
||||
// Return null after all hooks have been called
|
||||
if (!process || !process.item || !process.item.Id) {
|
||||
if (!process?.item?.Id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -351,7 +351,7 @@ export const TVHeroCarousel: React.FC<TVHeroCarouselProps> = ({
|
||||
|
||||
// Get subtitle for episodes
|
||||
const episodeSubtitle = useMemo(() => {
|
||||
if (!activeItem || activeItem.Type !== "Episode") return null;
|
||||
if (activeItem?.Type !== "Episode") return null;
|
||||
return `S${activeItem.ParentIndexNumber} E${activeItem.IndexNumber} · ${activeItem.Name}`;
|
||||
}, [activeItem]);
|
||||
|
||||
|
||||
@@ -180,4 +180,4 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
export { CARD_WIDTH, CARD_HEIGHT };
|
||||
export { CARD_HEIGHT, CARD_WIDTH };
|
||||
|
||||
@@ -155,7 +155,7 @@ export const TVLiveTVGuide: React.FC = () => {
|
||||
);
|
||||
|
||||
// Fetch programs for visible channels
|
||||
const { data: programsData, isLoading: isLoadingPrograms } = useQuery({
|
||||
const { data: programsData } = useQuery({
|
||||
queryKey: [
|
||||
"livetv",
|
||||
"tv-guide",
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
} from "react-native";
|
||||
import { Text } from "@/components/common/Text";
|
||||
import { useTVFocusAnimation } from "@/components/tv";
|
||||
import { useTVBackPress } from "@/hooks/useTVBackPress";
|
||||
import { scaleSize } from "@/utils/scaleSize";
|
||||
|
||||
interface TVPasswordEntryModalProps {
|
||||
@@ -201,6 +202,13 @@ export const TVPasswordEntryModal: React.FC<TVPasswordEntryModalProps> = ({
|
||||
setIsReady(false);
|
||||
}, [visible]);
|
||||
|
||||
// Close the modal on the TV remote back/menu button while it is open.
|
||||
useTVBackPress(() => {
|
||||
if (!visible) return false;
|
||||
onClose();
|
||||
return true;
|
||||
}, [visible, onClose]);
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!password) {
|
||||
setError(t("password.enter_password"));
|
||||
|
||||
@@ -59,6 +59,7 @@ import { useRemoteControl } from "./hooks/useRemoteControl";
|
||||
import { useVideoTime } from "./hooks/useVideoTime";
|
||||
import { TechnicalInfoOverlay } from "./TechnicalInfoOverlay";
|
||||
import { TrickplayBubble } from "./TrickplayBubble";
|
||||
import type { Track } from "./types";
|
||||
import { useControlsTimeout } from "./useControlsTimeout";
|
||||
|
||||
interface Props {
|
||||
@@ -315,6 +316,31 @@ export const Controls: FC<Props> = ({
|
||||
[onSubtitleIndexChange],
|
||||
);
|
||||
|
||||
// Re-fetch subtitle streams from the server (e.g. after a server-side
|
||||
// download) and map them to the modal's Track shape. setTrack drives the
|
||||
// player through the same handler used for manual subtitle selection.
|
||||
const refreshSubtitleTracks = useCallback(async (): Promise<Track[]> => {
|
||||
try {
|
||||
const streams = (await onRefreshSubtitleTracks?.()) ?? [];
|
||||
// Skip streams without a real index: `?? -1` would alias them to the
|
||||
// "disable subtitles" sentinel and mis-route selection.
|
||||
return streams
|
||||
.filter((stream) => typeof stream.Index === "number")
|
||||
.map((stream) => {
|
||||
const index = stream.Index as number;
|
||||
return {
|
||||
name:
|
||||
stream.DisplayTitle ||
|
||||
`${stream.Language || "Unknown"} (${stream.Codec})`,
|
||||
index,
|
||||
setTrack: () => onSubtitleIndexChange?.(index),
|
||||
};
|
||||
});
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}, [onRefreshSubtitleTracks, onSubtitleIndexChange]);
|
||||
|
||||
const {
|
||||
trickPlayUrl,
|
||||
calculateTrickplayUrl,
|
||||
@@ -572,6 +598,9 @@ export const Controls: FC<Props> = ({
|
||||
disableTrack?.setTrack();
|
||||
},
|
||||
onLocalSubtitleDownloaded: handleLocalSubtitleDownloaded,
|
||||
refreshSubtitleTracks: onRefreshSubtitleTracks
|
||||
? refreshSubtitleTracks
|
||||
: undefined,
|
||||
});
|
||||
controlsInteractionRef.current();
|
||||
}, [
|
||||
@@ -581,6 +610,8 @@ export const Controls: FC<Props> = ({
|
||||
videoContextSubtitleTracks,
|
||||
subtitleIndex,
|
||||
handleLocalSubtitleDownloaded,
|
||||
onRefreshSubtitleTracks,
|
||||
refreshSubtitleTracks,
|
||||
]);
|
||||
|
||||
const handleToggleTechnicalInfo = useCallback(() => {
|
||||
|
||||
@@ -28,4 +28,4 @@ type Track = {
|
||||
localPath?: string;
|
||||
};
|
||||
|
||||
export type { EmbeddedSubtitle, ExternalSubtitle, TranscodedSubtitle, Track };
|
||||
export type { EmbeddedSubtitle, ExternalSubtitle, Track, TranscodedSubtitle };
|
||||
|
||||
Reference in New Issue
Block a user