mirror of
https://github.com/sussy-code/smov.git
synced 2024-12-21 14:47:41 +01:00
chromecast button styling
Co-authored-by: Jip Frijlink <JipFr@users.noreply.github.com> Co-authored-by: James Hawkins <jhawki2005@gmail.com> Co-authored-by: William Oldham <wegg7250@gmail.com>
This commit is contained in:
parent
0c57aa1a73
commit
d6d318006b
3 changed files with 60 additions and 9 deletions
|
@ -50,7 +50,6 @@ body[data-no-select] {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
google-cast-launcher {
|
.google-cast-button:not(.casting) google-cast-launcher {
|
||||||
@apply pointer-events-auto m-2 text-white flex items-center justify-center p-2;
|
@apply brightness-[500];
|
||||||
@apply transition-[background-color,transform] duration-100 rounded-full bg-denim-600 bg-opacity-0 hover:bg-opacity-50 active:bg-denim-500 active:bg-opacity-100 active:scale-110;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,60 @@
|
||||||
import { Icons } from "@/components/Icon";
|
import { Icons } from "@/components/Icon";
|
||||||
import { VideoPlayerIconButton } from "@/video/components/parts/VideoPlayerIconButton";
|
import { VideoPlayerIconButton } from "@/video/components/parts/VideoPlayerIconButton";
|
||||||
|
import { useVideoPlayerDescriptor } from "@/video/state/hooks";
|
||||||
|
import { useMisc } from "@/video/state/logic/misc";
|
||||||
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ChromecastAction(props: Props) {
|
export function ChromecastAction(props: Props) {
|
||||||
|
const [hidden, setHidden] = useState(false);
|
||||||
|
const descriptor = useVideoPlayerDescriptor();
|
||||||
|
const misc = useMisc(descriptor);
|
||||||
|
const isCasting = misc.isCasting;
|
||||||
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const setButtonVisibility = useCallback(
|
||||||
|
(tag: HTMLElement) => {
|
||||||
|
const isVisible = (tag.getAttribute("style") ?? "").includes("inline");
|
||||||
|
setHidden(!isVisible);
|
||||||
|
},
|
||||||
|
[setHidden]
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const tag = ref.current?.querySelector<HTMLElement>("google-cast-launcher");
|
||||||
|
if (!tag) return;
|
||||||
|
|
||||||
|
const observer = new MutationObserver(() => {
|
||||||
|
setButtonVisibility(tag);
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(tag, { attributes: true, attributeFilter: ["style"] });
|
||||||
|
setButtonVisibility(tag);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
observer.disconnect();
|
||||||
|
};
|
||||||
|
}, [setButtonVisibility]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VideoPlayerIconButton className={props.className} icon={Icons.CASTING} />
|
<VideoPlayerIconButton
|
||||||
|
ref={ref}
|
||||||
|
className={[
|
||||||
|
props.className ?? "",
|
||||||
|
"google-cast-button",
|
||||||
|
isCasting ? "casting" : "",
|
||||||
|
hidden ? "hidden" : "",
|
||||||
|
].join(" ")}
|
||||||
|
icon={Icons.CASTING}
|
||||||
|
onClick={(e) => {
|
||||||
|
const castButton = e.currentTarget.querySelector(
|
||||||
|
"google-cast-launcher"
|
||||||
|
);
|
||||||
|
if (castButton) (castButton as HTMLDivElement).click();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Icon, Icons } from "@/components/Icon";
|
import { Icon, Icons } from "@/components/Icon";
|
||||||
import React from "react";
|
import React, { forwardRef } from "react";
|
||||||
|
|
||||||
export interface VideoPlayerIconButtonProps {
|
export interface VideoPlayerIconButtonProps {
|
||||||
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
||||||
|
@ -9,11 +9,15 @@ export interface VideoPlayerIconButtonProps {
|
||||||
iconSize?: string;
|
iconSize?: string;
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
wide?: boolean;
|
wide?: boolean;
|
||||||
|
noPadding?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function VideoPlayerIconButton(props: VideoPlayerIconButtonProps) {
|
export const VideoPlayerIconButton = forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
VideoPlayerIconButtonProps
|
||||||
|
>((props, ref) => {
|
||||||
return (
|
return (
|
||||||
<div className={props.className}>
|
<div className={props.className} ref={ref}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={props.onClick}
|
onClick={props.onClick}
|
||||||
|
@ -23,7 +27,7 @@ export function VideoPlayerIconButton(props: VideoPlayerIconButtonProps) {
|
||||||
className={[
|
className={[
|
||||||
"flex items-center justify-center rounded-full bg-denim-600 bg-opacity-0 transition-colors duration-100 group-hover:bg-opacity-50 group-active:bg-denim-500 group-active:bg-opacity-100",
|
"flex items-center justify-center rounded-full bg-denim-600 bg-opacity-0 transition-colors duration-100 group-hover:bg-opacity-50 group-active:bg-denim-500 group-active:bg-opacity-100",
|
||||||
props.active ? "!bg-denim-500 !bg-opacity-100" : "",
|
props.active ? "!bg-denim-500 !bg-opacity-100" : "",
|
||||||
props.wide ? "py-2 px-4" : "p-2",
|
!props.noPadding ? (props.wide ? "py-2 px-4" : "p-2") : "",
|
||||||
].join(" ")}
|
].join(" ")}
|
||||||
>
|
>
|
||||||
<Icon icon={props.icon} className={props.iconSize ?? "text-2xl"} />
|
<Icon icon={props.icon} className={props.iconSize ?? "text-2xl"} />
|
||||||
|
@ -32,4 +36,4 @@ export function VideoPlayerIconButton(props: VideoPlayerIconButtonProps) {
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
Loading…
Reference in a new issue