mirror of
https://github.com/movie-web/movie-web.git
synced 2024-12-27 05:51:51 +01:00
airplay button
Co-authored-by: Jip Frijlink <JipFr@users.noreply.github.com>
This commit is contained in:
parent
acd6541ba7
commit
f6bbec8907
17
src/components/player/atoms/Airplay.tsx
Normal file
17
src/components/player/atoms/Airplay.tsx
Normal 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}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
@ -10,3 +10,4 @@ export * from "./Title";
|
|||||||
export * from "./EpisodeTitle";
|
export * from "./EpisodeTitle";
|
||||||
export * from "./Settings";
|
export * from "./Settings";
|
||||||
export * from "./Episodes";
|
export * from "./Episodes";
|
||||||
|
export * from "./Airplay";
|
||||||
|
@ -85,6 +85,14 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
|
|||||||
emit("fullscreen", isFullscreen);
|
emit("fullscreen", isFullscreen);
|
||||||
if (!isFullscreen) emit("needstrack", false);
|
if (!isFullscreen) emit("needstrack", false);
|
||||||
});
|
});
|
||||||
|
videoElement.addEventListener(
|
||||||
|
"webkitplaybacktargetavailabilitychanged",
|
||||||
|
(e: any) => {
|
||||||
|
if (e.availability === "available") {
|
||||||
|
emit("canairplay", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function unloadSource() {
|
function unloadSource() {
|
||||||
@ -206,5 +214,11 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
startAirplay() {
|
||||||
|
const videoPlayer = videoElement as any;
|
||||||
|
if (videoPlayer && videoPlayer.webkitShowPlaybackTargetPicker) {
|
||||||
|
videoPlayer.webkitShowPlaybackTargetPicker();
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ export type DisplayInterfaceEvents = {
|
|||||||
qualities: SourceQuality[];
|
qualities: SourceQuality[];
|
||||||
changedquality: SourceQuality | null;
|
changedquality: SourceQuality | null;
|
||||||
needstrack: boolean;
|
needstrack: boolean;
|
||||||
|
canairplay: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface DisplayInterface extends Listener<DisplayInterfaceEvents> {
|
export interface DisplayInterface extends Listener<DisplayInterfaceEvents> {
|
||||||
@ -26,4 +27,5 @@ export interface DisplayInterface extends Listener<DisplayInterfaceEvents> {
|
|||||||
setVolume(vol: number): void;
|
setVolume(vol: number): void;
|
||||||
setTime(t: number): void;
|
setTime(t: number): void;
|
||||||
destroy(): void;
|
destroy(): void;
|
||||||
|
startAirplay(): void;
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,7 @@ export function PlayerPart(props: PlayerPartProps) {
|
|||||||
</Player.LeftSideControls>
|
</Player.LeftSideControls>
|
||||||
<div className="flex items-center space-x-3">
|
<div className="flex items-center space-x-3">
|
||||||
<Player.Episodes onChange={props.onMetaChange} />
|
<Player.Episodes onChange={props.onMetaChange} />
|
||||||
|
<Player.Airplay />
|
||||||
<Player.Settings />
|
<Player.Settings />
|
||||||
<Player.Fullscreen />
|
<Player.Fullscreen />
|
||||||
</div>
|
</div>
|
||||||
|
@ -80,6 +80,11 @@ export const createDisplaySlice: MakeSlice<DisplaySlice> = (set, get) => ({
|
|||||||
s.caption.asTrack = needsTrack;
|
s.caption.asTrack = needsTrack;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
newDisplay.on("canairplay", (canAirplay) => {
|
||||||
|
set((s) => {
|
||||||
|
s.interface.canAirplay = canAirplay;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
set((s) => {
|
set((s) => {
|
||||||
s.display = newDisplay;
|
s.display = newDisplay;
|
||||||
|
@ -19,6 +19,7 @@ export interface InterfaceSlice {
|
|||||||
hasOpenOverlay: boolean;
|
hasOpenOverlay: boolean;
|
||||||
hovering: PlayerHoverState;
|
hovering: PlayerHoverState;
|
||||||
lastHoveringState: PlayerHoverState;
|
lastHoveringState: PlayerHoverState;
|
||||||
|
canAirplay: boolean;
|
||||||
|
|
||||||
volumeChangedWithKeybind: boolean; // has the volume recently been adjusted with the up/down arrows recently?
|
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"
|
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,
|
volumeChangedWithKeybind: false,
|
||||||
volumeChangedWithKeybindDebounce: null,
|
volumeChangedWithKeybindDebounce: null,
|
||||||
timeFormat: VideoPlayerTimeFormat.REGULAR,
|
timeFormat: VideoPlayerTimeFormat.REGULAR,
|
||||||
|
canAirplay: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
setLastVolume(state) {
|
setLastVolume(state) {
|
||||||
|
Loading…
Reference in New Issue
Block a user