/* eslint-disable react-hooks/rules-of-hooks */ import { BaseBoxShapeUtil, HTMLContainer, TLEmbedShape, TLEmbedShapePermissions, TLOnResizeHandler, TLShapeUtilFlag, embedShapeMigrations, embedShapePermissionDefaults, embedShapeProps, toDomPrecision, useIsEditing, useValue, } from '@bigbluebutton/editor' import { useMemo } from 'react' import { getEmbedInfo, getEmbedInfoUnsafely } from '../../utils/embeds/embeds' import { resizeBox } from '../shared/resizeBox' import { getRotatedBoxShadow } from '../shared/rotated-box-shadow' const getSandboxPermissions = (permissions: TLEmbedShapePermissions) => { return Object.entries(permissions) .filter(([_perm, isEnabled]) => isEnabled) .map(([perm]) => perm) .join(' ') } /** @public */ export class EmbedShapeUtil extends BaseBoxShapeUtil { static override type = 'embed' as const static override props = embedShapeProps static override migrations = embedShapeMigrations override hideSelectionBoundsFg: TLShapeUtilFlag = (shape) => !this.canResize(shape) override canEdit: TLShapeUtilFlag = () => true override canUnmount: TLShapeUtilFlag = (shape: TLEmbedShape) => { return !!getEmbedInfo(shape.props.url)?.definition?.canUnmount } override canResize = (shape: TLEmbedShape) => { return !!getEmbedInfo(shape.props.url)?.definition?.doesResize } override canEditInReadOnly = () => true override getDefaultProps(): TLEmbedShape['props'] { return { w: 300, h: 300, url: '', } } override isAspectRatioLocked: TLShapeUtilFlag = (shape) => { const embedInfo = getEmbedInfo(shape.props.url) return embedInfo?.definition.isAspectRatioLocked ?? false } override onResize: TLOnResizeHandler = (shape, info) => { const isAspectRatioLocked = this.isAspectRatioLocked(shape) const embedInfo = getEmbedInfo(shape.props.url) let minWidth = embedInfo?.definition.minWidth ?? 200 let minHeight = embedInfo?.definition.minHeight ?? 200 if (isAspectRatioLocked) { // Enforce aspect ratio // Neither the width or height can be less than 200 const aspectRatio = shape.props.w / shape.props.h if (aspectRatio > 1) { // Landscape minWidth *= aspectRatio } else { // Portrait minHeight /= aspectRatio } } return resizeBox(shape, info, { minWidth, minHeight }) } override component(shape: TLEmbedShape) { const { w, h, url } = shape.props const isEditing = useIsEditing(shape.id) const embedInfo = useMemo(() => getEmbedInfoUnsafely(url), [url]) const isHoveringWhileEditingSameShape = useValue( 'is hovering', () => { const { editingShapeId, hoveredShapeId } = this.editor.getCurrentPageState() if (editingShapeId && hoveredShapeId !== editingShapeId) { const editingShape = this.editor.getShape(editingShapeId) if (editingShape && this.editor.isShapeOfType(editingShape, 'embed')) { return true } } return false }, [] ) const pageRotation = this.editor.getShapePageTransform(shape)!.rotation() const isInteractive = isEditing || isHoveringWhileEditingSameShape if (embedInfo?.definition.type === 'github_gist') { const idFromGistUrl = embedInfo.url.split('/').pop() if (!idFromGistUrl) throw Error('No gist id!') return ( ) } const sandbox = getSandboxPermissions({ ...embedShapePermissionDefaults, ...(embedInfo?.definition.overridePermissions ?? {}), }) return ( {embedInfo?.definition ? (