Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/icewind1991/files_markdown.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
authorRobin Appelman <robin@icewind.nl>2017-08-29 16:34:45 +0300
committerRobin Appelman <robin@icewind.nl>2017-08-29 16:34:45 +0300
commit4fc50167b1fe6e6a6147a3a1e8fb25c274396937 (patch)
treed6b43f1e8d679a433f6bc0faefb7cacd421af2fd /js
parent1a657c70783f86df4dd1061ce299a5cd12727f9b (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.ts2
-rw-r--r--js/PasteImage.ts66
-rw-r--r--js/PreviewPlugin.ts52
-rw-r--r--js/Renderer.ts2
-rw-r--r--js/editor.ts4
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');