button in menu bubble to link to files

Since the menu bubble deals with links
it makes more sense to add the button here.

Moved it to the initial part of the menu bubble
as an alternative to the link form.

Hand current path to menu bubble and use it
* to start from there when picking the file to link to
* to calculate the relative path.

Signed-off-by: Azul <azul@riseup.net>
This commit is contained in:
Azul 2020-06-16 10:00:16 +02:00
Родитель 8d9535fd7c
Коммит 03ccc8aa03
16 изменённых файлов: 96 добавлений и 46 удалений

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -50,7 +50,9 @@
<slot name="header" />
</MenuBar>
<div>
<MenuBubble v-if="!readOnly && isRichEditor" :editor="tiptap" />
<MenuBubble v-if="!readOnly && isRichEditor"
:editor="tiptap"
:filePath="relativePath" />
<EditorContent v-show="initialLoading"
class="editor__content"
:editor="tiptap" />

Просмотреть файл

@ -75,6 +75,7 @@
import { EditorMenuBar } from 'tiptap'
import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip'
import menuBarIcons from './../mixins/menubar'
import { optimalPath } from './../helpers/files'
import Actions from '@nextcloud/vue/dist/Components/Actions'
import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
@ -158,14 +159,6 @@ export default {
action: (commands) => {
this.showImagePrompt(commands.image)
},
}, {
label: t('text', 'Insert link'),
class: 'icon-link',
isActive: () => {
},
action: (commands) => {
this.showLinkPrompt(commands.link)
},
}]
},
childPopoverMenu() {
@ -207,10 +200,6 @@ export default {
return this.lastImagePath
|| this.filePath.split('/').slice(0, -1).join('/')
},
linkPath() {
return this.lastLinkPath
|| this.filePath.split('/').slice(0, -1).join('/')
},
},
mounted() {
window.addEventListener('resize', this.getWindowWidth)
@ -266,7 +255,7 @@ export default {
mimetype: fileInfo.mimetype,
hasPreview: fileInfo.hasPreview,
}
const path = this.optimalPathTo(`${fileInfo.path}/${fileInfo.name}`)
const path = optimalPath(this.filePath, `${fileInfo.path}/${fileInfo.name}`)
const encodedPath = path.split('/').map(encodeURIComponent).join('/')
const meta = Object.entries(appendMeta).map(([key, val]) => `${key}=${encodeURIComponent(val)}`).join('&')
const src = `${encodedPath}?fileId=${fileInfo.id}#${meta}`

Просмотреть файл

@ -27,16 +27,16 @@
@hide="hideLinkMenu">
<div class="menububble" :class="{ 'is-active': menu.isActive }" :style="`left: ${menu.left}px; bottom: ${menu.bottom}px;`">
<form v-if="linkMenuIsActive" class="menububble__form" @submit.prevent="setLinkUrl(commands.link, linkUrl)">
<button
class="icon-file"
@click="selectFile(commands.link)" />
<input ref="linkInput"
v-model="linkUrl"
class="menububble__input"
type="text"
placeholder="https://"
@keydown.esc="hideLinkMenu">
<button class="menububble__button icon-confirm" type="button" @click="setLinkUrl(commands.link, linkUrl)" />
<button class="menububble__button icon-confirm"
type="button"
tabindex="0"
@click="setLinkUrl(commands.link, linkUrl)" />
</form>
<template v-else>
@ -45,7 +45,16 @@
:class="{ 'is-active': isActive.link() }"
@click="showLinkMenu(getMarkAttrs('link'))">
<span v-tooltip="isActive.link() ? 'Update Link' : 'Add Link'" class="icon-link" />
<span class="menububble__buttontext">{{ t('text', 'Add link') }}</span>
<span class="menububble__buttontext">
{{ t('text', isActive.link() ? 'Update Link' : 'Add Link') }}
</span>
</button>
<button
class="menububble__button"
:class="{ 'is-active': isActive.link() }"
@click="selectFile(commands.link)">
<span v-tooltip="'Link file'" class="icon-file" />
<span class="menububble__buttontext">{{ t('text', 'Link file') }}</span>
</button>
</template>
</div>
@ -55,6 +64,7 @@
<script>
import { EditorMenuBubble } from 'tiptap'
import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip'
import { optimalPath } from './../helpers/files'
export default {
name: 'MenuBubble',
@ -70,6 +80,11 @@ export default {
required: false,
default: null,
},
filePath: {
type: String,
required: false,
default: '',
},
},
data: () => {
return {
@ -89,27 +104,33 @@ export default {
this.linkUrl = null
this.linkMenuIsActive = false
},
selectFile(command) {
const currentUser = OC.getCurrentUser()
if (!currentUser) {
return
}
const startPath = this.filePath.split('/').slice(0, -1).join('/')
OC.dialogs.filepicker('Select file to link to', (file) => {
const client = OC.Files.getClient()
client.getFileInfo(file).then((_status, fileInfo) => {
// todo: use optimal path
const path = (`${fileInfo.path}/${fileInfo.name}`)
const path = optimalPath(this.filePath, `${fileInfo.path}/${fileInfo.name}`)
const encodedPath = path.split('/').map(encodeURIComponent).join('/')
const href = `${encodedPath}?fileId=${fileInfo.id}`
this.setLinkUrl(command, href)
command({ href: `${encodedPath}?fileId=${fileInfo.id}` })
this.hideLinkMenu()
})
}, false, [], true)
// todo: , undefined, this.linkPath)
}, false, [], true, undefined, startPath)
},
setLinkUrl(command, url) {
if (url && !url.match(/^[a-zA-Z]+:\/\//) && !url.match(/^\//)) {
// Heuristics for determining if we need a https:// prefix.
const noPrefixes = [
/^[a-zA-Z]+:/, // url with protocol ("mailTo:email@domain.tld")
/^\//, // absolute path
/\?fileId=/, // relative link with fileId
/^\.\.?\//, // relative link starting with ./ or ../
/^[^.]*[/$]/, // no dots before first '/' - not a domain name
/^#/, // url fragment
]
if (url && !noPrefixes.find(regex => url.match(regex))) {
url = 'https://' + url
}
command({ href: url })

Просмотреть файл

@ -30,6 +30,21 @@ import { imagePath } from '@nextcloud/router'
const FILE_ACTION_IDENTIFIER = 'Edit with text app'
const optimalPath = function(from, to) {
const current = from.split('/')
const target = to.split('/')
current.pop() // ignore filename
while (current[0] === target[0]) {
current.shift()
target.shift()
}
const relativePath = current.fill('..').concat(target)
const absolutePath = to.split('/')
return relativePath.length < absolutePath.length
? relativePath.join('/')
: to
}
const registerFileCreate = () => {
const newFileMenuPlugin = {
attach(menu) {
@ -157,6 +172,7 @@ const FilesWorkspacePlugin = {
}
export {
optimalPath,
registerFileActionFallback,
registerFileCreate,
FilesWorkspacePlugin,