From f6fe67a142614aac81471dd693d44276cfa421d8 Mon Sep 17 00:00:00 2001 From: keray <1172304645@qq.com> Date: Wed, 25 Sep 2024 14:44:04 +0800 Subject: [PATCH 1/2] Uploader adds support for handlers extension --- packages/quill/src/modules/uploader.ts | 102 ++++++++++++++++++------- 1 file changed, 76 insertions(+), 26 deletions(-) diff --git a/packages/quill/src/modules/uploader.ts b/packages/quill/src/modules/uploader.ts index c53058c51b..63c5607c5c 100644 --- a/packages/quill/src/modules/uploader.ts +++ b/packages/quill/src/modules/uploader.ts @@ -6,7 +6,8 @@ import type { Range } from '../core/selection.js'; interface UploaderOptions { mimetypes: string[]; - handler: (this: { quill: Quill }, range: Range, files: File[]) => void; + handler?: (this: { quill: Quill }, range: Range, files: File[]) => void; + handlers?: Array>; } class Uploader extends Module { @@ -14,6 +15,7 @@ class Uploader extends Module { constructor(quill: Quill, options: Partial) { super(quill, options); + options.handlers?.forEach((handler) => handler.setQuill(quill)); quill.root.addEventListener('drop', (e) => { e.preventDefault(); let native: ReturnType | null = null; @@ -46,38 +48,86 @@ class Uploader extends Module { } }); if (uploads.length > 0) { - // @ts-expect-error Fix me later - this.options.handler.call(this, range, uploads); + if (this.options.handlers) { + const handlerFlag: Array = []; + uploads.forEach(() => handlerFlag.push(0)); + let rangLength = range.length; + for (let index = 0; index < uploads.length; index++) { + const file = uploads[index]; + const handler = this.options.handlers?.find((h) => + h.support(file.type), + ); + if (!handler) continue; + handler.handler(file).then((coverFile) => { + const nodeCoverLength = rangLength; + rangLength = 0; + let beforeRangeLength = 0; + for (let i = 0; i < index; i++) { + beforeRangeLength += handlerFlag[i]; + } + const nodeLength = handler.insert( + { + index: range.index + beforeRangeLength, + length: nodeCoverLength, + }, + file, + coverFile, + ); + handlerFlag[index] = nodeLength; + }); + } + return; + } + this.options.handler?.call(this, range, uploads); } } } -Uploader.DEFAULTS = { - mimetypes: ['image/png', 'image/jpeg'], - handler(range: Range, files: File[]) { +export abstract class UploaderHandler { + quill: Quill; + setQuill(quill: Quill): void { + this.quill = quill; + } + abstract support(fileType: String): boolean; + abstract handler(file: File): Promise; + abstract insert(range: Range, file: File, cover: T): number; +} +export abstract class AbstractUploaderHandler extends UploaderHandler { + abstract support(fileType: String): boolean; + abstract handler(file: File): Promise; + insert(range: Range, file: File, cover: T): number { + const singleDelta = new Delta() + .retain(range.index) + .delete(range.length) + .insert(this.deltaData(file, cover)); + this.quill.updateContents(singleDelta, Emitter.sources.USER); + return 1; + } + protected abstract deltaData(file: File, cover: T): any; +} +export class ImageUploaderHandler extends AbstractUploaderHandler { + support(fileType: String) { if (!this.quill.scroll.query('image')) { - return; + return false; } - const promises = files.map>((file) => { - return new Promise((resolve) => { - const reader = new FileReader(); - reader.onload = () => { - resolve(reader.result as string); - }; - reader.readAsDataURL(file); - }); - }); - Promise.all(promises).then((images) => { - const update = images.reduce((delta: Delta, image) => { - return delta.insert({ image }); - }, new Delta().retain(range.index).delete(range.length)) as Delta; - this.quill.updateContents(update, Emitter.sources.USER); - this.quill.setSelection( - range.index + images.length, - Emitter.sources.SILENT, - ); + return fileType.startsWith('image'); + } + handler(file: File): Promise { + return new Promise((resolve) => { + const reader = new FileReader(); + reader.onload = () => { + resolve(reader.result as string); + }; + reader.readAsDataURL(file); }); - }, + } + protected deltaData(file: File, cover: String): any { + return { image: cover }; + } +} +Uploader.DEFAULTS = { + mimetypes: ['image/png', 'image/jpeg'], + handlers: [new ImageUploaderHandler()], }; export default Uploader; From e8ee20b36a6a6e0cab67450938a7941e1acfc504 Mon Sep 17 00:00:00 2001 From: keray <1172304645@qq.com> Date: Wed, 25 Sep 2024 14:59:11 +0800 Subject: [PATCH 2/2] Set cursor position after all files are uploaded --- packages/quill/src/modules/uploader.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/quill/src/modules/uploader.ts b/packages/quill/src/modules/uploader.ts index 63c5607c5c..991d017d84 100644 --- a/packages/quill/src/modules/uploader.ts +++ b/packages/quill/src/modules/uploader.ts @@ -74,6 +74,13 @@ class Uploader extends Module { coverFile, ); handlerFlag[index] = nodeLength; + const uploadsFinish = handlerFlag.every((f) => f > 0); + if (uploadsFinish) { + this.quill.setSelection( + range.index + handlerFlag.reduce((v, s) => v + s), + Emitter.sources.SILENT, + ); + } }); } return;