feat(autoplay): add shared AutoplayCountdown overlay

This commit is contained in:
Uruk
2026-05-22 15:06:48 +02:00
parent 276ba1e4c5
commit 6c00a0348a
2 changed files with 108 additions and 1 deletions

View File

@@ -0,0 +1,103 @@
/**
* Player-agnostic "next episode" countdown card. The parent owns the timer and
* positioning — this component only renders the next episode's poster, title,
* the remaining seconds, and the Play-now / Cancel actions.
*/
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { Image } from "expo-image";
import { useTranslation } from "react-i18next";
import { Pressable, View } from "react-native";
import { Text } from "@/components/common/Text";
interface AutoplayCountdownProps {
/** The episode that will play next. */
nextEpisode: BaseItemDto;
/** Poster image URL for the next episode, or null. */
posterUrl: string | null;
/** Seconds left before the next episode plays. */
secondsRemaining: number;
/** Play the next episode immediately. */
onPlayNow: () => void;
/** Cancel autoplay — the next episode will not play. */
onCancel: () => void;
}
export function AutoplayCountdown({
nextEpisode,
posterUrl,
secondsRemaining,
onPlayNow,
onCancel,
}: AutoplayCountdownProps) {
const { t } = useTranslation();
return (
<View
style={{
flexDirection: "row",
gap: 12,
width: 320,
padding: 12,
borderRadius: 12,
backgroundColor: "rgba(20, 20, 20, 0.94)",
}}
>
{posterUrl && (
<Image
source={{ uri: posterUrl }}
style={{ width: 62, height: 93, borderRadius: 6 }}
contentFit='cover'
/>
)}
<View style={{ flex: 1, justifyContent: "space-between" }}>
<View style={{ gap: 2 }}>
<Text style={{ color: "#999", fontSize: 12 }}>
{t("player.up_next")}
</Text>
<Text
style={{ color: "#fff", fontSize: 15, fontWeight: "600" }}
numberOfLines={2}
>
{nextEpisode.Name}
</Text>
<Text style={{ color: "#a855f7", fontSize: 13 }}>
{t("player.next_episode_in", { seconds: secondsRemaining })}
</Text>
</View>
<View style={{ flexDirection: "row", gap: 8, marginTop: 8 }}>
<Pressable
onPress={onPlayNow}
accessibilityRole='button'
style={{
flex: 1,
paddingVertical: 8,
borderRadius: 8,
backgroundColor: "#a855f7",
alignItems: "center",
}}
>
<Text style={{ color: "#fff", fontWeight: "600" }}>
{t("player.play_now")}
</Text>
</Pressable>
<Pressable
onPress={onCancel}
accessibilityRole='button'
style={{
flex: 1,
paddingVertical: 8,
borderRadius: 8,
backgroundColor: "#333",
alignItems: "center",
}}
>
<Text style={{ color: "#fff", fontWeight: "600" }}>
{t("player.cancel")}
</Text>
</Pressable>
</View>
</View>
</View>
);
}

View File

@@ -47,7 +47,11 @@
"downloaded_file_message": "Do you want to play the downloaded file?",
"downloaded_file_yes": "Yes",
"downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel"
"downloaded_file_cancel": "Cancel",
"up_next": "Up next",
"next_episode_in": "Next episode in {{seconds}}s",
"play_now": "Play now",
"cancel": "Cancel"
},
"casting_player": {
"buffering": "Buffering...",