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
path: root/src
diff options
context:
space:
mode:
authorMax <max@nextcloud.com>2022-03-29 12:37:39 +0300
committerMax <max@nextcloud.com>2022-04-05 12:00:32 +0300
commit23402ca5cee86feed7cd21151794e850d7a30c7d (patch)
treeb187959dde4aa85706324f0c08ea931166d2283a /src
parent41a04a28d0a8310ca85a1a533b62c996ba1f2f30 (diff)
ui: maintain menu bubble size
When selecting the right-most chars in a line the menu bubble was getting too small. Meassure the menu bubble when it is drawn but still hidden. Calculate its position based on the editor width and the meassured bubble width. Signed-off-by: Max <max@nextcloud.com>
Diffstat (limited to 'src')
-rw-r--r--src/components/EditorWrapper.vue22
-rw-r--r--src/components/MenuBubble.vue23
-rw-r--r--src/components/MenuBubbleContainer.vue90
3 files changed, 113 insertions, 22 deletions
diff --git a/src/components/EditorWrapper.vue b/src/components/EditorWrapper.vue
index 61ceb0769..c8599daa8 100644
--- a/src/components/EditorWrapper.vue
+++ b/src/components/EditorWrapper.vue
@@ -54,11 +54,11 @@
<slot name="header" />
</MenuBar>
<div v-if="!menubarLoaded" class="menubar placeholder" />
+ <MenuBubble v-if="!readOnly && isRichEditor"
+ :editor="tiptap"
+ :content-wrapper="contentWrapper"
+ :file-path="relativePath" />
<div ref="contentWrapper" class="content-wrapper">
- <MenuBubble v-if="renderMenus"
- :editor="tiptap"
- :content-wrapper="contentWrapper"
- :file-path="relativePath" />
<EditorContent v-show="contentLoaded"
class="editor__content"
:editor="tiptap" />
@@ -112,6 +112,11 @@ export default {
isMobile,
store,
],
+ provide() {
+ return {
+ editorInfo: this.editorInfo,
+ }
+ },
props: {
initialSession: {
type: Object,
@@ -176,6 +181,7 @@ export default {
saveStatusPolling: null,
contentWrapper: null,
+ editorInfo: { width: 640 },
}
},
computed: {
@@ -262,9 +268,11 @@ export default {
this.saveStatusPolling = setInterval(() => {
this.updateLastSavedStatus()
}, 2000)
+ window.addEventListener('resize', this.updateEditorWidth)
},
beforeDestroy() {
this.close()
+ window.removeEventListener('resize', this.updateEditorWidth)
},
methods: {
async close() {
@@ -530,6 +538,12 @@ export default {
}
}
},
+
+ updateEditorWidth() {
+ if (this.$el) {
+ this.editorInfo.width = this.$el.offsetWidth
+ }
+ },
},
}
</script>
diff --git a/src/components/MenuBubble.vue b/src/components/MenuBubble.vue
index b6676dbb1..3bf926685 100644
--- a/src/components/MenuBubble.vue
+++ b/src/components/MenuBubble.vue
@@ -25,9 +25,8 @@
class="menububble"
:editor="editor"
@hide="hideLinkMenu">
- <div class="menububble"
- :class="{ 'is-active': menu.isActive }"
- :style="bubblePosition(menu)">
+ <MenuBubbleContainer :menu="menu"
+ :class="{ 'is-active': menu.isActive }">
<form v-if="linkMenuIsActive" class="menububble__form" @submit.prevent="setLinkUrl(commands.link, linkUrl)">
<input ref="linkInput"
v-model="linkUrl"
@@ -59,24 +58,22 @@
<span class="menububble__buttontext">{{ t('text', 'Link file') }}</span>
</button>
</template>
- </div>
+ </MenuBubbleContainer>
</EditorMenuBubble>
</template>
<script>
import { EditorMenuBubble } from 'tiptap'
+import MenuBubbleContainer from './MenuBubbleContainer'
import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip'
import { optimalPath } from './../helpers/files'
import { loadState } from '@nextcloud/initial-state'
-// This is a rough estimate used for positioning the bubble.
-// The actual width depends on the language and the state of the bubble.
-const MAX_BUBBLE_WIDTH = 325
-
export default {
name: 'MenuBubble',
components: {
EditorMenuBubble,
+ MenuBubbleContainer,
},
directives: {
tooltip: Tooltip,
@@ -155,15 +152,6 @@ export default {
command({ href: url })
this.hideLinkMenu()
},
- bubblePosition(menu) {
- const maxLeft = document.getElementById('editor').offsetWidth - MAX_BUBBLE_WIDTH
- const left = Math.min(maxLeft, menu.left - (MAX_BUBBLE_WIDTH / 2))
- const offset = this.contentWrapper?.scrollTop || 0
- return {
- top: `${menu.top + offset + 5}px`,
- left: `${left}px`,
- }
- },
},
}
@@ -179,7 +167,6 @@ export default {
border-radius: var(--border-radius-large);
overflow: hidden;
padding: 0;
- margin-left: 10px;
visibility: hidden;
opacity: 0;
transition: opacity 0.2s, visibility 0.2s;
diff --git a/src/components/MenuBubbleContainer.vue b/src/components/MenuBubbleContainer.vue
new file mode 100644
index 000000000..dbef078fd
--- /dev/null
+++ b/src/components/MenuBubbleContainer.vue
@@ -0,0 +1,90 @@
+<!--
+ - @copyright Copyright (c) 2022 Max <max@nextcloud.com>
+ -
+ - @author Max <max@nextcloud.com>
+ -
+ - @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 :style="bubblePosition">
+ <slot />
+ </div>
+</template>
+
+<script>
+
+export default {
+ name: 'MenuBubbleContainer',
+
+ inject: ['editorInfo'],
+ props: {
+ menu: {
+ type: Object,
+ required: true,
+ },
+ isActive: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+
+ },
+
+ data: () => {
+ return {
+ bubbleWidth: 325,
+ }
+ },
+
+ computed: {
+ editorWidth() {
+ return this.editorInfo.width
+ },
+ maxLeft() {
+ return this.editorWidth - this.bubbleWidth
+ },
+ bubblePosition() {
+ if (!this.menu.top) {
+ return { top: 'unset', left: 'unset' }
+ }
+ const offset = this.contentWrapper?.scrollTop || 0
+ const left = Math.min(this.maxLeft, this.menu.left - (this.bubbleWidth / 2))
+ return {
+ top: `${this.menu.top + offset + 5}px`,
+ left: `${left}px`,
+ }
+ },
+ },
+
+ // Meassure the bubble width once the editor is ready and visible.
+ // At this point the bubble will be hidden but with all content inside.
+ // It therefore has the width we want to use to calculate its position.
+ watch: {
+ 'editorInfo.width': 'updateBubbleWidth',
+ },
+
+ methods: {
+ updateBubbleWidth() {
+ this.$nextTick(() => {
+ this.bubbleWidth = this.$el?.offsetWidth ?? 325
+ })
+ },
+ },
+
+}
+</script>