'use client' import React from 'react' import { useEditor, EditorContent } from '@tiptap/react' import StarterKit from '@tiptap/starter-kit' import learnhouseIcon from 'public/learnhouse_icon.png' import { ToolbarButtons } from './Toolbar/ToolbarButtons' import { motion } from 'framer-motion' import Image from 'next/image' import styled from 'styled-components' import { DividerVerticalIcon, SlashIcon } from '@radix-ui/react-icons' import learnhouseAI_icon from 'public/learnhouse_ai_simple.png' import { AIEditorStateTypes, useAIEditor, useAIEditorDispatch, } from '@components/Contexts/AI/AIEditorContext' // Extensions import InfoCallout from './Extensions/Callout/Info/InfoCallout' import WarningCallout from './Extensions/Callout/Warning/WarningCallout' import ImageBlock from './Extensions/Image/ImageBlock' import Youtube from '@tiptap/extension-youtube' import VideoBlock from './Extensions/Video/VideoBlock' import { ComputerIcon, Eye, Monitor } from 'lucide-react' import MathEquationBlock from './Extensions/MathEquation/MathEquationBlock' import PDFBlock from './Extensions/PDF/PDFBlock' import QuizBlock from './Extensions/Quiz/QuizBlock' import Table from '@tiptap/extension-table' import TableCell from '@tiptap/extension-table-cell' import TableHeader from '@tiptap/extension-table-header' import TableRow from '@tiptap/extension-table-row' import ToolTip from '@components/StyledElements/Tooltip/Tooltip' import Link from 'next/link' import { getCourseThumbnailMediaDirectory } from '@services/media/media' // Lowlight import { common, createLowlight } from 'lowlight' const lowlight = createLowlight(common) import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight' import css from 'highlight.js/lib/languages/css' import js from 'highlight.js/lib/languages/javascript' import ts from 'highlight.js/lib/languages/typescript' import html from 'highlight.js/lib/languages/xml' import python from 'highlight.js/lib/languages/python' import java from 'highlight.js/lib/languages/java' import { CourseProvider } from '@components/Contexts/CourseContext' import { useLHSession } from '@components/Contexts/LHSessionContext' import AIEditorToolkit from './AI/AIEditorToolkit' import useGetAIFeatures from '@components/AI/Hooks/useGetAIFeatures' import Collaboration from '@tiptap/extension-collaboration' import CollaborationCursor from '@tiptap/extension-collaboration-cursor' import ActiveAvatars from './ActiveAvatars' import { getUriWithOrg } from '@services/config/config' import EmbedObjects from './Extensions/EmbedObjects/EmbedObjects' import Badges from './Extensions/Badges/Badges' import Buttons from './Extensions/Buttons/Buttons' import { useMediaQuery } from 'usehooks-ts' interface Editor { content: string activity: any course: any org: any session: any ydoc: any hocuspocusProvider: any, isCollabEnabledOnThisOrg: boolean userRandomColor: string mouseMovements: any setContent: (content: string) => void } function Editor(props: Editor) { const session = useLHSession() as any const dispatchAIEditor = useAIEditorDispatch() as any const aiEditorState = useAIEditor() as AIEditorStateTypes const is_ai_feature_enabled = useGetAIFeatures({ feature: 'editor' }) const [isButtonAvailable, setIsButtonAvailable] = React.useState(false) React.useEffect(() => { if (is_ai_feature_enabled) { setIsButtonAvailable(true) } }, [is_ai_feature_enabled]) // remove course_ from course_uuid const course_uuid = props.course.course_uuid.substring(7) // remove activity_ from activity_uuid const activity_uuid = props.activity.activity_uuid.substring(9) // Code Block Languages for Lowlight lowlight.register('html', html) lowlight.register('css', css) lowlight.register('js', js) lowlight.register('ts', ts) lowlight.register('python', python) lowlight.register('java', java) const editor: any = useEditor({ editable: true, extensions: [ StarterKit.configure({ // The Collaboration extension comes with its own history handling history: props.isCollabEnabledOnThisOrg ? false : undefined, }), InfoCallout.configure({ editable: true, }), WarningCallout.configure({ editable: true, }), ImageBlock.configure({ editable: true, activity: props.activity, }), VideoBlock.configure({ editable: true, activity: props.activity, }), MathEquationBlock.configure({ editable: true, activity: props.activity, }), PDFBlock.configure({ editable: true, activity: props.activity, }), QuizBlock.configure({ editable: true, activity: props.activity, }), Youtube.configure({ controls: true, modestBranding: true, }), CodeBlockLowlight.configure({ lowlight, }), EmbedObjects.configure({ editable: true, activity: props.activity, }), Badges.configure({ editable: true, activity: props.activity, }), Buttons.configure({ editable: true, activity: props.activity, }), Table.configure({ resizable: true, }), TableRow, TableHeader, TableCell, // Add Collaboration and CollaborationCursor only if isCollabEnabledOnThisOrg is true ...(props.isCollabEnabledOnThisOrg ? [ Collaboration.configure({ document: props.hocuspocusProvider?.document, }), CollaborationCursor.configure({ provider: props.hocuspocusProvider, user: { name: props.session.data.user.first_name + ' ' + props.session.data.user.last_name, color: props.userRandomColor, }, }), ] : []), ], // If collab is enabled the onSynced callback ensures initial content is set only once using editor.setContent(), preventing repetitive content insertion on editor syncs. content: props.isCollabEnabledOnThisOrg ? null : props.content, }) const isMobile = useMediaQuery('(max-width: 767px)') if (isMobile) { // TODO: Work on a better editor mobile experience return (
The editor is only accessible from a desktop device.
Please switch to a desktop to view.