Browse Source

Add chromecasting UI

pull/519/head
mrjvs 2 years ago
parent
commit
436a75d3f2
  1. 3
      src/assets/locales/en.json
  2. 22
      src/components/player/atoms/CastingNotification.tsx
  3. 1
      src/components/player/atoms/index.ts
  4. 4
      src/components/player/base/SubtitleView.tsx
  5. 3
      src/components/player/display/base.ts
  6. 3
      src/components/player/display/chromecast.ts
  7. 3
      src/components/player/display/displayInterface.ts
  8. 5
      src/pages/parts/player/PlayerPart.tsx

3
src/assets/locales/en.json

@ -94,6 +94,9 @@
"failure": "Error occurred" "failure": "Error occurred"
} }
}, },
"casting": {
"enabled": "Casting to device..."
},
"playbackError": { "playbackError": {
"badge": "Playback error", "badge": "Playback error",
"title": "Failed to play video!", "title": "Failed to play video!",

22
src/components/player/atoms/CastingNotification.tsx

@ -0,0 +1,22 @@
import { useTranslation } from "react-i18next";
import { Icon, Icons } from "@/components/Icon";
import { usePlayerStore } from "@/stores/player/store";
export function CastingNotification() {
const { t } = useTranslation();
const isLoading = usePlayerStore((s) => s.mediaPlaying.isLoading);
const display = usePlayerStore((s) => s.display);
const isCasting = display?.getType() === "casting";
if (isLoading || !isCasting) return null;
return (
<div className="flex flex-col items-center justify-center gap-4">
<div className="rounded-full bg-opacity-10 bg-video-buttonBackground p-3 brightness-100 grayscale">
<Icon icon={Icons.CASTING} />
</div>
<p className="text-center">{t("player.casting.enabled")}</p>
</div>
);
}

1
src/components/player/atoms/index.ts

@ -15,3 +15,4 @@ export * from "./Airplay";
export * from "./VolumeChangedPopout"; export * from "./VolumeChangedPopout";
export * from "./NextEpisodeButton"; export * from "./NextEpisodeButton";
export * from "./Chromecast"; export * from "./Chromecast";
export * from "./CastingNotification";

4
src/components/player/base/SubtitleView.tsx

@ -107,8 +107,10 @@ export function SubtitleRenderer() {
export function SubtitleView(props: { controlsShown: boolean }) { export function SubtitleView(props: { controlsShown: boolean }) {
const caption = usePlayerStore((s) => s.caption.selected); const caption = usePlayerStore((s) => s.caption.selected);
const captionAsTrack = usePlayerStore((s) => s.caption.asTrack); const captionAsTrack = usePlayerStore((s) => s.caption.asTrack);
const display = usePlayerStore((s) => s.display);
const isCasting = display?.getType() === "casting";
if (captionAsTrack || !caption) return null; if (captionAsTrack || !caption || isCasting) return null;
return ( return (
<Transition <Transition

3
src/components/player/display/base.ts

@ -253,6 +253,9 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
return { return {
on, on,
off, off,
getType() {
return "web";
},
destroy: () => { destroy: () => {
destroyVideoElement(); destroyVideoElement();
fscreen.removeEventListener("fullscreenchange", fullscreenChange); fscreen.removeEventListener("fullscreenchange", fullscreenChange);

3
src/components/player/display/chromecast.ts

@ -158,6 +158,9 @@ export function makeChromecastDisplayInterface(
return { return {
on, on,
off, off,
getType() {
return "casting";
},
destroy: () => { destroy: () => {
stopListening(); stopListening();
destroyVideoElement(); destroyVideoElement();

3
src/components/player/display/displayInterface.ts

@ -46,6 +46,8 @@ export interface DisplayCaption {
url?: string; url?: string;
} }
export type DisplayType = "web" | "casting";
export interface DisplayInterface extends Listener<DisplayInterfaceEvents> { export interface DisplayInterface extends Listener<DisplayInterfaceEvents> {
play(): void; play(): void;
pause(): void; pause(): void;
@ -66,4 +68,5 @@ export interface DisplayInterface extends Listener<DisplayInterfaceEvents> {
setPlaybackRate(rate: number): void; setPlaybackRate(rate: number): void;
setMeta(meta: DisplayMeta): void; setMeta(meta: DisplayMeta): void;
setCaption(caption: DisplayCaption | null): void; setCaption(caption: DisplayCaption | null): void;
getType(): DisplayType;
} }

5
src/pages/parts/player/PlayerPart.tsx

@ -31,10 +31,15 @@ export function PlayerPart(props: PlayerPartProps) {
<Player.SubtitleView controlsShown={showTargets} /> <Player.SubtitleView controlsShown={showTargets} />
{status === playerStatus.PLAYING ? ( {status === playerStatus.PLAYING ? (
<>
<Player.CenterControls> <Player.CenterControls>
<Player.LoadingSpinner /> <Player.LoadingSpinner />
<Player.AutoPlayStart /> <Player.AutoPlayStart />
</Player.CenterControls> </Player.CenterControls>
<Player.CenterControls>
<Player.CastingNotification />
</Player.CenterControls>
</>
) : null} ) : null}
<Player.CenterMobileControls <Player.CenterMobileControls

Loading…
Cancel
Save