mirror of
https://github.com/ajnart/homarr.git
synced 2026-02-28 01:10:54 +01:00
* feat: add everyone group through seed * feat: add reserved group name check in group router actions * feat: improve user interface for everyone group * fix: reserved group alert is a server component * feat: add all users to everyone group * chore: update lockfile * fix: format issues * fix: lint issues * fix: lint format issues * test: add unit tests for everyone group * refactor: add codegen for documentation urls by sitemap * refactor: change group query to count * chore: remove migrations temporarily * chore: add migrations again * chore: add lint rule to prevent usage of raw documentation links * fix: format issues
87 lines
2.3 KiB
TypeScript
87 lines
2.3 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useRef } from "react";
|
|
import { Anchor, Center, Group, Stack, Title } from "@mantine/core";
|
|
import { IconBrandYoutube, IconDeviceCctvOff } from "@tabler/icons-react";
|
|
import combineClasses from "clsx";
|
|
import videojs from "video.js";
|
|
|
|
import { useI18n } from "@homarr/translation/client";
|
|
|
|
import type { WidgetComponentProps } from "../definition";
|
|
import classes from "./component.module.css";
|
|
|
|
import "video.js/dist/video-js.css";
|
|
|
|
import { createDocumentationLink } from "@homarr/definitions";
|
|
|
|
export default function VideoWidget({ options }: WidgetComponentProps<"video">) {
|
|
if (options.feedUrl.trim() === "") {
|
|
return <NoUrl />;
|
|
}
|
|
|
|
if (options.feedUrl.trim().startsWith("https://www.youtube.com/watch")) {
|
|
return <ForYoutubeUseIframe />;
|
|
}
|
|
|
|
return <Feed options={options} />;
|
|
}
|
|
|
|
const NoUrl = () => {
|
|
const t = useI18n();
|
|
|
|
return (
|
|
<Center h="100%">
|
|
<Stack align="center">
|
|
<IconDeviceCctvOff />
|
|
<Title order={4}>{t("widget.video.error.noUrl")}</Title>
|
|
</Stack>
|
|
</Center>
|
|
);
|
|
};
|
|
|
|
const ForYoutubeUseIframe = () => {
|
|
const t = useI18n();
|
|
|
|
return (
|
|
<Center h="100%">
|
|
<Stack align="center" gap="xs">
|
|
<IconBrandYoutube />
|
|
<Title order={4}>{t("widget.video.error.forYoutubeUseIframe")}</Title>
|
|
<Anchor href={createDocumentationLink("/docs/widgets/iframe")}>{t("common.action.checkoutDocs")}</Anchor>
|
|
</Stack>
|
|
</Center>
|
|
);
|
|
};
|
|
|
|
const Feed = ({ options }: Pick<WidgetComponentProps<"video">, "options">) => {
|
|
const videoRef = useRef<HTMLVideoElement>(null);
|
|
|
|
useEffect(() => {
|
|
if (!videoRef.current) {
|
|
return;
|
|
}
|
|
|
|
// Initialize Video.js player if it's not already initialized
|
|
if (!("player" in videoRef.current)) {
|
|
videojs(
|
|
videoRef.current,
|
|
{
|
|
autoplay: options.hasAutoPlay,
|
|
muted: options.isMuted,
|
|
controls: options.hasControls,
|
|
},
|
|
() => undefined,
|
|
);
|
|
}
|
|
}, [options.hasAutoPlay, options.hasControls, options.isMuted, videoRef]);
|
|
|
|
return (
|
|
<Group justify="center" w="100%" h="100%" pos="relative">
|
|
<video className={combineClasses("video-js", classes.video)} ref={videoRef}>
|
|
<source src={options.feedUrl} />
|
|
</video>
|
|
</Group>
|
|
);
|
|
};
|