diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 910abebc..19eabb6d 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -212,7 +212,6 @@ "Nothing here yet": "There's nothing here yet", "Nothing is here": "There is nothing here", "Notifications": "Notifications", - "Registered since {{date}}": "Registered since {{date}}", "Or continue with social network": "Or continue with social network", "Or paste a link to an image": "Or paste a link to an image", "Ordered list": "Ordered list", @@ -250,6 +249,7 @@ "Quotes": "Quotes", "Reason uknown": "Reason unknown", "Recent": "Fresh", + "Registered since {{date}}": "Registered since {{date}}", "Remove link": "Remove link", "Reply": "Reply", "Report": "Complain", @@ -327,6 +327,7 @@ "Upload": "Upload", "Upload error": "Upload error", "Upload video": "Upload video", + "Uploading image": "Uploading image", "Username": "Username", "Userpic": "Userpic", "Users": "Users", diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json index 5ecc804f..11f3a432 100644 --- a/public/locales/ru/translation.json +++ b/public/locales/ru/translation.json @@ -222,7 +222,6 @@ "Nothing here yet": "Здесь пока ничего нет", "Nothing is here": "Здесь ничего нет", "Notifications": "Уведомления", - "Registered since {{date}}": "На сайте c {{date}}", "Or continue with social network": "Или войдите через соцсеть", "Or paste a link to an image": "Или вставьте ссылку на изображение", "Ordered list": "Нумерованный список", @@ -264,6 +263,7 @@ "Quotes": "Цитаты", "Reason uknown": "Причина неизвестна", "Recent": "Свежее", + "Registered since {{date}}": "На сайте c {{date}}", "Release date...": "Дата выхода...", "Remove link": "Убрать ссылку", "Reply": "Ответить", @@ -345,6 +345,7 @@ "Upload": "Загрузить", "Upload error": "Ошибка загрузки", "Upload video": "Загрузить видео", + "Uploading image": "Загружаем изображение", "Username": "Имя пользователя", "Userpic": "Аватар", "Users": "Пользователи", diff --git a/src/components/Editor/Editor.tsx b/src/components/Editor/Editor.tsx index f31f4e1f..8b6ecfb5 100644 --- a/src/components/Editor/Editor.tsx +++ b/src/components/Editor/Editor.tsx @@ -44,6 +44,9 @@ import { EditorFloatingMenu } from './EditorFloatingMenu' import './Prosemirror.scss' import { Image } from '@tiptap/extension-image' import { Footnote } from './extensions/Footnote' +import { handleFileUpload } from '../../utils/handleFileUpload' +import { imageProxy } from '../../utils/imageProxy' +import { useSnackbar } from '../../context/snackbar' type Props = { shoutId: number @@ -51,6 +54,17 @@ type Props = { onChange: (text: string) => void } +const allowedImageTypes = new Set([ + 'image/bmp', + 'image/gif', + 'image/jpeg', + 'image/jpg', + 'image/png', + 'image/tiff', + 'image/webp', + 'image/x-icon' +]) + const yDocs: Record = {} const providers: Record = {} @@ -61,6 +75,10 @@ export const Editor = (props: Props) => { const [isCommonMarkup, setIsCommonMarkup] = createSignal(false) const [shouldShowTextBubbleMenu, setShouldShowTextBubbleMenu] = createSignal(false) + const { + actions: { showSnackbar } + } = useSnackbar() + const docName = `shout-${props.shoutId}` if (!yDocs[docName]) { @@ -114,12 +132,73 @@ export const Editor = (props: Props) => { content: 'figcaption image' }) + const handleClipboardPaste = async () => { + try { + const clipboardItems = await navigator.clipboard.read() + + if (clipboardItems.length === 0) return + const [clipboardItem] = clipboardItems + const { types } = clipboardItem + const imageType = types.find((type) => allowedImageTypes.has(type)) + + if (!imageType) return + const blob = await clipboardItem.getType(imageType) + const extension = imageType.split('/')[1] + const file = new File([blob], `clipboardImage.${extension}`) + + const uplFile = { + source: blob.toString(), + name: file.name, + size: file.size, + file + } + + showSnackbar({ body: t('Uploading image') }) + const result = await handleFileUpload(uplFile) + + editor() + .chain() + .focus() + .insertContent({ + type: 'capturedImage', + content: [ + { + type: 'figcaption', + content: [ + { + type: 'text', + text: result.originalFilename + } + ] + }, + { + type: 'image', + attrs: { + src: imageProxy(result.url) + } + } + ] + }) + .run() + } catch (error) { + console.log('!!! Paste image Error:', error) + } + } + const { initialContent } = props + const editor = createTiptapEditor(() => ({ element: editorElRef.current, editorProps: { attributes: { class: 'articleEditor' + }, + transformPastedHTML(html) { + return html.replaceAll(//g, '') + }, + handlePaste: () => { + handleClipboardPaste() + return false } }, extensions: [ @@ -246,6 +325,7 @@ export const Editor = (props: Props) => { TrailingNode, Article ], + enablePasteRules: [Link], content: initialContent ?? null })) diff --git a/src/utils/renderUploadedImage.ts b/src/utils/renderUploadedImage.ts index 30aa4749..40b95f14 100644 --- a/src/utils/renderUploadedImage.ts +++ b/src/utils/renderUploadedImage.ts @@ -15,7 +15,7 @@ export const renderUploadedImage = (editor: Editor, image: UploadedFile) => { content: [ { type: 'text', - text: image.originalFilename + text: image.originalFilename ?? '' } ] },