Răsfoiți Sursa

Image upload UI initial implementation.

Szymon Kupś 8 ani în urmă
părinte
comite
19a4b8693f

+ 66 - 0
packages/ckeditor5-upload/src/imageupload.js

@@ -11,6 +11,9 @@ import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 import ImageUploadEngine from './imageuploadengine';
 import FileDialogButtonView from './ui/filedialogbuttonview';
 import imageIcon from '@ckeditor/ckeditor5-core/theme/icons/image.svg';
+import uploadingPlaceholder from '../theme/icons/image_placeholder.svg';
+import UIElement from '@ckeditor/ckeditor5-engine/src/view/uielement';
+import '../theme/theme.scss';
 
 /**
  * Image upload plugin.
@@ -33,6 +36,7 @@ export default class ImageUpload extends Plugin {
 		const editor = this.editor;
 		const t = editor.t;
 
+		// Setup `insertImage` button.
 		editor.ui.componentFactory.add( 'insertImage', ( locale ) => {
 			const view = new FileDialogButtonView( locale );
 
@@ -52,5 +56,67 @@ export default class ImageUpload extends Plugin {
 
 			return view;
 		} );
+
+		const uploadEngine = editor.plugins.get( ImageUploadEngine );
+
+		// TODO: to constructor?
+		this.placeholder = 'data:image/svg+xml;utf8,' + uploadingPlaceholder;
+
+		// Reading started.
+		uploadEngine.on( 'upload:reading', ( evt, modelImage ) => {
+			const viewFigure = editor.editing.mapper.toViewElement( modelImage );
+
+			// TODO: do it better since there might be more elements.
+			const viewImg = viewFigure.getChild( 0 );
+
+			viewFigure.addClass( 'ck-appear', 'ck-infinite-progress' );
+
+			viewImg.setAttribute( 'src', this.placeholder );
+			editor.editing.view.render();
+		} );
+
+		// Uploading started.
+		uploadEngine.on( 'upload:uploading', ( evt, modelImage, loader ) => {
+			const viewFigure = editor.editing.mapper.toViewElement( modelImage );
+			const progressBar = createProgressBar();
+			viewFigure.appendChildren( progressBar );
+
+			viewFigure.removeClass( 'ck-infinite-progress' );
+			editor.editing.view.render();
+
+			loader.on( 'change:uploadedPercent', ( evt, name, value ) => {
+				progressBar.setStyle( 'width', value + '%' );
+				editor.editing.view.render();
+			} );
+		} );
+
+		uploadEngine.on( 'upload:complete', ( evt, modelImage ) => {
+			const viewFigure = editor.editing.mapper.toViewElement( modelImage );
+			const progressBar = getProgressBar( viewFigure );
+
+			if ( progressBar ) {
+				progressBar.remove();
+				editor.editing.view.render();
+			}
+		} );
 	}
 }
+
+const progressBarSymbol = Symbol( 'progress-bar' );
+
+function createProgressBar() {
+	const progressBar = new UIElement( 'div', { class: 'ck-progress-bar' } );
+	progressBar.setCustomProperty( progressBarSymbol, true );
+
+	return progressBar;
+}
+
+function getProgressBar( imageFigure ) {
+	for ( const child of imageFigure.getChildren() ) {
+		if ( child.getCustomProperty( progressBarSymbol ) ) {
+			return child;
+		}
+	}
+
+	return null;
+}

+ 5 - 0
packages/ckeditor5-upload/src/imageuploadengine.js

@@ -97,6 +97,7 @@ export default class ImageUploadEngine extends Plugin {
 			const viewImg = viewFigure.getChild( 0 );
 
 			viewImg.setAttribute( 'src', this.placeholder );
+			this.fire( 'upload:reading', modelImage );
 		} );
 	}
 
@@ -122,6 +123,8 @@ export default class ImageUploadEngine extends Plugin {
 				viewImg.setAttribute( 'src', data );
 				editor.editing.view.render();
 
+				this.fire( 'upload:uploading', imageElement, loader );
+
 				return loader.upload();
 			} )
 			.then( data => {
@@ -129,6 +132,8 @@ export default class ImageUploadEngine extends Plugin {
 					batch.setAttribute( imageElement, 'src', data.original );
 				} );
 
+				this.fire( 'upload:complete', imageElement, loader );
+
 				clean();
 			} )
 			.catch( msg => {

+ 58 - 0
packages/ckeditor5-upload/theme/theme.scss

@@ -0,0 +1,58 @@
+
+// Move it to image/widget.
+figure.image.ck-widget {
+	position: relative;
+	overflow: hidden;
+}
+
+// Showing animation.
+.ck-appear {
+	animation: fadeIn 700ms;
+}
+
+@keyframes fadeIn {
+	from { opacity: 0; }
+	to   { opacity: 1; }
+}
+
+// Infinite progress bar on top.
+$lineWidth: 30px;
+
+.ck-infinite-progress::before {
+	content: "";
+	width: $lineWidth;
+	height: 2px;
+	position: absolute;
+	top: 0;
+	right: 0;
+	background: rgba(0, 0, 0, 0.1);
+	animation-name: ltrsUploadProgressBefore;
+	animation-duration: 1500ms;
+	animation-iteration-count: infinite;
+	transition-timing-function: linear;
+}
+
+.ck-progress-bar {
+	height: 2px;
+	width: 0;
+	position: absolute;
+	top: 0;
+	left: 0;
+	background: red;
+	transition: width 100ms;
+}
+
+@keyframes ltrsUploadProgressBefore {
+	0% {
+		width: $lineWidth;
+		right: 0;
+	}
+
+	50% {
+		width: $lineWidth * 1.5;
+	}
+
+	100% {
+		right: 100%;
+	}
+}