@@ -13,11 +13,11 @@ import {
1313 createReactBlockSpec ,
1414} from '@blocknote/react' ;
1515import { TFunction } from 'i18next' ;
16- import { useEffect } from 'react' ;
16+ import { useEffect , useState } from 'react' ;
1717import { useTranslation } from 'react-i18next' ;
18- import { createGlobalStyle } from 'styled-components' ;
18+ import { createGlobalStyle , css } from 'styled-components' ;
1919
20- import { Box , Icon } from '@/components' ;
20+ import { Box , Icon , Loading } from '@/components' ;
2121
2222import { DocsBlockNoteEditor } from '../../types' ;
2323
@@ -66,6 +66,7 @@ const PdfBlockComponent = ({
6666 const pdfUrl = block . props . url ;
6767 const { i18n, t } = useTranslation ( ) ;
6868 const lang = i18n . resolvedLanguage ;
69+ const [ isPDFContent , setIsPDFContent ] = useState < boolean | null > ( null ) ;
6970
7071 useEffect ( ( ) => {
7172 if ( lang && locales [ lang as keyof typeof locales ] ) {
@@ -82,29 +83,74 @@ const PdfBlockComponent = ({
8283 }
8384 } , [ lang , t ] ) ;
8485
86+ useEffect ( ( ) => {
87+ if ( ! pdfUrl ) {
88+ setIsPDFContent ( false ) ;
89+ return ;
90+ }
91+
92+ const validatePDFContent = async ( ) => {
93+ try {
94+ const response = await fetch ( pdfUrl ) ;
95+ const contentType = response . headers . get ( 'content-type' ) ;
96+
97+ if ( response . ok && contentType ?. includes ( 'application/pdf' ) ) {
98+ setIsPDFContent ( true ) ;
99+ } else {
100+ setIsPDFContent ( false ) ;
101+ }
102+ } catch {
103+ setIsPDFContent ( false ) ;
104+ }
105+ } ;
106+
107+ void validatePDFContent ( ) ;
108+ } , [ pdfUrl ] ) ;
109+
85110 return (
86111 < Box ref = { contentRef } className = "bn-file-block-content-wrapper" >
87112 < PDFBlockStyle />
88- < ResizableFileBlockWrapper
89- buttonIcon = {
90- < Icon iconName = "upload" $size = "24px" $css = "line-height: normal;" />
91- }
92- block = { block as unknown as FileBlockBlock }
93- editor = { editor as unknown as FileBlockEditor }
94- >
113+ { isPDFContent === null && < Loading /> }
114+ { isPDFContent !== null && ! isPDFContent && (
95115 < Box
96- className = "bn-visual-media"
97- role = "presentation"
98- as = "embed"
99- $width = "100%"
100- $height = "450px"
101- type = "application/pdf"
102- src = { pdfUrl }
116+ $align = "center"
117+ $justify = "center"
118+ $color = "#666"
119+ $background = "#f5f5f5"
120+ $border = "1px solid #ddd"
121+ $height = "300px"
122+ $css = { css `
123+ text-align : center;
124+ ` }
103125 contentEditable = { false }
104- draggable = { false }
105126 onClick = { ( ) => editor . setTextCursorPosition ( block ) }
106- />
107- </ ResizableFileBlockWrapper >
127+ >
128+ { t ( 'Invalid or missing PDF file.' ) }
129+ </ Box >
130+ ) }
131+ { isPDFContent && (
132+ < ResizableFileBlockWrapper
133+ buttonIcon = {
134+ < Icon iconName = "upload" $size = "24px" $css = "line-height: normal;" />
135+ }
136+ block = { block as unknown as FileBlockBlock }
137+ editor = { editor as unknown as FileBlockEditor }
138+ >
139+ < Box
140+ as = "embed"
141+ className = "bn-visual-media"
142+ role = "presentation"
143+ $width = "100%"
144+ $height = "450px"
145+ type = "application/pdf"
146+ src = { pdfUrl }
147+ aria-label = { block . props . name || t ( 'PDF document' ) }
148+ contentEditable = { false }
149+ draggable = { false }
150+ onClick = { ( ) => editor . setTextCursorPosition ( block ) }
151+ />
152+ </ ResizableFileBlockWrapper >
153+ ) }
108154 </ Box >
109155 ) ;
110156} ;
0 commit comments