Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/lint-check-internal-links.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npm run lint
run: npm run lint -- --max-warnings=0

typecheck:
name: TypeScript Check
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ It does the following:

## Video Tutorial

<YouTubeEmbed videoId="a737yFcglnM?si=bHoFxhrlWhMCxEQr&start=275"></YouTubeEmbed>
<YouTubeEmbed videoId="a737yFcglnM" startSeconds={275}></YouTubeEmbed>

## Summary

Expand Down
2 changes: 1 addition & 1 deletion docs/fassets/developer-guides/5-fassets-mint.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ This script demonstrates how to retrieve the FDC proof and execute minting.

## Video Tutorial

<YouTubeEmbed videoId="a737yFcglnM?si=5L0owLyQREvO09d8"></YouTubeEmbed>
<YouTubeEmbed videoId="a737yFcglnM"></YouTubeEmbed>

## Summary

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ This script demonstrates how to retrieve the FDC proof and execute minting.

## Video Tutorial

<YouTubeEmbed videoId="a737yFcglnM?si=5L0owLyQREvO09d8"></YouTubeEmbed>
<YouTubeEmbed videoId="a737yFcglnM"></YouTubeEmbed>

## Summary

Expand Down
2 changes: 1 addition & 1 deletion docs/fassets/developer-guides/7-fassets-redeem.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ If the agent is unable to pay the redemption payment in the specified time, the

## Video Tutorial

<YouTubeEmbed videoId="a737yFcglnM?si=bHoFxhrlWhMCxEQr&start=275"></YouTubeEmbed>
<YouTubeEmbed videoId="a737yFcglnM" startSeconds={275}></YouTubeEmbed>

## Summary

Expand Down
2 changes: 1 addition & 1 deletion docs/fdc/1-overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,4 @@ The **Flare Data Connector (FDC)** is a critical infrastructure component for th

## Watch the video

<YouTubeEmbed videoId="4mAT1v8gZMQ?si=w6z6Gw6siCTX3Ntg"></YouTubeEmbed>
<YouTubeEmbed videoId="4mAT1v8gZMQ"></YouTubeEmbed>
2 changes: 1 addition & 1 deletion docs/fdc/2-getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -431,4 +431,4 @@ isFinalized(uint256 _protocolId, uint256 _votingRoundId) returns (bool)

## Watch the video

<YouTubeEmbed videoId="bURtt4siWd0?si=tVnpU0SC7ISMnrA0"></YouTubeEmbed>
<YouTubeEmbed videoId="bURtt4siWd0"></YouTubeEmbed>
2 changes: 1 addition & 1 deletion docs/ftso/0-overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,4 @@ Data providers are rewarded when the block-latency feeds remains within `±0.25%

## Watch the video

<YouTubeEmbed videoId="4mAT1v8gZMQ?si=w6z6Gw6siCTX3Ntg"></YouTubeEmbed>
<YouTubeEmbed videoId="4mAT1v8gZMQ"></YouTubeEmbed>
2 changes: 1 addition & 1 deletion docs/ftso/1-getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -176,4 +176,4 @@ The floating point value of a feed can be calculated by dividing the `feedValue`

## Watch the video

<YouTubeEmbed videoId="Lgia7lbTSk0?si=-7xaJ9dth0F6N-7F"></YouTubeEmbed>
<YouTubeEmbed videoId="Lgia7lbTSk0"></YouTubeEmbed>
2 changes: 1 addition & 1 deletion docs/ftso/scaling/1-overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,4 @@ As a result, Scaling maintains robust participation across both common and niche

## Watch the video

<YouTubeEmbed videoId="4mAT1v8gZMQ?si=w6z6Gw6siCTX3Ntg"></YouTubeEmbed>
<YouTubeEmbed videoId="4mAT1v8gZMQ"></YouTubeEmbed>
2 changes: 1 addition & 1 deletion docs/network/0-overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -391,4 +391,4 @@ Additional resources: [Flare Brand Kit](https://flare.network/media/), [go-flare

## Watch the video

<YouTubeEmbed videoId="GwY_BhEpBG8?si=5jY4dq8d1Cv8YoYX"></YouTubeEmbed>
<YouTubeEmbed videoId="GwY_BhEpBG8"></YouTubeEmbed>
2 changes: 1 addition & 1 deletion docs/network/1-getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ Now you know how to deploy and call example contracts on Flare's testnet. You ca

## Watch the video

<YouTubeEmbed videoId="X4xEVD0sPzA?si=_Xk6IxtB-rIZCSGK"></YouTubeEmbed>
<YouTubeEmbed videoId="X4xEVD0sPzA"></YouTubeEmbed>

:::tip[What's next?]

Expand Down
2 changes: 1 addition & 1 deletion docs/network/7-fsp.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ like the [Flare Time Series Oracle](/ftso/overview) and the [Flare Data Connecto

## Watch the video

<YouTubeEmbed videoId="s2n5Hc0gSZs?si=UDvQfe4oZMvKtVCa"></YouTubeEmbed>
<YouTubeEmbed videoId="s2n5Hc0gSZs"></YouTubeEmbed>

## Components

Expand Down
3 changes: 2 additions & 1 deletion examples/developer-hub-javascript/autoRedeemHyperEVM.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
*/

import { ethers } from "hardhat";
import { formatUnits, zeroPadValue, AbiCoder, Contract } from "ethers";
import type { Contract } from "ethers";
import { formatUnits, zeroPadValue, AbiCoder } from "ethers";
import { Options } from "@layerzerolabs/lz-v2-utilities";
import { EndpointId } from "@layerzerolabs/lz-definitions";

Expand Down
2 changes: 1 addition & 1 deletion examples/developer-hub-javascript/bridgeToHyperEVM.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { web3 } from "hardhat";
import { formatUnits } from "ethers";
import { EndpointId } from "@layerzerolabs/lz-definitions";
import { Options } from "@layerzerolabs/lz-v2-utilities";
import {
import type {
IERC20Instance,
FAssetOFTAdapterInstance,
} from "../../typechain-types";
Expand Down
106 changes: 92 additions & 14 deletions src/components/YouTubeEmbed/index.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,122 @@
import React from "react";
import React, { useEffect, useMemo, useRef, useState } from "react";
import clsx from "clsx";
import Head from "@docusaurus/Head";
import styles from "./styles.module.css";

type LoadStrategy = "onVisible" | "eager";

interface YouTubeEmbedProps {
/** The unique YouTube Video ID (e.g., "dQw4w9WgXcQ") */
videoId: string;
title?: string;
privacyMode?: boolean;
loadStrategy?: LoadStrategy;
rootMargin?: string;
startSeconds?: number;
className?: string;
}

const clampInt = (v: number) => Math.max(0, Math.floor(v));

const YouTubeEmbed: React.FC<YouTubeEmbedProps> = ({
videoId,
title = "YouTube video player",
privacyMode = true,
loadStrategy = "eager",
rootMargin = "250px",
startSeconds,
className = "",
}) => {
if (!videoId) {
console.error("YouTubeEmbed: videoId prop is required.");
return <div className={className}>Error: Missing YouTube Video ID.</div>;
}

// Determine the base URL based on privacy mode
const containerRef = useRef<HTMLDivElement | null>(null);
const [isActivated, setIsActivated] = useState(loadStrategy === "eager");

const baseUrl = privacyMode
? "https://www.youtube-nocookie.com/embed/"
: "https://www.youtube.com/embed/";

const embedUrl = `${baseUrl}${videoId}`;
const thumbnailUrl = useMemo(
() => `https://i.ytimg.com/vi/${encodeURIComponent(videoId)}/hqdefault.jpg`,
[videoId],
);

const embedUrl = useMemo(() => {
const params = new URLSearchParams({
rel: "0",
modestbranding: "1",
playsinline: "1",
});

if (typeof startSeconds === "number" && Number.isFinite(startSeconds)) {
params.set("start", String(clampInt(startSeconds)));
}

return `${baseUrl}${encodeURIComponent(videoId)}?${params.toString()}`;
}, [baseUrl, videoId, startSeconds]);

useEffect(() => {
if (isActivated) return;
if (loadStrategy !== "onVisible") return;

const el = containerRef.current;
if (!el) return;

const obs = new IntersectionObserver(
(entries) => {
const entry = entries[0];
if (entry?.isIntersecting) {
setIsActivated(true);
obs.disconnect();
}
},
{ root: null, rootMargin, threshold: 0.01 },
);

obs.observe(el);
return () => obs.disconnect();
}, [isActivated, loadStrategy, rootMargin]);

return (
<div className={clsx(styles.container, className)}>
<iframe
className={styles.iframe}
src={embedUrl}
title={title}
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerPolicy="strict-origin-when-cross-origin"
allowFullScreen
loading="lazy"
></iframe>
<div ref={containerRef} className={clsx(styles.container, className)}>
<Head>
<link rel="preconnect" href="https://i.ytimg.com" />
<link
rel="preconnect"
href={
privacyMode
? "https://www.youtube-nocookie.com"
: "https://www.youtube.com"
}
/>
<link rel="preconnect" href="https://www.google.com" />
<link rel="preconnect" href="https://www.gstatic.com" crossOrigin="" />
</Head>

{isActivated ? (
<iframe
className={styles.iframe}
src={embedUrl}
title={title}
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerPolicy="strict-origin-when-cross-origin"
allowFullScreen
loading={loadStrategy === "eager" ? "eager" : "lazy"}
/>
) : (
<div className={styles.placeholder} aria-hidden="true">
<img
className={styles.thumbnail}
src={thumbnailUrl}
alt=""
loading="lazy"
decoding="async"
/>
<span className={styles.playButton} aria-hidden="true" />
</div>
)}
</div>
);
};
Expand Down
49 changes: 47 additions & 2 deletions src/components/YouTubeEmbed/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,58 @@
aspect-ratio: 16 / 9;
margin: 30px auto;
max-width: 784px;
border-radius: 12px;
}

.iframe {
position: absolute;
top: 0;
left: 0;
inset: 0;
width: 100%;
height: 100%;
border: 0;
}

.placeholder {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
background: transparent;
}

.thumbnail {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
}

.playButton {
position: absolute;
left: 50%;
top: 50%;
width: 72px;
height: 48px;
transform: translate(-50%, -50%);
border-radius: 12px;
background: rgba(0, 0, 0, 0.65);
}

.playButton::before {
content: "";
position: absolute;
left: 50%;
top: 50%;
transform: translate(-35%, -50%);
width: 0;
height: 0;
border-left: 18px solid rgba(255, 255, 255, 0.95);
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
}

.noScriptLink {
display: inline-block;
margin-top: 10px;
}
Loading