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
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin'
import { ListPlugin } from '@lexical/react/LexicalListPlugin'
import { EditorState, LexicalEditor } from 'lexical'
import HorizontalRulePlugin from './Plugins/HorizontalRulePlugin'
import TwitterPlugin from './Plugins/TwitterPlugin'
import YouTubePlugin from './Plugins/YouTubePlugin'
import AutoEmbedPlugin from './Plugins/AutoEmbedPlugin'
import CollapsiblePlugin from './Plugins/CollapsiblePlugin'
import DraggableBlockPlugin from './Plugins/DraggableBlockPlugin'
import CodeHighlightPlugin from './Plugins/CodeHighlightPlugin'
Expand Down Expand Up @@ -125,9 +122,6 @@ export const BlocksEditor: FunctionComponent<BlocksEditorProps> = ({
<CodeHighlightPlugin />
<LinkPlugin />
<HashtagPlugin />
<AutoEmbedPlugin />
<TwitterPlugin />
<YouTubePlugin />
<CollapsiblePlugin />
<TabIndentationPlugin />
<RemoveBrokenTablesPlugin />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,6 @@ import type {

import { BlockWithAlignableContents } from '@lexical/react/LexicalBlockWithAlignableContents'
import { DecoratorBlockNode, SerializedDecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode'
import { useCallback, useEffect, useRef, useState } from 'react'

const WIDGET_SCRIPT_URL = '/dist/twitter-widgets.js'

type TweetComponentProps = Readonly<{
className: Readonly<{
base: string
focus: string
}>
format: ElementFormatType | null
loadingComponent?: JSX.Element | string
nodeKey: NodeKey
onError?: (error: string) => void
onLoad?: () => void
tweetID: string
}>

function convertTweetElement(domNode: HTMLDivElement): DOMConversionOutput | null {
const id = domNode.getAttribute('data-lexical-tweet-id')
Expand All @@ -46,71 +30,6 @@ function convertTweetElement(domNode: HTMLDivElement): DOMConversionOutput | nul
return null
}

let isTwitterScriptLoading = true

function TweetComponent({
className,
format,
loadingComponent,
nodeKey,
onError,
onLoad,
tweetID,
}: TweetComponentProps) {
const containerRef = useRef<HTMLDivElement | null>(null)

const previousTweetIDRef = useRef<string>('')
const [isTweetLoading, setIsTweetLoading] = useState(false)

const createTweet = useCallback(async () => {
try {
// @ts-expect-error Twitter is attached to the window.
await window.twttr.widgets.createTweet(tweetID, containerRef.current)

setIsTweetLoading(false)
isTwitterScriptLoading = false

if (onLoad) {
onLoad()
}
} catch (error) {
if (onError) {
onError(String(error))
}
}
}, [onError, onLoad, tweetID])

useEffect(() => {
if (tweetID !== previousTweetIDRef.current) {
setIsTweetLoading(true)

if (isTwitterScriptLoading) {
const script = document.createElement('script')
script.src = WIDGET_SCRIPT_URL
script.async = true
document.body?.appendChild(script)
script.onload = createTweet
if (onError) {
script.onerror = onError as OnErrorEventHandler
}
} else {
createTweet().catch(console.error)
}

if (previousTweetIDRef) {
previousTweetIDRef.current = tweetID
}
}
}, [createTweet, onError, tweetID])

return (
<BlockWithAlignableContents className={className} format={format} nodeKey={nodeKey}>
{isTweetLoading ? loadingComponent : null}
<div style={{ display: 'inline-block', width: '550px' }} ref={containerRef} />
</BlockWithAlignableContents>
)
}

export type SerializedTweetNode = Spread<
{
id: string
Expand Down Expand Up @@ -172,7 +91,7 @@ export class TweetNode extends DecoratorBlockNode {
}

override getTextContent(_includeInert?: boolean | undefined, _includeDirectionless?: false | undefined): string {
return `https://twitter.com/i/web/status/${this.__id}`
return `https://x.com/i/web/status/${this.__id}`
}

override decorate(_: LexicalEditor, config: EditorConfig): JSX.Element {
Expand All @@ -181,14 +100,13 @@ export class TweetNode extends DecoratorBlockNode {
base: embedBlockTheme.base || '',
focus: embedBlockTheme.focus || '',
}
const link = this.getTextContent()
return (
<TweetComponent
className={className}
format={this.__format}
loadingComponent="Loading..."
nodeKey={this.getKey()}
tweetID={this.__id}
/>
<BlockWithAlignableContents className={className} format={this.__format} nodeKey={this.getKey()}>
<a href={link} target="_blank" rel="noreferrer noopener">
{link}
</a>
</BlockWithAlignableContents>
)
}

Expand Down
Loading
Loading