feat: File attachments (#3031)

* stash

* refactor, working in non-collab + collab editor

* attachment styling

* Avoid crypto require in browser

* AttachmentIcon, handling unknown types

* Do not allow attachment creation for file sizes over limit

* Allow image as file attachment

* Upload placeholder styling

* lint

* Refactor: Do not use placeholder for file attachmentuploads

* Add loading spinner

* fix: Extra paragraphs around attachments on insert

* Bump editor

* fix build error

* Remove attachment placeholder when upload fails

* Remove unused styles

* fix: Attachments on shared pages

* Merge fixes
This commit is contained in:
Tom Moor
2022-03-06 13:58:58 -08:00
committed by GitHub
parent 8b0b383e9e
commit 631d600920
82 changed files with 846 additions and 322 deletions

View File

@@ -36,7 +36,7 @@ const uploadPlugin = (options: Options) =>
paste(view, event: ClipboardEvent): boolean {
if (
(view.props.editable && !view.props.editable(view.state)) ||
!options.uploadImage
!options.uploadFile
) {
return false;
}
@@ -48,8 +48,9 @@ const uploadPlugin = (options: Options) =>
// check if we actually pasted any files
const files = Array.prototype.slice
.call(event.clipboardData.items)
.map((dt: any) => dt.getAsFile())
.filter((file: File) => file);
.filter((dt: DataTransferItem) => dt.kind !== "string")
.map((dt: DataTransferItem) => dt.getAsFile())
.filter(Boolean);
if (files.length === 0) {
return false;
@@ -67,15 +68,13 @@ const uploadPlugin = (options: Options) =>
drop(view, event: DragEvent): boolean {
if (
(view.props.editable && !view.props.editable(view.state)) ||
!options.uploadImage
!options.uploadFile
) {
return false;
}
// filter to only include image files
const files = getDataTransferFiles(event).filter((file) =>
/image/i.test(file.type)
);
const files = getDataTransferFiles(event);
if (files.length === 0) {
return false;
}
@@ -430,14 +429,14 @@ export default class Image extends Node {
replaceImage: () => (state: EditorState) => {
const { view } = this.editor;
const {
uploadImage,
onImageUploadStart,
onImageUploadStop,
uploadFile,
onFileUploadStart,
onFileUploadStop,
onShowToast,
} = this.editor.props;
if (!uploadImage) {
throw new Error("uploadImage prop is required to replace images");
if (!uploadFile) {
throw new Error("uploadFile prop is required to replace images");
}
// create an input element and click to trigger picker
@@ -447,9 +446,9 @@ export default class Image extends Node {
inputElement.onchange = (event: Event) => {
const files = getDataTransferFiles(event);
insertFiles(view, event, state.selection.from, files, {
uploadImage,
onImageUploadStart,
onImageUploadStop,
uploadFile,
onFileUploadStart,
onFileUploadStop,
onShowToast,
dictionary: this.options.dictionary,
replaceExisting: true,