replace component for quiz videos
This commit is contained in:
parent
b092abc4f7
commit
ee5d3448ab
@ -10,12 +10,10 @@ import { useVkMetricsGoals } from "@/utils/hooks/metrics/useVkMetricsGoals";
|
|||||||
import { useYandexMetricsGoals } from "@/utils/hooks/metrics/useYandexMetricsGoals";
|
import { useYandexMetricsGoals } from "@/utils/hooks/metrics/useYandexMetricsGoals";
|
||||||
import { DESIGN_LIST } from "@/utils/designList";
|
import { DESIGN_LIST } from "@/utils/designList";
|
||||||
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
||||||
|
|
||||||
import YoutubeEmbedIframe from "./tools/YoutubeEmbedIframe";
|
|
||||||
|
|
||||||
import { NameplateLogo } from "@icons/NameplateLogo";
|
import { NameplateLogo } from "@icons/NameplateLogo";
|
||||||
|
|
||||||
import type { QuizQuestionResult } from "@/model/questionTypes/result";
|
import type { QuizQuestionResult } from "@/model/questionTypes/result";
|
||||||
|
import QuizVideo from "@/ui_kit/VideoIframe/VideoIframe";
|
||||||
|
|
||||||
type ResultFormProps = {
|
type ResultFormProps = {
|
||||||
resultQuestion: QuizQuestionResult;
|
resultQuestion: QuizQuestionResult;
|
||||||
@ -117,7 +115,7 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{!resultQuestion?.content.useImage && resultQuestion.content.video && (
|
{!resultQuestion?.content.useImage && resultQuestion.content.video && (
|
||||||
<YoutubeEmbedIframe
|
<QuizVideo
|
||||||
videoUrl={resultQuestion.content.video}
|
videoUrl={resultQuestion.content.video}
|
||||||
containerSX={{
|
containerSX={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
|
@ -14,8 +14,7 @@ import { DESIGN_LIST } from "@/utils/designList";
|
|||||||
|
|
||||||
import { useVkMetricsGoals } from "@/utils/hooks/metrics/useVkMetricsGoals";
|
import { useVkMetricsGoals } from "@/utils/hooks/metrics/useVkMetricsGoals";
|
||||||
import { useYandexMetricsGoals } from "@/utils/hooks/metrics/useYandexMetricsGoals";
|
import { useYandexMetricsGoals } from "@/utils/hooks/metrics/useYandexMetricsGoals";
|
||||||
|
import QuizVideo from "@/ui_kit/VideoIframe/VideoIframe";
|
||||||
import YoutubeEmbedIframe from "../tools/YoutubeEmbedIframe";
|
|
||||||
|
|
||||||
export const StartPageViewPublication = () => {
|
export const StartPageViewPublication = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
@ -54,7 +53,7 @@ export const StartPageViewPublication = () => {
|
|||||||
/>
|
/>
|
||||||
) : settings.cfg.startpage.background.type === "video" ? (
|
) : settings.cfg.startpage.background.type === "video" ? (
|
||||||
settings.cfg.startpage.background.video ? (
|
settings.cfg.startpage.background.video ? (
|
||||||
<YoutubeEmbedIframe
|
<QuizVideo
|
||||||
videoUrl={settings.cfg.startpage.background.video}
|
videoUrl={settings.cfg.startpage.background.video}
|
||||||
containerSX={{
|
containerSX={{
|
||||||
width: settings.cfg.startpageType === "centered" ? "550px" : "100%",
|
width: settings.cfg.startpageType === "centered" ? "550px" : "100%",
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import { Box, Typography, useTheme } from "@mui/material";
|
import { Box, Typography, useTheme } from "@mui/material";
|
||||||
|
|
||||||
import YoutubeEmbedIframe from "@/components/ViewPublicationPage/tools/YoutubeEmbedIframe";
|
|
||||||
|
|
||||||
import type { QuizQuestionPage } from "@model/questionTypes/page";
|
import type { QuizQuestionPage } from "@model/questionTypes/page";
|
||||||
|
import QuizVideo from "@/ui_kit/VideoIframe/VideoIframe";
|
||||||
|
|
||||||
type PageProps = {
|
type PageProps = {
|
||||||
currentQuestion: QuizQuestionPage;
|
currentQuestion: QuizQuestionPage;
|
||||||
@ -55,7 +53,7 @@ export const Page = ({ currentQuestion }: PageProps) => {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<YoutubeEmbedIframe
|
<QuizVideo
|
||||||
containerSX={{
|
containerSX={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "calc(100% - 270px)",
|
height: "calc(100% - 270px)",
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
import { Box, SxProps } from "@mui/material";
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
videoUrl: string;
|
|
||||||
containerSX?: SxProps;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function YoutubeEmbedIframe({ videoUrl, containerSX }: Props) {
|
|
||||||
const extractYoutubeVideoId =
|
|
||||||
/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/gi;
|
|
||||||
const videoId = extractYoutubeVideoId.exec(videoUrl)?.[1];
|
|
||||||
// if (!videoId) return null;
|
|
||||||
|
|
||||||
const embedUrl = `https://www.youtube.com/embed/${videoId}?controls=0&autoplay=1&modestbranding=0&showinfo=0&disablekb=1&mute=1&loop=1`;
|
|
||||||
// https://www.youtube.com/shorts/9VgqBPd6RPA
|
|
||||||
// https://www.youtube.com/watch?v=I2N8hTHhvGY
|
|
||||||
return (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
pointerEvents: "none",
|
|
||||||
"& iframe": {
|
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
},
|
|
||||||
...containerSX,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
component="video"
|
|
||||||
sx={{
|
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
}}
|
|
||||||
autoPlay
|
|
||||||
muted
|
|
||||||
src={videoUrl}
|
|
||||||
/>
|
|
||||||
{/* <iframe
|
|
||||||
src={embedUrl}
|
|
||||||
title="YouTube video player"
|
|
||||||
frameBorder="0"
|
|
||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
|
||||||
allowFullScreen
|
|
||||||
/> */}
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,5 +1,6 @@
|
|||||||
import QuizAnswerer from "./components/QuizAnswerer";
|
import QuizAnswerer from "./components/QuizAnswerer";
|
||||||
|
import QuizVideo from "./ui_kit/VideoIframe/VideoIframe";
|
||||||
|
|
||||||
export type { QuizSettings } from "@model/settingsData";
|
export type { QuizSettings } from "@model/settingsData";
|
||||||
export type * from "./model/widget";
|
export type * from "./model/widget";
|
||||||
|
export { QuizAnswerer, QuizVideo };
|
||||||
export { QuizAnswerer };
|
|
||||||
|
43
lib/ui_kit/VideoIframe/VideoIframe.tsx
Normal file
43
lib/ui_kit/VideoIframe/VideoIframe.tsx
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { Box } from "@mui/material";
|
||||||
|
import { getVideo } from "./helper";
|
||||||
|
import type { SxProps } from "@mui/material";
|
||||||
|
import useSWR from "swr";
|
||||||
|
import LoadingSkeleton from "../LoadingSkeleton";
|
||||||
|
import { ApologyPage } from "@/components/ViewPublicationPage/ApologyPage";
|
||||||
|
|
||||||
|
type VideoIframeProps = {
|
||||||
|
videoUrl: string;
|
||||||
|
containerSX?: SxProps;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function QuizVideo({ videoUrl, containerSX }: VideoIframeProps) {
|
||||||
|
const { data: videoData, error, isLoading } = useSWR(["video", videoUrl], (params) => getVideo(params[1]));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
minHeight: videoData?.sourceName === "tiktok" ? "740px" : 0,
|
||||||
|
"& iframe": { width: "100%", height: "100%" },
|
||||||
|
...containerSX,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isLoading ? (
|
||||||
|
<LoadingSkeleton />
|
||||||
|
) : !videoData || error ? (
|
||||||
|
<ApologyPage error={error ?? new Error()} />
|
||||||
|
) : videoData.sourceName === "custom" || videoData.sourceName === "yandex" ? (
|
||||||
|
<Box component="video" sx={{ width: "100%", height: "100%" }} autoPlay controls muted src={videoData.url} />
|
||||||
|
) : (
|
||||||
|
<Box
|
||||||
|
component="iframe"
|
||||||
|
src={videoData.url}
|
||||||
|
title={videoData.sourceName}
|
||||||
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||||
|
{...{ allowFullScreen: true, frameBorder: 0 }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
165
lib/ui_kit/VideoIframe/helper.ts
Normal file
165
lib/ui_kit/VideoIframe/helper.ts
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
type SourceType = "youtube" | "short" | "vk" | "google" | "yandex" | "mail" | "tiktok" | "custom";
|
||||||
|
|
||||||
|
export type VideoUrlResult = {
|
||||||
|
sourceName: SourceType;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type TiktokResponse = {
|
||||||
|
version: string;
|
||||||
|
type: string;
|
||||||
|
title: string;
|
||||||
|
author_url: string;
|
||||||
|
author_name: string;
|
||||||
|
width: string;
|
||||||
|
height: string;
|
||||||
|
html: string;
|
||||||
|
thumbnail_width: number;
|
||||||
|
thumbnail_height: number;
|
||||||
|
thumbnail_url: string;
|
||||||
|
provider_url: string;
|
||||||
|
provider_name: string;
|
||||||
|
author_unique_id: string;
|
||||||
|
embed_product_id: string;
|
||||||
|
embed_type: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type YandexResponse = {
|
||||||
|
antivirus_status: string;
|
||||||
|
views_count: number;
|
||||||
|
resource_id: string;
|
||||||
|
file: string;
|
||||||
|
owner: {
|
||||||
|
login: string;
|
||||||
|
display_name: string;
|
||||||
|
uid: string;
|
||||||
|
};
|
||||||
|
size: number;
|
||||||
|
exif: unknown;
|
||||||
|
media_type: string;
|
||||||
|
preview: string;
|
||||||
|
type: string;
|
||||||
|
mime_type: string;
|
||||||
|
revision: number;
|
||||||
|
public_url: string;
|
||||||
|
path: string;
|
||||||
|
md5: string;
|
||||||
|
public_key: string;
|
||||||
|
sha256: string;
|
||||||
|
name: string;
|
||||||
|
created: string;
|
||||||
|
sizes: {
|
||||||
|
url: string;
|
||||||
|
name: string;
|
||||||
|
}[];
|
||||||
|
modified: string;
|
||||||
|
comment_ids: {
|
||||||
|
private_resource: string;
|
||||||
|
public_resource: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const FILTER_SITES_REGEX: Record<Exclude<SourceType, "short" | "custom">, RegExp> = {
|
||||||
|
youtube: /^(https?:\/\/)?(www\.)?((m\.youtube|youtube)\.com|youtu\.be)\/.+$/,
|
||||||
|
vk: /^(https?:\/\/)?(m.)?vk\..+$/,
|
||||||
|
tiktok: /^(https?:\/\/)?((www|vt).)?tiktok\..+$/,
|
||||||
|
google: /^(https?:\/\/)?(www.)?drive\.google\..+$/,
|
||||||
|
yandex: /^(https?:\/\/)?disk\.yandex\..+$/,
|
||||||
|
mail: /^(https?:\/\/)?cloud\.mail\..+$/,
|
||||||
|
};
|
||||||
|
|
||||||
|
const EXTRACT_VIDEO_ID_REGEX: Record<Exclude<SourceType, "custom">, RegExp> = {
|
||||||
|
youtube: /(?<=v=|v\/|d\/|be\/|embed\/)[\w-]+/,
|
||||||
|
short: /(?<=v=|v\/|d\/|be\/|embed\/)[\w-]+/,
|
||||||
|
vk: /(-?(\d+)_(\d+))/,
|
||||||
|
google: /(?<=(file\/d\/))[\w-]+/,
|
||||||
|
yandex: /(?<=i\/)[\w-]+/,
|
||||||
|
mail: /$/,
|
||||||
|
tiktok: /(?<=video\/|\.com\/)[\w-]+/,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getVideo = async (videoUrl: string): Promise<VideoUrlResult> => {
|
||||||
|
if (videoUrl.match(FILTER_SITES_REGEX.youtube)?.[0]) {
|
||||||
|
if (videoUrl.includes("youtube.com/shorts")) {
|
||||||
|
const videoId = videoUrl.match(EXTRACT_VIDEO_ID_REGEX.short)?.[0];
|
||||||
|
|
||||||
|
return {
|
||||||
|
sourceName: "short",
|
||||||
|
url: `https://www.youtube.com/embed/${videoId}?controls=0&autoplay=1&modestbranding=0&showinfo=0&disablekb=1&mute=1&loop=1`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const videoId = videoUrl.match(EXTRACT_VIDEO_ID_REGEX.youtube)?.[0];
|
||||||
|
return {
|
||||||
|
sourceName: "youtube",
|
||||||
|
url: `https://www.youtube.com/embed/${videoId}?controls=0&autoplay=1&modestbranding=0&showinfo=0&disablekb=1&mute=1&loop=1`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (videoUrl.match(FILTER_SITES_REGEX.vk)) {
|
||||||
|
const videoId = videoUrl.match(EXTRACT_VIDEO_ID_REGEX.vk)?.[0];
|
||||||
|
|
||||||
|
return {
|
||||||
|
sourceName: "vk",
|
||||||
|
url: `https://vk.com/video_ext.php?oid=${videoId?.split("_")[0]}&id=${videoId?.split("_")[1]}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (videoUrl.match(FILTER_SITES_REGEX.tiktok)) {
|
||||||
|
const videoId = videoUrl.match(EXTRACT_VIDEO_ID_REGEX.tiktok)?.[0] ?? "";
|
||||||
|
|
||||||
|
if (/[a-zA-Z]/.test(videoId)) {
|
||||||
|
try {
|
||||||
|
const { data } = await axios.get<TiktokResponse>("https://www.tiktok.com/oembed", {
|
||||||
|
params: { url: videoUrl },
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
sourceName: "tiktok",
|
||||||
|
url: `https://www.tiktok.com/embed/v2/${data.embed_product_id}?embedFrom=embed_page_preview`,
|
||||||
|
};
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
return {
|
||||||
|
sourceName: "tiktok",
|
||||||
|
url: `https://www.tiktok.com/embed/v2/${videoId}?embedFrom=embed_page_preview`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
sourceName: "tiktok",
|
||||||
|
url: `https://www.tiktok.com/embed/v2/${videoId}?embedFrom=embed_page_preview`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (videoUrl.match(FILTER_SITES_REGEX.google)) {
|
||||||
|
const videoId = videoUrl.match(EXTRACT_VIDEO_ID_REGEX.google)?.[0];
|
||||||
|
|
||||||
|
return {
|
||||||
|
sourceName: "google",
|
||||||
|
url: `https://drive.google.com/file/d/${videoId}/preview`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (videoUrl.match(FILTER_SITES_REGEX.yandex)) {
|
||||||
|
const videoId = videoUrl.match(EXTRACT_VIDEO_ID_REGEX.yandex);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { data } = await axios.get<YandexResponse>("https://cloud-api.yandex.net/v1/disk/public/resources", {
|
||||||
|
params: { public_key: `https://disk.yandex.ru/i/${videoId}` },
|
||||||
|
});
|
||||||
|
|
||||||
|
return { sourceName: "yandex", url: data.file };
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
return { sourceName: "yandex", url: "" };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (videoUrl.match(FILTER_SITES_REGEX.mail)) {
|
||||||
|
return { sourceName: "mail", url: videoUrl };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { sourceName: "custom", url: videoUrl };
|
||||||
|
};
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@frontend/squzanswerer",
|
"name": "@frontend/squzanswerer",
|
||||||
"version": "1.0.44",
|
"version": "1.0.45",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist-package/index.js",
|
"main": "./dist-package/index.js",
|
||||||
"module": "./dist-package/index.js",
|
"module": "./dist-package/index.js",
|
||||||
|
Loading…
Reference in New Issue
Block a user