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

github.com/nextcloud/text.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulius Härtl <jus@bitgrid.net>2019-06-15 13:39:11 +0300
committerJulius Härtl <jus@bitgrid.net>2019-06-15 13:39:11 +0300
commit1824f1065c953b0f2f178cf553a6797508659633 (patch)
tree8bae6c7ea2271c1d9887fff6934f1694f336d9d2
parent1bf1660e84c84039036851cea627573cf77c9494 (diff)
Implement custom image node with placeholder and alt text editing
Signed-off-by: Julius Härtl <jus@bitgrid.net>
-rw-r--r--src/EditorFactory.js2
-rw-r--r--src/components/EditorWrapper.vue2
-rw-r--r--src/components/MenuBar.vue2
-rw-r--r--src/nodes/Image.js39
-rw-r--r--src/nodes/ImageView.vue157
-rw-r--r--src/nodes/index.js27
6 files changed, 226 insertions, 3 deletions
diff --git a/src/EditorFactory.js b/src/EditorFactory.js
index 167b3a6dc..468a9bf99 100644
--- a/src/EditorFactory.js
+++ b/src/EditorFactory.js
@@ -31,10 +31,10 @@ import {
Blockquote,
CodeBlock,
HorizontalRule,
- Image,
History
} from 'tiptap-extensions'
import { Strong, Italic, Strike } from './marks'
+import { Image } from './nodes'
import MarkdownIt from 'markdown-it'
import { MarkdownSerializer, defaultMarkdownSerializer } from 'prosemirror-markdown'
diff --git a/src/components/EditorWrapper.vue b/src/components/EditorWrapper.vue
index 8d6f0e97f..591fecc27 100644
--- a/src/components/EditorWrapper.vue
+++ b/src/components/EditorWrapper.vue
@@ -269,7 +269,7 @@ export default {
})
this.syncService.state = this.tiptap.state
this.$emit('update:loaded', true)
- this.tiptap.focus('end')
+ this.tiptap.focus('start')
})
.on('sync', ({ steps, document }) => {
try {
diff --git a/src/components/MenuBar.vue b/src/components/MenuBar.vue
index e1ce9c8ee..f37ee054c 100644
--- a/src/components/MenuBar.vue
+++ b/src/components/MenuBar.vue
@@ -100,7 +100,7 @@ export default {
const _command = command
OC.dialogs.filepicker('Insert an image', (file) => {
const src = OC.generateUrl('/core/preview.png?') + `file=${file}&x=1024&y=1024&a=true`
- _command({ src })
+ _command({ src, alt: file })
// TODO: check permissions
// TODO: check for available preview
}, false, false, true)
diff --git a/src/nodes/Image.js b/src/nodes/Image.js
new file mode 100644
index 000000000..bd0e39c25
--- /dev/null
+++ b/src/nodes/Image.js
@@ -0,0 +1,39 @@
+/*
+ * @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import { Image as TiptapImage } from 'tiptap-extensions'
+import ImageView from './ImageView'
+
+export default class Image extends TiptapImage {
+
+ get view() {
+ return ImageView
+ }
+
+ get schema() {
+ return {
+ ...super.schema,
+ selectable: false
+ }
+ }
+
+}
diff --git a/src/nodes/ImageView.vue b/src/nodes/ImageView.vue
new file mode 100644
index 000000000..3b837c5b2
--- /dev/null
+++ b/src/nodes/ImageView.vue
@@ -0,0 +1,157 @@
+<!--
+ - @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net>
+ -
+ - @author Julius Härtl <jus@bitgrid.net>
+ -
+ - @license GNU AGPL version 3 or any later version
+ -
+ - This program is free software: you can redistribute it and/or modify
+ - it under the terms of the GNU Affero General Public License as
+ - published by the Free Software Foundation, either version 3 of the
+ - License, or (at your option) any later version.
+ -
+ - This program is distributed in the hope that it will be useful,
+ - but WITHOUT ANY WARRANTY; without even the implied warranty of
+ - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ - GNU Affero General Public License for more details.
+ -
+ - You should have received a copy of the GNU Affero General Public License
+ - along with this program. If not, see <http://www.gnu.org/licenses/>.
+ -
+ -->
+
+<template>
+ <div class="image" :class="{'icon-loading': !loaded}">
+ <div v-if="imageLoaded">
+ <transition name="fade">
+ <img v-show="loaded" :src="src"
+ class="image__main" @load="onLoaded">
+ </transition>
+ <transition name="fade">
+ <div v-show="loaded" class="image__caption">
+ <input ref="altInput" type="text" :value="alt"
+ @keyup.enter="updateAlt()">
+ </div>
+ </transition>
+ </div>
+ <div v-else class="image__placeholder">
+ <transition name="fade">
+ <div v-show="loaded" class="image__main">
+ <div class="icon-image" />
+ <p>{{ t('text', 'Insufficient permissions to view image') }}</p>
+ </div>
+ </transition>
+ <transition name="fade">
+ <div v-show="loaded" class="image__caption">
+ <input ref="altInput" type="text" :value="alt"
+ @keyup.enter="updateAlt()">
+ </div>
+ </transition>
+ </div>
+ </div>
+</template>
+
+<script>
+export default {
+ name: 'ImageView',
+ props: ['node', 'updateAttrs', 'view'], // eslint-disable-line
+ data() {
+ return {
+ imageLoaded: false,
+ loaded: false,
+ failed: false
+ }
+ },
+ computed: {
+ src: {
+ get() {
+ return this.node.attrs.src
+ },
+ set(src) {
+ this.updateAttrs({
+ src
+ })
+ }
+ },
+ alt: {
+ get() {
+ return this.node.attrs.alt ? this.node.attrs.alt : ''
+ },
+ set(alt) {
+ this.updateAttrs({
+ alt
+ })
+ }
+ },
+ t() {
+ return (a, s) => window.t(a, s)
+ }
+ },
+ beforeMount() {
+ var img = new Image()
+ img.src = this.node.attrs.src
+ img.onload = () => {
+ this.imageLoaded = true
+ }
+ img.onerror = () => {
+ this.failed = true
+ this.imageLoaded = false
+ this.loaded = true
+ }
+ },
+ methods: {
+ updateAlt() {
+ this.alt = this.$refs.altInput.value
+ },
+ onLoaded() {
+ this.loaded = true
+ }
+ }
+}
+</script>
+
+<style scoped lang="scss">
+ .image {
+ border: 1px solid transparent !important;
+ &:hover {
+ border: 1px solid var(--color-background-darker) !important;
+ }
+ }
+ .image__caption {
+ text-align: center;
+ color: var(--color-text-lighter);
+ input[type="text"] {
+ width: 100%;
+ border: none;
+ text-align: center;
+ }
+ }
+ .icon-image {
+ margin-top: 10px;
+ height: 32px;
+ padding: 20px;
+ }
+ .image__loading {
+ height: 100px;
+ }
+ .image__placeholder .image__main {
+ background-color: var(--color-background-dark);
+ text-align: center;
+ padding: 20px;
+ .icon-image {
+ opacity: 0.7;
+ }
+ }
+
+ .fade-enter-active {
+ transition: opacity .3s ease-in-out;
+ }
+
+ .fade-enter-to {
+ opacity: 1;
+ }
+
+ .fade-enter {
+ opacity: 0;
+ }
+</style>
diff --git a/src/nodes/index.js b/src/nodes/index.js
new file mode 100644
index 000000000..b51a01d03
--- /dev/null
+++ b/src/nodes/index.js
@@ -0,0 +1,27 @@
+/*
+ * @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import Image from './Image'
+
+export {
+ Image
+}