Path: blob/master/src/packages/frontend/cookie-consent/youtube.ts
14422 views
/*1* This file is part of CoCalc: Copyright © 2026 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45// Stand-alone "consent for embedded YouTube" flag. Kept separate from the6// vanilla-cookieconsent v3 banner state on purpose: accepting a YouTube7// embed must not mark the main banner as "decided", otherwise the8// force-consent overlay on sign-up / SSO launch would stop triggering for9// a visitor who only clicked a video on the landing page.10//11// The preferences modal still surfaces this consent (see translations.ts +12// init.ts) so users can review and revoke it alongside the categories;13// internally that UI just reads/writes the dedicated cookie below.1415import { useEffect, useState } from "react";1617const YT_COOKIE = "cocalc_youtube_consent";18const ONE_YEAR_S = 365 * 24 * 60 * 60;19export const YOUTUBE_CONSENT_EVENT = "cocalc:youtube-consent";2021export function hasYouTubeConsent(): boolean {22if (typeof document === "undefined") return false;23return document.cookie24.split(";")25.some((c) => c.trim() === `${YT_COOKIE}=1`);26}2728function emitChange(): void {29if (typeof window !== "undefined") {30window.dispatchEvent(new Event(YOUTUBE_CONSENT_EVENT));31}32}3334export function grantYouTubeConsent(): void {35if (typeof document === "undefined") return;36document.cookie =37`${YT_COOKIE}=1; path=/; max-age=${ONE_YEAR_S}; SameSite=Lax`;38emitChange();39}4041export function revokeYouTubeConsent(): void {42if (typeof document === "undefined") return;43document.cookie = `${YT_COOKIE}=; path=/; max-age=0; SameSite=Lax`;44emitChange();45}4647// React hook: re-renders when YouTube consent state flips. First render48// returns false to avoid a Next.js hydration mismatch (the server can't49// read document.cookie); useEffect reconciles to the real value.50export function useYouTubeConsent(): boolean {51const [granted, setGranted] = useState(false);52useEffect(() => {53const update = () => setGranted(hasYouTubeConsent());54update();55window.addEventListener(YOUTUBE_CONSENT_EVENT, update);56return () =>57window.removeEventListener(YOUTUBE_CONSENT_EVENT, update);58}, []);59return granted;60}616263