Commit 934d6b2b by yakoff94

fix resizer

parent 70b17b67
...@@ -22,6 +22,7 @@ import TextStyle from '@tiptap/extension-text-style' ...@@ -22,6 +22,7 @@ import TextStyle from '@tiptap/extension-text-style'
import Superscript from '@tiptap/extension-superscript' import Superscript from '@tiptap/extension-superscript'
import Subscript from '@tiptap/extension-subscript' import Subscript from '@tiptap/extension-subscript'
// import ImageResize from 'tiptap-imagresize'
import ToolBar from './components/ToolBar' import ToolBar from './components/ToolBar'
import EditorModal from './components/EditorModal' import EditorModal from './components/EditorModal'
import Uploader from './components/Uploader' import Uploader from './components/Uploader'
...@@ -38,6 +39,7 @@ import IframeModal from './modals/IframeModal' ...@@ -38,6 +39,7 @@ import IframeModal from './modals/IframeModal'
import IframeCustomModal from './modals/IframeCustomModal' import IframeCustomModal from './modals/IframeCustomModal'
import { isMobile } from 'react-device-detect' import { isMobile } from 'react-device-detect'
import Resizable from './extensions/Resizing' import Resizable from './extensions/Resizing'
import Resizing from "./extensions/Resizing";
const initialBubbleItems = [ const initialBubbleItems = [
'bold', 'bold',
...@@ -55,8 +57,8 @@ const QEditor = ({ ...@@ -55,8 +57,8 @@ const QEditor = ({
value, value,
onChange = () => {}, onChange = () => {},
style, style,
uploadOptions = { url: '', errorMessage: '' }, uploadOptions = {url: '', errorMessage: ''},
toolsOptions = { type: 'all' } toolsOptions = {type: 'all'}
}) => { }) => {
global.uploadUrl = uploadOptions.url global.uploadUrl = uploadOptions.url
...@@ -71,7 +73,7 @@ const QEditor = ({ ...@@ -71,7 +73,7 @@ const QEditor = ({
const [focusFromTo, setFocusFromTo] = useState(null) const [focusFromTo, setFocusFromTo] = useState(null)
const [oldFocusFromTo, setOldFocusFromTo] = useState(null) const [oldFocusFromTo, setOldFocusFromTo] = useState(null)
const [isUploading, setIsUploading] = useState(false) const [isUploading, setIsUploading] = useState(false)
const [recordType, setRecordType] = useState({ video: true }) const [recordType, setRecordType] = useState({video: true})
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
const getRgb = (hex) => { const getRgb = (hex) => {
...@@ -167,12 +169,7 @@ const QEditor = ({ ...@@ -167,12 +169,7 @@ const QEditor = ({
} }
// update link // update link
editor editor.chain().focus().extendMarkRange('link').setLink({href: url, target: '_blank'}).run()
.chain()
.focus()
.extendMarkRange('link')
.setLink({ href: url, target: '_blank' })
.run()
} }
}, },
file: { file: {
...@@ -209,15 +206,15 @@ const QEditor = ({ ...@@ -209,15 +206,15 @@ const QEditor = ({
}, },
h2: { h2: {
title: 'Заголовок 2', title: 'Заголовок 2',
onClick: () => editor.chain().focus().toggleHeading({ level: 2 }).run() onClick: () => editor.chain().focus().toggleHeading({level: 2}).run()
}, },
h3: { h3: {
title: 'Заголовок 3', title: 'Заголовок 3',
onClick: () => editor.chain().focus().toggleHeading({ level: 3 }).run() onClick: () => editor.chain().focus().toggleHeading({level: 3}).run()
}, },
h4: { h4: {
title: 'Заголовок 4', title: 'Заголовок 4',
onClick: () => editor.chain().focus().toggleHeading({ level: 4 }).run() onClick: () => editor.chain().focus().toggleHeading({level: 4}).run()
}, },
paragraph: { paragraph: {
title: 'Обычный', title: 'Обычный',
...@@ -293,8 +290,8 @@ const QEditor = ({ ...@@ -293,8 +290,8 @@ const QEditor = ({
alignCenter: { alignCenter: {
title: 'По центру', title: 'По центру',
onClick: () => { onClick: () => {
editor.commands.setTextAlign('center') editor.commands.setTextAlign('center');
editor.chain().focus() editor.chain().focus();
} }
}, },
alignRight: { alignRight: {
...@@ -307,7 +304,7 @@ const QEditor = ({ ...@@ -307,7 +304,7 @@ const QEditor = ({
insertTable: { insertTable: {
title: 'Вставить таблицу', title: 'Вставить таблицу',
onClick: () => onClick: () =>
editor.chain().focus().insertTable({ rows: 2, cols: 2 }).run() editor.chain().focus().insertTable({rows: 2, cols: 2}).run()
}, },
deleteTable: { deleteTable: {
title: 'Удалить таблицу', title: 'Удалить таблицу',
...@@ -359,7 +356,7 @@ const QEditor = ({ ...@@ -359,7 +356,7 @@ const QEditor = ({
voicemessage: { voicemessage: {
title: 'Записать голосовое сообщение', title: 'Записать голосовое сообщение',
onClick: () => { onClick: () => {
setRecordType({ audio: true }) setRecordType({audio: true})
clearBlobUrl() clearBlobUrl()
modalOpener('voicemessage', 'Записать голосовое сообщение') modalOpener('voicemessage', 'Записать голосовое сообщение')
} }
...@@ -367,7 +364,7 @@ const QEditor = ({ ...@@ -367,7 +364,7 @@ const QEditor = ({
webcamera: { webcamera: {
title: 'Записать с камеры', title: 'Записать с камеры',
onClick: () => { onClick: () => {
setRecordType({ video: true }) setRecordType({video: true})
clearBlobUrl() clearBlobUrl()
modalOpener('webcamera', 'Записать с камеры') modalOpener('webcamera', 'Записать с камеры')
} }
...@@ -376,9 +373,9 @@ const QEditor = ({ ...@@ -376,9 +373,9 @@ const QEditor = ({
title: 'Записать экран', title: 'Записать экран',
onClick: () => { onClick: () => {
if (isMobile) { if (isMobile) {
setRecordType({ video: true }) setRecordType({video: true})
} else { } else {
setRecordType({ screen: true }) setRecordType({screen: true})
} }
clearBlobUrl() clearBlobUrl()
modalOpener('screencust', 'Записать экран') modalOpener('screencust', 'Записать экран')
...@@ -402,6 +399,7 @@ const QEditor = ({ ...@@ -402,6 +399,7 @@ const QEditor = ({
Image.configure({ Image.configure({
inline: true inline: true
}), }),
// ImageResize.configure({resizeIcon: <>ResizeMe</>,
Resizable.configure({ Resizable.configure({
types: ["image"], // resizable type types: ["image"], // resizable type
handlerStyle: { // handler point style handlerStyle: { // handler point style
...@@ -456,8 +454,8 @@ const QEditor = ({ ...@@ -456,8 +454,8 @@ const QEditor = ({
Subscript Subscript
], ],
content: value, content: value,
onUpdate: ({ editor }) => onChange(editor.getHTML()), onUpdate: ({editor}) => onChange(editor.getHTML()),
onFocus: ({ editor }) => { onFocus: ({editor}) => {
const wrap = editor.options.element.closest('.atma-editor-wrap') const wrap = editor.options.element.closest('.atma-editor-wrap')
wrap.querySelectorAll('.atma-editor-toolbar-s').forEach(function (s) { wrap.querySelectorAll('.atma-editor-toolbar-s').forEach(function (s) {
...@@ -488,7 +486,7 @@ const QEditor = ({ ...@@ -488,7 +486,7 @@ const QEditor = ({
) )
} }
const getUploader = ({ accept = '*', ...o }) => { const getUploader = ({accept = '*', ...o}) => {
let url = uploadOptions.url let url = uploadOptions.url
let multiple = true let multiple = true
if (o.afterParams && o.afterParams.length > 0) { if (o.afterParams && o.afterParams.length > 0) {
...@@ -544,12 +542,10 @@ const QEditor = ({ ...@@ -544,12 +542,10 @@ const QEditor = ({
) )
data.append('file', file) data.append('file', file)
const headers = { 'Content-Type': 'multipart/form-data' } const headers = {'Content-Type': 'multipart/form-data'}
return new Promise(function (resolve) { return new Promise(function (resolve) {
axios axios.post(uploadOptions.url, data, {headers: headers}).then((response) => {
.post(uploadOptions.url, data, { headers: headers })
.then((response) => {
if (response.data.state === 'success') { if (response.data.state === 'success') {
resolve(response.data) resolve(response.data)
} }
...@@ -587,7 +583,7 @@ const QEditor = ({ ...@@ -587,7 +583,7 @@ const QEditor = ({
) )
case 'audio': case 'audio':
return ( return (
<Fragment>{getUploader({ accept: '.wav, .mp3, .ogg' })}</Fragment> <Fragment>{getUploader({accept: '.wav, .mp3, .ogg'})}</Fragment>
) )
case 'iframe_pdf': case 'iframe_pdf':
return ( return (
...@@ -599,13 +595,13 @@ const QEditor = ({ ...@@ -599,13 +595,13 @@ const QEditor = ({
</Fragment> </Fragment>
) )
case 'video': case 'video':
return <Fragment>{getUploader({ accept: 'video/*' })}</Fragment> return <Fragment>{getUploader({accept: 'video/*'})}</Fragment>
case 'image': case 'image':
return <Fragment>{getUploader({ accept: 'image/*' })}</Fragment> return <Fragment>{getUploader({accept: 'image/*'})}</Fragment>
case 'file': case 'file':
return ( return (
<Fragment> <Fragment>
{getUploader({ accept: '*', afterParams: ['no_convert=1'] })} {getUploader({accept: '*', afterParams: ['no_convert=1']})}
</Fragment> </Fragment>
) )
case 'voicemessage': case 'voicemessage':
...@@ -614,16 +610,16 @@ const QEditor = ({ ...@@ -614,16 +610,16 @@ const QEditor = ({
{isMobile && ( {isMobile && (
<div className='webwrap'> <div className='webwrap'>
<div> <div>
Аудиозапись с мобильного устройства недоступна, <br />{' '} Аудиозапись с мобильного устройства недоступна, <br/>{' '}
запишите стандартными функциями устройства и воспользуйтесь запишите стандартными функциями устройства и воспользуйтесь
кнопкой «Прикрепить файл» кнопкой «Прикрепить файл»
</div> </div>
</div> </div>
)} )}
{!isMobile && ( { ! isMobile && (
<div className='audio-player'> <div className='audio-player'>
<div className='audio-player-start audio-player-margin'> <div className='audio-player-start audio-player-margin'>
{status === 'recording' && !mediaBlobUrl ? ( {status === 'recording' && ! mediaBlobUrl ? (
<div <div
onClick={stopRecording} onClick={stopRecording}
className='audio-player-center-recording' className='audio-player-center-recording'
...@@ -635,13 +631,13 @@ const QEditor = ({ ...@@ -635,13 +631,13 @@ const QEditor = ({
/> />
)} )}
</div> </div>
<div className='audio-player-voice audio-player-margin' /> <div className='audio-player-voice audio-player-margin'/>
{status === 'recording' && !mediaBlobUrl ? ( {status === 'recording' && ! mediaBlobUrl ? (
<ReactStopwatch <ReactStopwatch
seconds={0} seconds={0}
minutes={0} minutes={0}
hours={0} hours={0}
render={({ formatted }) => { render={({formatted}) => {
return ( return (
<span className='audio-player-timer audio-player-margin'> <span className='audio-player-timer audio-player-margin'>
{formatted} {formatted}
...@@ -650,7 +646,7 @@ const QEditor = ({ ...@@ -650,7 +646,7 @@ const QEditor = ({
}} }}
/> />
) : ( ) : (
<span className='audio-player-timer audio-player-margin' /> <span className='audio-player-timer audio-player-margin'/>
)} )}
</div> </div>
)} )}
...@@ -663,13 +659,13 @@ const QEditor = ({ ...@@ -663,13 +659,13 @@ const QEditor = ({
{isMobile && ( {isMobile && (
<div className='webwrap'> <div className='webwrap'>
<div> <div>
Запись экрана с мобильного устройства недоступна, <br /> Запись экрана с мобильного устройства недоступна, <br/>
запишите стандартными функциями устройства и воспользуйтесь запишите стандартными функциями устройства и воспользуйтесь
кнопкой «Загрузить видео» кнопкой «Загрузить видео»
</div> </div>
</div> </div>
)} )}
{!isMobile && ( { ! isMobile && (
<> <>
<div className='webwrap'> <div className='webwrap'>
<div className='webwrap-content'> <div className='webwrap-content'>
...@@ -691,12 +687,12 @@ const QEditor = ({ ...@@ -691,12 +687,12 @@ const QEditor = ({
/> />
) )
)} )}
{status === 'recording' && !mediaBlobUrl ? ( {status === 'recording' && ! mediaBlobUrl ? (
<ReactStopwatch <ReactStopwatch
seconds={0} seconds={0}
minutes={0} minutes={0}
hours={0} hours={0}
render={({ formatted }) => { render={({formatted}) => {
return ( return (
<span className='webwrap-timer'>{formatted}</span> <span className='webwrap-timer'>{formatted}</span>
) )
...@@ -705,7 +701,7 @@ const QEditor = ({ ...@@ -705,7 +701,7 @@ const QEditor = ({
) : ( ) : (
<span className='webwrap-timer'>00:00:00</span> <span className='webwrap-timer'>00:00:00</span>
)} )}
{!mediaBlobUrl && ( { ! mediaBlobUrl && (
<div className='webwrap-start-border'> <div className='webwrap-start-border'>
<button <button
onClick={ onClick={
...@@ -726,14 +722,14 @@ const QEditor = ({ ...@@ -726,14 +722,14 @@ const QEditor = ({
<div className='web-bottom-elements'> <div className='web-bottom-elements'>
{mediaBlobUrl && ( {mediaBlobUrl && (
<div onClick={clearBlobUrl} className='web-button-wrap'> <div onClick={clearBlobUrl} className='web-button-wrap'>
<div className='web-button-rerecord' /> <div className='web-button-rerecord'/>
<span className='web-button-rerecord-text'> <span className='web-button-rerecord-text'>
Перезаписать Перезаписать
</span> </span>
</div> </div>
)} )}
{!mediaBlobUrl && <div className='web-button-spacer' />} { ! mediaBlobUrl && <div className='web-button-spacer'/>}
{!mediaBlobUrl && ( { ! mediaBlobUrl && (
<div <div
onClick={isAudioMuted ? unMuteAudio : muteAudio} onClick={isAudioMuted ? unMuteAudio : muteAudio}
className={ className={
...@@ -741,7 +737,7 @@ const QEditor = ({ ...@@ -741,7 +737,7 @@ const QEditor = ({
} }
/> />
)} )}
<div className='web-button-spacer' /> <div className='web-button-spacer'/>
</div> </div>
</> </>
)} )}
...@@ -755,13 +751,13 @@ const QEditor = ({ ...@@ -755,13 +751,13 @@ const QEditor = ({
{isMobile && ( {isMobile && (
<div className='webwrap'> <div className='webwrap'>
<div> <div>
Видеозапись с мобильного устройства недоступна, <br /> Видеозапись с мобильного устройства недоступна, <br/>
запишите стандартными функциями устройства и воспользуйтесь запишите стандартными функциями устройства и воспользуйтесь
кнопкой «Загрузить видео» кнопкой «Загрузить видео»
</div> </div>
</div> </div>
)} )}
{!isMobile && ( { ! isMobile && (
<> <>
<div className='webwrap'> <div className='webwrap'>
<div className='webwrap-content'> <div className='webwrap-content'>
...@@ -783,12 +779,12 @@ const QEditor = ({ ...@@ -783,12 +779,12 @@ const QEditor = ({
/> />
) )
)} )}
{status === 'recording' && !mediaBlobUrl ? ( {status === 'recording' && ! mediaBlobUrl ? (
<ReactStopwatch <ReactStopwatch
seconds={0} seconds={0}
minutes={0} minutes={0}
hours={0} hours={0}
render={({ formatted }) => { render={({formatted}) => {
return ( return (
<span className='webwrap-timer'>{formatted}</span> <span className='webwrap-timer'>{formatted}</span>
) )
...@@ -797,7 +793,7 @@ const QEditor = ({ ...@@ -797,7 +793,7 @@ const QEditor = ({
) : ( ) : (
<span className='webwrap-timer'>00:00:00</span> <span className='webwrap-timer'>00:00:00</span>
)} )}
{!mediaBlobUrl && ( { ! mediaBlobUrl && (
<div className='webwrap-start-border'> <div className='webwrap-start-border'>
<button <button
onClick={ onClick={
...@@ -818,14 +814,14 @@ const QEditor = ({ ...@@ -818,14 +814,14 @@ const QEditor = ({
<div className='web-bottom-elements'> <div className='web-bottom-elements'>
{mediaBlobUrl && ( {mediaBlobUrl && (
<div onClick={clearBlobUrl} className='web-button-wrap'> <div onClick={clearBlobUrl} className='web-button-wrap'>
<div className='web-button-rerecord' /> <div className='web-button-rerecord'/>
<span className='web-button-rerecord-text'> <span className='web-button-rerecord-text'>
Перезаписать Перезаписать
</span> </span>
</div> </div>
)} )}
{!mediaBlobUrl && <div className='web-button-spacer' />} { ! mediaBlobUrl && <div className='web-button-spacer'/>}
{!mediaBlobUrl && ( { ! mediaBlobUrl && (
<div <div
onClick={isAudioMuted ? unMuteAudio : muteAudio} onClick={isAudioMuted ? unMuteAudio : muteAudio}
className={ className={
...@@ -833,7 +829,7 @@ const QEditor = ({ ...@@ -833,7 +829,7 @@ const QEditor = ({
} }
/> />
)} )}
<div className='web-button-spacer' /> <div className='web-button-spacer'/>
</div> </div>
</> </>
)} )}
...@@ -856,17 +852,17 @@ const QEditor = ({ ...@@ -856,17 +852,17 @@ const QEditor = ({
} }
break break
case 'screencust': case 'screencust':
if (status === 'recording' || isUploading || !mediaBlobUrl) { if (status === 'recording' || isUploading || ! mediaBlobUrl) {
isDisabled = true isDisabled = true
} }
break break
case 'voicemessage': case 'voicemessage':
if (status === 'recording' || isUploading || !mediaBlobUrl) { if (status === 'recording' || isUploading || ! mediaBlobUrl) {
isDisabled = true isDisabled = true
} }
break break
case 'webcamera': case 'webcamera':
if (status === 'recording' || isUploading || !mediaBlobUrl) { if (status === 'recording' || isUploading || ! mediaBlobUrl) {
isDisabled = true isDisabled = true
} }
break break
...@@ -895,14 +891,14 @@ const QEditor = ({ ...@@ -895,14 +891,14 @@ const QEditor = ({
const regex = new RegExp( const regex = new RegExp(
'(?:<iframe[^>]*)(?:(?:\\/>)|(?:>.*?<\\/iframe>))' '(?:<iframe[^>]*)(?:(?:\\/>)|(?:>.*?<\\/iframe>))'
) )
isDisabled = !regex.test(embedContent) isDisabled = ! regex.test(embedContent)
break break
} }
return isDisabled return isDisabled
} }
if (!editor) { if ( ! editor) {
return null return null
} }
...@@ -960,12 +956,11 @@ const QEditor = ({ ...@@ -960,12 +956,11 @@ const QEditor = ({
return false return false
} else { } else {
if ( if (
document.querySelectorAll('.atma-editor-uploader-progress') document.querySelectorAll('.atma-editor-uploader-progress').length > 0
.length > 0
) { ) {
if ( if (
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
!confirm( ! confirm(
'Не полностью загруженные файлы будут утеряны. Вы уверены, что хотите продолжить?' 'Не полностью загруженные файлы будут утеряны. Вы уверены, что хотите продолжить?'
) )
) { ) {
...@@ -976,31 +971,23 @@ const QEditor = ({ ...@@ -976,31 +971,23 @@ const QEditor = ({
switch (innerModalType) { switch (innerModalType) {
case 'image': case 'image':
uploadedPaths.map((file, i) => { uploadedPaths.map((file, i) => {
editor.chain().focus().setImage({ src: file.path }).run(); editor.chain().focus().setImage({src: file.path}).run();
}) })
break break
case 'video': case 'video':
uploadedPaths.map((file, i) => { uploadedPaths.map((file, i) => {
editor editor.chain().focus().setVideo({
.chain()
.focus()
.setVideo({
src: file.path, src: file.path,
poster: file.path + '.jpg' poster: file.path + '.jpg'
}) }).run()
.run()
}) })
break break
case 'voicemessage': case 'voicemessage':
if (mediaBlobUrl && uploadedPaths.length === 0) { if (mediaBlobUrl && uploadedPaths.length === 0) {
if (!isUploading) { if ( ! isUploading) {
await saveScreenCust(mediaBlobUrl).then((data) => { await saveScreenCust(mediaBlobUrl).then((data) => {
if (data?.file_path) { if (data?.file_path) {
editor editor.chain().focus().addVoiceMessage({src: data.file_path}).run()
.chain()
.focus()
.addVoiceMessage({ src: data.file_path })
.run()
} }
}) })
} }
...@@ -1008,14 +995,10 @@ const QEditor = ({ ...@@ -1008,14 +995,10 @@ const QEditor = ({
break break
case 'screencust': case 'screencust':
if (mediaBlobUrl && uploadedPaths.length === 0) { if (mediaBlobUrl && uploadedPaths.length === 0) {
if (!isUploading) { if ( ! isUploading) {
await saveScreenCust(mediaBlobUrl).then((data) => { await saveScreenCust(mediaBlobUrl).then((data) => {
if (data?.file_path) { if (data?.file_path) {
editor editor.chain().focus().setVideo({src: data.file_path}).run()
.chain()
.focus()
.setVideo({ src: data.file_path })
.run()
} }
}) })
} }
...@@ -1023,14 +1006,10 @@ const QEditor = ({ ...@@ -1023,14 +1006,10 @@ const QEditor = ({
break break
case 'webcamera': case 'webcamera':
if (mediaBlobUrl && uploadedPaths.length === 0) { if (mediaBlobUrl && uploadedPaths.length === 0) {
if (!isUploading) { if ( ! isUploading) {
await saveScreenCust(mediaBlobUrl).then((data) => { await saveScreenCust(mediaBlobUrl).then((data) => {
if (data?.file_path) { if (data?.file_path) {
editor editor.chain().focus().setVideo({src: data.file_path}).run()
.chain()
.focus()
.setVideo({ src: data.file_path })
.run()
} }
}) })
} }
...@@ -1043,10 +1022,7 @@ const QEditor = ({ ...@@ -1043,10 +1022,7 @@ const QEditor = ({
const url = new URL( const url = new URL(
reg.test(_url) ? _url : 'https:' + _url reg.test(_url) ? _url : 'https:' + _url
) )
let urlId = url.pathname let urlId = url.pathname.replace(/\/$/gi, '').split('/').pop()
.replace(/\/$/gi, '')
.split('/')
.pop()
switch (url.hostname) { switch (url.hostname) {
case 'rutube.ru': case 'rutube.ru':
...@@ -1074,57 +1050,41 @@ const QEditor = ({ ...@@ -1074,57 +1050,41 @@ const QEditor = ({
_url = `https://www.youtube.com/embed/${urlId}` _url = `https://www.youtube.com/embed/${urlId}`
break break
} }
editor.chain().focus().setIframe({ src: _url }).run() editor.chain().focus().setIframe({src: _url}).run()
break break
case 'iframe_custom': case 'iframe_custom':
editor.chain().focus().insertContent(embedContent).run() editor.chain().focus().insertContent(embedContent).run()
break break
case 'iframe_pptx': case 'iframe_pptx':
uploadedPaths.map((file, i) => { uploadedPaths.map((file, i) => {
editor editor.chain().focus().insertContent(
.chain()
.focus()
.insertContent(
`<iframe src="https://view.officeapps.live.com/op/embed.aspx?src=${file.path}" width="100%" height="600px" frameBorder="0"></iframe>` `<iframe src="https://view.officeapps.live.com/op/embed.aspx?src=${file.path}" width="100%" height="600px" frameBorder="0"></iframe>`
) ).run()
.run()
}) })
break break
case 'audio': case 'audio':
uploadedPaths.map((file) => { uploadedPaths.map((file) => {
editor editor.chain().focus().insertContent(
.chain()
.focus()
.insertContent(
`<audio class="audio-player" controls="true" src="${file.path}" />` `<audio class="audio-player" controls="true" src="${file.path}" />`
) ).run()
.run()
}) })
break break
case 'iframe_pdf': case 'iframe_pdf':
uploadedPaths.map((file, i) => { uploadedPaths.map((file, i) => {
editor editor.chain().focus().insertContent(
.chain()
.focus()
.insertContent(
`<iframe src="https://docs.google.com/viewer?embedded=true&url=${file.path}" width="100%" height="800px" frameBorder="0"></iframe>` `<iframe src="https://docs.google.com/viewer?embedded=true&url=${file.path}" width="100%" height="800px" frameBorder="0"></iframe>`
) ).run()
.run()
}) })
break break
case 'file': case 'file':
uploadedPaths.map((file, i) => { uploadedPaths.map((file, i) => {
let exp = file.path.split('.') let exp = file.path.split('.')
exp = exp[exp.length - 1] exp = exp[exp.length - 1]
editor editor.chain().focus().insertContent(
.chain()
.focus()
.insertContent(
` `
<a href="${file.path}" target="_blank" download="${file.name}.${exp}" data-size="${file.size}">${file.name}</a> <a href="${file.path}" target="_blank" download="${file.name}.${exp}" data-size="${file.size}">${file.name}</a>
` `
) ).run()
.run()
}) })
break break
} }
...@@ -1152,11 +1112,11 @@ const QEditor = ({ ...@@ -1152,11 +1112,11 @@ const QEditor = ({
return ( return (
<div className='atma-editor-wrap' style={style}> <div className='atma-editor-wrap' style={style}>
<div className='atma-editor'> <div className='atma-editor'>
<ToolBar editor={editor} {...{ toolsOptions }} {...{ toolsLib }} /> <ToolBar editor={editor} {...{toolsOptions}} {...{toolsLib}} />
<BubbleMenu <BubbleMenu
typpyOptions={{ followCursor: true }} typpyOptions={{followCursor: true}}
editor={editor} editor={editor}
shouldShow={({ ...o }) => { shouldShow={({...o}) => {
let items = [] let items = []
if ( if (
o.from !== o.to && o.from !== o.to &&
...@@ -1177,7 +1137,7 @@ const QEditor = ({ ...@@ -1177,7 +1137,7 @@ const QEditor = ({
return true return true
} }
}} }}
tippyOptions={{ duration: 100 }} tippyOptions={{duration: 100}}
> >
<div <div
className='atma-editor-bubble' className='atma-editor-bubble'
...@@ -1191,36 +1151,16 @@ const QEditor = ({ ...@@ -1191,36 +1151,16 @@ const QEditor = ({
className={ className={
'qcolors' + (itemColor === 'none' ? ' unset' : '') 'qcolors' + (itemColor === 'none' ? ' unset' : '')
} }
style={{ background: itemColor }} style={{background: itemColor}}
onClick={() => { onClick={() => {
if (itemColor === 'none') { if (itemColor === 'none') {
colorsSelected === 'color' colorsSelected === 'color'
? editor ? editor.chain().focus().unsetHighlight().unsetColor().run()
.chain() : editor.chain().focus().unsetColor().unsetHighlight().run()
.focus()
.unsetHighlight()
.unsetColor()
.run()
: editor
.chain()
.focus()
.unsetColor()
.unsetHighlight()
.run()
} else { } else {
colorsSelected === 'color' colorsSelected === 'color'
? editor ? editor.chain().focus().unsetHighlight().setColor(itemColor).run()
.chain() : editor.chain().focus().unsetColor().toggleHighlight({color: itemColor}).run()
.focus()
.unsetHighlight()
.setColor(itemColor)
.run()
: editor
.chain()
.focus()
.unsetColor()
.toggleHighlight({ color: itemColor })
.run()
} }
setColorsSelected(null) setColorsSelected(null)
}} }}
...@@ -1230,7 +1170,7 @@ const QEditor = ({ ...@@ -1230,7 +1170,7 @@ const QEditor = ({
: bubbleItems.map((type, i) => { : bubbleItems.map((type, i) => {
if (type === '|') { if (type === '|') {
return ( return (
<div key={'bubbleSeparator' + i} className='qseparator' /> <div key={'bubbleSeparator' + i} className='qseparator'/>
) )
} else { } else {
return ( return (
...@@ -1249,7 +1189,7 @@ const QEditor = ({ ...@@ -1249,7 +1189,7 @@ const QEditor = ({
})} })}
</div> </div>
</BubbleMenu> </BubbleMenu>
<EditorContent editor={editor} className='atma-editor-content' /> <EditorContent editor={editor} className='atma-editor-content'/>
</div> </div>
<EditorModal isOpen={modalIsOpen} title={modalTitle}> <EditorModal isOpen={modalIsOpen} title={modalTitle}>
{getInnerModal()} {getInnerModal()}
......
...@@ -4,7 +4,7 @@ import { Extension } from "@tiptap/core"; ...@@ -4,7 +4,7 @@ import { Extension } from "@tiptap/core";
export default Extension.create({ export default Extension.create({
name: "Resizable", name: "Resizable",
addOptions() { addOptions () {
return { return {
types: ["image", "video"], types: ["image", "video"],
handlerStyle: { handlerStyle: {
...@@ -18,31 +18,31 @@ export default Extension.create({ ...@@ -18,31 +18,31 @@ export default Extension.create({
}; };
}, },
addStorage() { addStorage () {
return { return {
resizeElement: null, resizeElement: null,
}; };
}, },
onCreate({ editor }) { onCreate ({editor}) {
const element = editor.options.element; const element = editor.options.element;
element.style.position = "relative"; element.style.position = "relative";
// resizeLayer // resizeLayer
console.log('onCreate', editor);
const resizeLayer = document.createElement("div"); const resizeLayer = document.createElement("div");
resizeLayer.className = "resize-layer"; resizeLayer.className = "resize-layer";
resizeLayer.style.display = "none"; resizeLayer.style.display = "none";
resizeLayer.style.position = "absolute"; resizeLayer.style.position = "absolute";
Object.entries(this.options.layerStyle).forEach(([key, value]) => { Object.entries(this.options.layerStyle).forEach(([key, value]) => {
resizeLayer.style[key] = value; resizeLayer.style[key] = value;
}); });
resizeLayer.addEventListener("mousedown", (e) => { resizeLayer.addEventListener("mousedown", (e) => {
const resizeElement = this.storage.resizeElement; const resizeElement = this.storage.resizeElement;
if (!resizeElement) return; if ( ! resizeElement) return;
if (/bottom/.test(e.target.className)) { if (/bottom/.test(e.target.className)) {
let startX = e.screenX; let startX = e.screenX;
const dir = e.target.classList.contains("bottom-left") ? -1 : 1; const dir = e.target.classList.contains("bottom-left") ? -1 : 1;
...@@ -57,8 +57,6 @@ export default Extension.create({ ...@@ -57,8 +57,6 @@ export default Extension.create({
const clientHeight = resizeElement.clientHeight; const clientHeight = resizeElement.clientHeight;
resizeElement.style.width = clientWidth + "px"; // max width resizeElement.style.width = clientWidth + "px"; // max width
// resizeLayer // resizeLayer
const pos = getRelativePosition(resizeElement, element); const pos = getRelativePosition(resizeElement, element);
resizeLayer.style.top = pos.top + "px"; resizeLayer.style.top = pos.top + "px";
...@@ -69,7 +67,7 @@ export default Extension.create({ ...@@ -69,7 +67,7 @@ export default Extension.create({
startX = e.screenX; startX = e.screenX;
}; };
document.addEventListener("mousemove", mousemoveHandle); document.addEventListener("mousemove", mousemoveHandle);
document.addEventListener("mouseup", () =>{ document.addEventListener("mouseup", () => {
document.removeEventListener("mousemove", mousemoveHandle) document.removeEventListener("mousemove", mousemoveHandle)
}); });
} }
...@@ -95,60 +93,42 @@ export default Extension.create({ ...@@ -95,60 +93,42 @@ export default Extension.create({
editor.resizeLayer = resizeLayer; editor.resizeLayer = resizeLayer;
element.appendChild(resizeLayer); element.appendChild(resizeLayer);
}, },
onSelectionUpdate({ editor, transaction }) { onUpdate({editor, transaction}) {
selectionUpdate({editor, transaction}, this.options, this.storage)
},
onSelectionUpdate ({editor, transaction}) {
selectionUpdate({editor, transaction}, this.options, this.storage)
},
});
function selectionUpdate({editor, transaction}, options, storage)
{
const element = editor.options.element; const element = editor.options.element;
const node = transaction.curSelection.node; const node = transaction.curSelection.node;
const resizeLayer = editor.resizeLayer; const resizeLayer = editor.resizeLayer;
console.log("res layer",resizeLayer) // console.log("res layer", resizeLayer)
if (node && this.options.types.includes(node.type.name)) { if (node && options.types.includes(node.type.name)) {
// resizeLayer位置大小 // resizeLayer
resizeLayer.style.display = "block"; resizeLayer.style.display = "block";
let dom = editor.view.domAtPos(transaction.curSelection.from).node; let dom = editor.view.domAtPos(transaction.curSelection.from).node;
if (dom.getAttribute("src") !== node.attrs.src) { if (dom.getAttribute("src") !== node.attrs.src) {
dom = dom.querySelector(`[src="${node.attrs.src}"]`); dom = dom.querySelector(`[src="${node.attrs.src}"]`);
} }
this.storage.resizeElement = dom; storage.resizeElement = dom;
const pos = getRelativePosition(dom, element); const pos = getRelativePosition(dom, element);
console.log("dom after src", dom)
console.log(pos)
resizeLayer.style.top = pos.top + "px"; resizeLayer.style.top = pos.top + "px";
resizeLayer.style.left = pos.left + "px"; resizeLayer.style.left = pos.left + "px";
resizeLayer.style.width = dom.width + "px"; resizeLayer.style.width = dom.width + "px";
resizeLayer.style.height = dom.height + "px"; resizeLayer.style.height = dom.height + "px";
const resizeObserver = new ResizeObserver((entries) => {
for (let entry of entries) {
const currentPosition = entry.target.getBoundingClientRect();
if (currentPosition.x === 0) {
console.log("changed pos");
//resizeLayer.style.display = "none";
}
console.log(entry.target.parentNode)
console.log("target: ", entry.target)
console.log("bounding rect: ", currentPosition)
}
})
resizeObserver.observe(dom);
} else { } else {
console.log("no node");
resizeLayer.style.display = "none"; resizeLayer.style.display = "none";
} }
}, }
}); function getRelativePosition (element, ancestor) {
// 计算相对位置
function getRelativePosition(element, ancestor) {
const elementRect = element.getBoundingClientRect(); const elementRect = element.getBoundingClientRect();
const ancestorRect = ancestor.getBoundingClientRect(); const ancestorRect = ancestor.getBoundingClientRect();
const relativePosition = { const relativePosition = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment