mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-05-21 14:26:35 +01:00
feat: Enhance Chromecast functionality and UI improvements
- Implemented a retry mechanism for Chromecast device discovery with a maximum of 3 attempts. - Added logging for discovered devices to aid in debugging. - Updated Chromecast button interactions to streamline navigation to the casting player. - Changed the color scheme for Chromecast components to a consistent purple theme. - Modified the ChromecastDeviceSheet to sync volume slider with prop changes. - Improved the ChromecastSettingsMenu to conditionally render audio and subtitle tracks based on availability. - Updated translations for the casting player to include new strings for better user experience.
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import React, { useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Modal, Pressable, View } from "react-native";
|
||||
import { Slider } from "react-native-awesome-slider";
|
||||
import type { Device } from "react-native-google-cast";
|
||||
@@ -19,6 +19,7 @@ interface ChromecastDeviceSheetProps {
|
||||
onDisconnect: () => Promise<void>;
|
||||
volume?: number;
|
||||
onVolumeChange?: (volume: number) => Promise<void>;
|
||||
showTechnicalInfo?: boolean;
|
||||
}
|
||||
|
||||
export const ChromecastDeviceSheet: React.FC<ChromecastDeviceSheetProps> = ({
|
||||
@@ -28,11 +29,17 @@ export const ChromecastDeviceSheet: React.FC<ChromecastDeviceSheetProps> = ({
|
||||
onDisconnect,
|
||||
volume = 0.5,
|
||||
onVolumeChange,
|
||||
showTechnicalInfo = false,
|
||||
}) => {
|
||||
const insets = useSafeAreaInsets();
|
||||
const [isDisconnecting, setIsDisconnecting] = useState(false);
|
||||
const volumeValue = useSharedValue(volume * 100);
|
||||
|
||||
// Sync volume slider with prop changes
|
||||
useEffect(() => {
|
||||
volumeValue.value = volume * 100;
|
||||
}, [volume, volumeValue]);
|
||||
|
||||
const handleDisconnect = async () => {
|
||||
setIsDisconnecting(true);
|
||||
try {
|
||||
@@ -55,9 +62,8 @@ export const ChromecastDeviceSheet: React.FC<ChromecastDeviceSheetProps> = ({
|
||||
<Modal
|
||||
visible={visible}
|
||||
animationType='slide'
|
||||
presentationStyle='pageSheet'
|
||||
presentationStyle='formSheet'
|
||||
onRequestClose={onClose}
|
||||
transparent
|
||||
>
|
||||
<Pressable
|
||||
style={{
|
||||
@@ -90,7 +96,7 @@ export const ChromecastDeviceSheet: React.FC<ChromecastDeviceSheetProps> = ({
|
||||
<View
|
||||
style={{ flexDirection: "row", alignItems: "center", gap: 12 }}
|
||||
>
|
||||
<Ionicons name='tv' size={24} color='#e50914' />
|
||||
<Ionicons name='tv' size={24} color='#a855f7' />
|
||||
<Text style={{ color: "white", fontSize: 18, fontWeight: "600" }}>
|
||||
Chromecast
|
||||
</Text>
|
||||
@@ -111,7 +117,7 @@ export const ChromecastDeviceSheet: React.FC<ChromecastDeviceSheetProps> = ({
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{device?.deviceId && (
|
||||
{device?.deviceId && showTechnicalInfo && (
|
||||
<View style={{ marginBottom: 20 }}>
|
||||
<Text style={{ color: "#999", fontSize: 12, marginBottom: 4 }}>
|
||||
Device ID
|
||||
@@ -153,8 +159,8 @@ export const ChromecastDeviceSheet: React.FC<ChromecastDeviceSheetProps> = ({
|
||||
theme={{
|
||||
disableMinTrackTintColor: "#333",
|
||||
maximumTrackTintColor: "#333",
|
||||
minimumTrackTintColor: "#e50914",
|
||||
bubbleBackgroundColor: "#e50914",
|
||||
minimumTrackTintColor: "#a855f7",
|
||||
bubbleBackgroundColor: "#a855f7",
|
||||
}}
|
||||
onValueChange={(value) => {
|
||||
volumeValue.value = value;
|
||||
@@ -171,7 +177,7 @@ export const ChromecastDeviceSheet: React.FC<ChromecastDeviceSheetProps> = ({
|
||||
onPress={handleDisconnect}
|
||||
disabled={isDisconnecting}
|
||||
style={{
|
||||
backgroundColor: "#e50914",
|
||||
backgroundColor: "#a855f7",
|
||||
padding: 16,
|
||||
borderRadius: 8,
|
||||
flexDirection: "row",
|
||||
|
||||
@@ -41,7 +41,7 @@ export const ChromecastEpisodeList: React.FC<ChromecastEpisodeListProps> = ({
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
padding: 12,
|
||||
backgroundColor: isCurrentEpisode ? "#e50914" : "transparent",
|
||||
backgroundColor: isCurrentEpisode ? "#a855f7" : "transparent",
|
||||
borderRadius: 8,
|
||||
marginBottom: 8,
|
||||
}}
|
||||
@@ -131,7 +131,7 @@ export const ChromecastEpisodeList: React.FC<ChromecastEpisodeListProps> = ({
|
||||
<Modal
|
||||
visible={visible}
|
||||
animationType='slide'
|
||||
presentationStyle='pageSheet'
|
||||
presentationStyle='formSheet'
|
||||
onRequestClose={onClose}
|
||||
>
|
||||
<View
|
||||
|
||||
@@ -95,9 +95,8 @@ export const ChromecastSettingsMenu: React.FC<ChromecastSettingsMenuProps> = ({
|
||||
<Modal
|
||||
visible={visible}
|
||||
animationType='slide'
|
||||
presentationStyle='pageSheet'
|
||||
presentationStyle='formSheet'
|
||||
onRequestClose={onClose}
|
||||
transparent
|
||||
>
|
||||
<Pressable
|
||||
style={{
|
||||
@@ -172,16 +171,17 @@ export const ChromecastSettingsMenu: React.FC<ChromecastSettingsMenuProps> = ({
|
||||
)}
|
||||
</View>
|
||||
{selectedMediaSource?.id === source.id && (
|
||||
<Ionicons name='checkmark' size={20} color='#e50914' />
|
||||
<Ionicons name='checkmark' size={20} color='#a855f7' />
|
||||
)}
|
||||
</Pressable>
|
||||
))}
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* Audio Tracks */}
|
||||
{renderSectionHeader("Audio", "musical-notes", "audio")}
|
||||
{expandedSection === "audio" && (
|
||||
{/* Audio Tracks - only show if more than one track */}
|
||||
{audioTracks.length > 1 &&
|
||||
renderSectionHeader("Audio", "musical-notes", "audio")}
|
||||
{audioTracks.length > 1 && expandedSection === "audio" && (
|
||||
<View style={{ paddingVertical: 8 }}>
|
||||
{audioTracks.map((track) => (
|
||||
<Pressable
|
||||
@@ -214,16 +214,17 @@ export const ChromecastSettingsMenu: React.FC<ChromecastSettingsMenuProps> = ({
|
||||
)}
|
||||
</View>
|
||||
{selectedAudioTrack?.index === track.index && (
|
||||
<Ionicons name='checkmark' size={20} color='#e50914' />
|
||||
<Ionicons name='checkmark' size={20} color='#a855f7' />
|
||||
)}
|
||||
</Pressable>
|
||||
))}
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* Subtitle Tracks */}
|
||||
{renderSectionHeader("Subtitles", "text", "subtitles")}
|
||||
{expandedSection === "subtitles" && (
|
||||
{/* Subtitle Tracks - only show if subtitles available */}
|
||||
{subtitleTracks.length > 0 &&
|
||||
renderSectionHeader("Subtitles", "text", "subtitles")}
|
||||
{subtitleTracks.length > 0 && expandedSection === "subtitles" && (
|
||||
<View style={{ paddingVertical: 8 }}>
|
||||
<Pressable
|
||||
onPress={() => {
|
||||
@@ -243,7 +244,7 @@ export const ChromecastSettingsMenu: React.FC<ChromecastSettingsMenuProps> = ({
|
||||
>
|
||||
<Text style={{ color: "white", fontSize: 15 }}>None</Text>
|
||||
{selectedSubtitleTrack === null && (
|
||||
<Ionicons name='checkmark' size={20} color='#e50914' />
|
||||
<Ionicons name='checkmark' size={20} color='#a855f7' />
|
||||
)}
|
||||
</Pressable>
|
||||
{subtitleTracks.map((track) => (
|
||||
@@ -278,7 +279,7 @@ export const ChromecastSettingsMenu: React.FC<ChromecastSettingsMenuProps> = ({
|
||||
)}
|
||||
</View>
|
||||
{selectedSubtitleTrack?.index === track.index && (
|
||||
<Ionicons name='checkmark' size={20} color='#e50914' />
|
||||
<Ionicons name='checkmark' size={20} color='#a855f7' />
|
||||
)}
|
||||
</Pressable>
|
||||
))}
|
||||
@@ -309,7 +310,7 @@ export const ChromecastSettingsMenu: React.FC<ChromecastSettingsMenuProps> = ({
|
||||
{speed === 1 ? "Normal" : `${speed}x`}
|
||||
</Text>
|
||||
{playbackSpeed === speed && (
|
||||
<Ionicons name='checkmark' size={20} color='#e50914' />
|
||||
<Ionicons name='checkmark' size={20} color='#a855f7' />
|
||||
)}
|
||||
</Pressable>
|
||||
))}
|
||||
@@ -343,7 +344,7 @@ export const ChromecastSettingsMenu: React.FC<ChromecastSettingsMenuProps> = ({
|
||||
width: 50,
|
||||
height: 30,
|
||||
borderRadius: 15,
|
||||
backgroundColor: showTechnicalInfo ? "#e50914" : "#333",
|
||||
backgroundColor: showTechnicalInfo ? "#a855f7" : "#333",
|
||||
justifyContent: "center",
|
||||
alignItems: showTechnicalInfo ? "flex-end" : "flex-start",
|
||||
padding: 2,
|
||||
|
||||
Reference in New Issue
Block a user