airplay button

Co-authored-by: Jip Frijlink <JipFr@users.noreply.github.com>
This commit is contained in:
mrjvs 2023-10-19 14:16:10 +02:00
parent acd6541ba7
commit f6bbec8907
7 changed files with 42 additions and 0 deletions

View File

@ -0,0 +1,17 @@
import { Icons } from "@/components/Icon";
import { VideoPlayerButton } from "@/components/player/internals/Button";
import { usePlayerStore } from "@/stores/player/store";
export function Airplay() {
const canAirplay = usePlayerStore((s) => s.interface.canAirplay);
const display = usePlayerStore((s) => s.display);
if (!canAirplay) return null;
return (
<VideoPlayerButton
onClick={() => display?.startAirplay()}
icon={Icons.AIRPLAY}
/>
);
}

View File

@ -10,3 +10,4 @@ export * from "./Title";
export * from "./EpisodeTitle";
export * from "./Settings";
export * from "./Episodes";
export * from "./Airplay";

View File

@ -85,6 +85,14 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
emit("fullscreen", isFullscreen);
if (!isFullscreen) emit("needstrack", false);
});
videoElement.addEventListener(
"webkitplaybacktargetavailabilitychanged",
(e: any) => {
if (e.availability === "available") {
emit("canairplay", true);
}
}
);
}
function unloadSource() {
@ -206,5 +214,11 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
}
}
},
startAirplay() {
const videoPlayer = videoElement as any;
if (videoPlayer && videoPlayer.webkitShowPlaybackTargetPicker) {
videoPlayer.webkitShowPlaybackTargetPicker();
}
},
};
}

View File

@ -13,6 +13,7 @@ export type DisplayInterfaceEvents = {
qualities: SourceQuality[];
changedquality: SourceQuality | null;
needstrack: boolean;
canairplay: boolean;
};
export interface DisplayInterface extends Listener<DisplayInterfaceEvents> {
@ -26,4 +27,5 @@ export interface DisplayInterface extends Listener<DisplayInterfaceEvents> {
setVolume(vol: number): void;
setTime(t: number): void;
destroy(): void;
startAirplay(): void;
}

View File

@ -72,6 +72,7 @@ export function PlayerPart(props: PlayerPartProps) {
</Player.LeftSideControls>
<div className="flex items-center space-x-3">
<Player.Episodes onChange={props.onMetaChange} />
<Player.Airplay />
<Player.Settings />
<Player.Fullscreen />
</div>

View File

@ -80,6 +80,11 @@ export const createDisplaySlice: MakeSlice<DisplaySlice> = (set, get) => ({
s.caption.asTrack = needsTrack;
});
});
newDisplay.on("canairplay", (canAirplay) => {
set((s) => {
s.interface.canAirplay = canAirplay;
});
});
set((s) => {
s.display = newDisplay;

View File

@ -19,6 +19,7 @@ export interface InterfaceSlice {
hasOpenOverlay: boolean;
hovering: PlayerHoverState;
lastHoveringState: PlayerHoverState;
canAirplay: boolean;
volumeChangedWithKeybind: boolean; // has the volume recently been adjusted with the up/down arrows recently?
volumeChangedWithKeybindDebounce: NodeJS.Timeout | null; // debounce for the duration of the "volume changed thingamajig"
@ -46,6 +47,7 @@ export const createInterfaceSlice: MakeSlice<InterfaceSlice> = (set, get) => ({
volumeChangedWithKeybind: false,
volumeChangedWithKeybindDebounce: null,
timeFormat: VideoPlayerTimeFormat.REGULAR,
canAirplay: false,
},
setLastVolume(state) {