diff options
author | Robin Appelman <robin@icewind.nl> | 2017-08-29 16:34:45 +0300 |
---|---|---|
committer | Robin Appelman <robin@icewind.nl> | 2017-08-29 16:34:45 +0300 |
commit | 4fc50167b1fe6e6a6147a3a1e8fb25c274396937 (patch) | |
tree | d6b43f1e8d679a433f6bc0faefb7cacd421af2fd /js | |
parent | 1a657c70783f86df4dd1061ce299a5cd12727f9b (diff) |
Allow pasting images into the document
Signed-off-by: Robin Appelman <robin@icewind.nl>
Diffstat (limited to 'js')
-rw-r--r-- | js/Nextcloud.d.ts | 2 | ||||
-rw-r--r-- | js/PasteImage.ts | 66 | ||||
-rw-r--r-- | js/PreviewPlugin.ts | 52 | ||||
-rw-r--r-- | js/Renderer.ts | 2 | ||||
-rw-r--r-- | js/editor.ts | 4 |
5 files changed, 124 insertions, 2 deletions
diff --git a/js/Nextcloud.d.ts b/js/Nextcloud.d.ts index 4b22bdb..b5da79c 100644 --- a/js/Nextcloud.d.ts +++ b/js/Nextcloud.d.ts @@ -30,7 +30,7 @@ declare namespace OC { function confirmHtml(text: string, title: string, callback: (result: boolean) => void, modal?: boolean): void; - function prompt(text: string, title: string, callback: (result: string) => void, modal?: boolean, name?: string, password?: boolean): void; + function prompt(text: string, title: string, callback: (ok: boolean, result: string) => void, modal?: boolean, name?: string, password?: boolean): void; function filepicker(title: string, callback: (result: string | string[]) => void, multiselect?: boolean, mimetypeFilter?: string, modal?: boolean): void; } diff --git a/js/PasteImage.ts b/js/PasteImage.ts new file mode 100644 index 0000000..cc8ea50 --- /dev/null +++ b/js/PasteImage.ts @@ -0,0 +1,66 @@ +// from https://github.com/redgeoff/paste-image + +// This code is heavily based on Joel Basada's great work at +// http://joelb.me/blog/2011/code-snippet-accessing-clipboard-images-with-javascript/ + +export type PasteListener = (image: HTMLImageElement, file: File) => void; + +export class PasteImage { + private initialized: boolean = false; + private listeners: PasteListener[] = []; + + private listenForPaste() { + window.addEventListener('paste', e => { + this.pasteHandler(e); + }); + } + + private init() { + if (this.initialized) { + return; + } + this.listenForPaste(); + this.initialized = true; + } + + private pasteHandler(e) { + if (e.clipboardData && e.clipboardData.items) { + // Get the items from the clipboard + const items = e.clipboardData.items; + + // Loop through all items, looking for any kind of image + for (let i = 0; i < items.length; i++) { + if (items[i].type.includes('image')) { + const blob = items[i].getAsFile(); + + const URLObj = this.getURLObj(); + const source = URLObj.createObjectURL(blob); + + // The URL can then be used as the source of an image + this.createImage(source, blob); + } + } + } + } + + private getURLObj() { + return window.URL || window['webkitURL']; + } + + // Creates a new image from a given source + private createImage(source: string, file: File) { + const pastedImage = new Image(); + + pastedImage.onload = () => { + for (const listener of this.listeners) { + listener(pastedImage, file); + } + }; + pastedImage.src = source; + } + + public listen(handler: PasteListener) { + this.init(); + this.listeners.push(handler); + } +} diff --git a/js/PreviewPlugin.ts b/js/PreviewPlugin.ts index 9ec7445..027a0f8 100644 --- a/js/PreviewPlugin.ts +++ b/js/PreviewPlugin.ts @@ -1,5 +1,7 @@ import {Renderer} from './Renderer'; import {UnderscoreStatic} from "underscore"; +import {PasteImage} from './PasteImage'; +import Thenable = JQuery.Thenable; declare const _: UnderscoreStatic; @@ -34,6 +36,8 @@ export class PreviewPlugin { this.Range = window['ace'].require("ace/range").Range; aceEditor.$blockScrolling = Infinity; + + new PasteImage().listen(this.handleImage); } return this.initPromise; @@ -119,4 +123,52 @@ export class PreviewPlugin { this.scrollMode = null; }, 100); }, 100); + + handleImage = (image: HTMLImageElement, file) => { + console.log(file); + OC.dialogs.prompt('Enter the name for the image', 'Upload image', (ok, name) => { + if (!ok) { + return; + } + const blob = image.src; + const cursorPos = aceEditor.getCursorPosition(); + const uploadText = `![uploading...](${blob})`; + const finalText = `![${name}](${name})`; + this.session.insert(cursorPos, uploadText); + this.uploadImage(name, file).then(() => { + this.session.replace( + new this.Range(cursorPos.row, cursorPos.column, cursorPos.row, cursorPos.column + uploadText.length), + finalText + ); + }); + + }, true, 'image name'); + }; + + uploadImage(name: string, file: File): Thenable<void> { + const path = `${this.getCurrentPath()}/${name}`.replace(/\/\/+/g, '/'); + const url = OC.linkToRemote('files' + path); + const reader = new FileReader(); + const deferred = $.Deferred(); + reader.onloadend = (e) => { + $.ajax({ + url: url, + processData: false, + data: reader.result, + type: 'PUT', + success: deferred.resolve.bind(deferred), + error: deferred.reject.bind(deferred) + }); + }; + reader.readAsArrayBuffer(file); + return deferred.promise(); + } + + getCurrentPath() { + if (OCA.Files_Texteditor.file && OCA.Files_Texteditor.file.dir) { + return OCA.Files_Texteditor.file.dir; + } else if (OCA.Files.App && OCA.Files.App.fileList._currentDirectory) { + return OCA.Files.App.fileList._currentDirectory; + } + } }
\ No newline at end of file diff --git a/js/Renderer.ts b/js/Renderer.ts index 60bab9c..1b6538b 100644 --- a/js/Renderer.ts +++ b/js/Renderer.ts @@ -125,7 +125,7 @@ export class Renderer { if (!path || path.indexOf('.') === -1) { return path; } - if (path.substr(0, 7) === 'http://' || path.substr(0, 8) === 'https://' || path.substr(0, 3) === '://') { + if (path.indexOf('://') !== -1) { return path; } else { if (path.substr(0, 1) !== '/') { diff --git a/js/editor.ts b/js/editor.ts index 18b27e7..2e5369e 100644 --- a/js/editor.ts +++ b/js/editor.ts @@ -9,6 +9,10 @@ $(document).ready(function () { } }); +// fix editor closing when click on dialog + +// OCA.Files_Texteditor._onClickDocument + // coerce webpack into loading scripts properly __webpack_require__.p = OC.filePath('files_markdown', 'js', '../build/'); __webpack_require__.nc = $('script[nonce]')[0].getAttribute('nonce'); |