feat(casting): implement casting functionality with auto-mute and UI controls
This commit is contained in:
@@ -14,9 +14,10 @@ import {
|
||||
} from "./components";
|
||||
import type { SubtitleTrack } from "./components/video-player";
|
||||
import type { LogoPosition } from "@/lib/types";
|
||||
import { Maximize2, Minimize2, Volume1, Volume2, VolumeX } from "lucide-react";
|
||||
import { Cast, Maximize2, Minimize2, Volume1, Volume2, VolumeX } from "lucide-react";
|
||||
import { useAuthContext } from "@/context/auth-context";
|
||||
import { useChannels, useCurrentBroadcast, useEpg } from "@/hooks/use-channels";
|
||||
import { useCast } from "@/hooks/use-cast";
|
||||
import {
|
||||
useStreamUrl,
|
||||
fmtTime,
|
||||
@@ -166,6 +167,20 @@ function TvPageContent() {
|
||||
const toggleMute = useCallback(() => setIsMuted((m) => !m), []);
|
||||
const VolumeIcon = isMuted || volume === 0 ? VolumeX : volume < 0.5 ? Volume1 : Volume2;
|
||||
|
||||
const { castAvailable, isCasting, castDeviceName, requestCast, stopCasting } = useCast();
|
||||
|
||||
// Auto-mute local video while casting, restore on cast end
|
||||
const prevMutedRef = useRef(false);
|
||||
useEffect(() => {
|
||||
if (isCasting) {
|
||||
prevMutedRef.current = isMuted;
|
||||
setIsMuted(true);
|
||||
} else {
|
||||
setIsMuted(prevMutedRef.current);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isCasting]);
|
||||
|
||||
// Channel jump by number (e.g. press "1","4" → jump to ch 14 after 1.5 s)
|
||||
const [channelInput, setChannelInput] = useState("");
|
||||
const channelInputTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
@@ -654,6 +669,18 @@ function TvPageContent() {
|
||||
: <Maximize2 className="h-4 w-4" />}
|
||||
</button>
|
||||
|
||||
{castAvailable && (
|
||||
<button
|
||||
className={`pointer-events-auto rounded-md bg-black/50 p-1.5 backdrop-blur transition-colors hover:bg-black/70 hover:text-white ${
|
||||
isCasting ? "text-blue-400" : "text-zinc-400"
|
||||
}`}
|
||||
onClick={() => isCasting ? stopCasting() : streamUrl && requestCast(streamUrl)}
|
||||
title={isCasting ? `Stop casting to ${castDeviceName ?? "TV"}` : "Cast to TV"}
|
||||
>
|
||||
<Cast className="h-4 w-4" />
|
||||
</button>
|
||||
)}
|
||||
|
||||
<button
|
||||
className="pointer-events-auto rounded-md bg-black/50 px-3 py-1.5 text-xs text-zinc-400 backdrop-blur transition-colors hover:bg-black/70 hover:text-white"
|
||||
onClick={toggleSchedule}
|
||||
@@ -708,6 +735,13 @@ function TvPageContent() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Casting indicator */}
|
||||
{isCasting && castDeviceName && (
|
||||
<div className="pointer-events-none absolute left-4 top-4 z-10 rounded-md bg-black/60 px-3 py-1.5 text-xs text-blue-300 backdrop-blur">
|
||||
Casting to {castDeviceName}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Channel number input overlay */}
|
||||
{channelInput && (
|
||||
<div className="pointer-events-none absolute left-1/2 top-1/2 z-30 -translate-x-1/2 -translate-y-1/2 rounded-xl bg-black/80 px-8 py-5 text-center backdrop-blur">
|
||||
|
||||
Reference in New Issue
Block a user