diff --git a/src/components/EditorWrapper.vue b/src/components/EditorWrapper.vue
index 1ec1d0cb1a2..f160bb0d258 100644
--- a/src/components/EditorWrapper.vue
+++ b/src/components/EditorWrapper.vue
@@ -74,9 +74,6 @@
-
@@ -136,7 +133,6 @@ export default {
EditorContent,
EditorMidiaHandler,
MenuBar,
- MenuBubble: () => import(/* webpackChunkName: "editor-rich" */'./MenuBubble.vue'),
Reader: () => import(/* webpackChunkName: "editor" */'./Reader.vue'),
CollisionResolveDialog: () => import(/* webpackChunkName: "editor" */'./CollisionResolveDialog.vue'),
GuestNameDialog: () => import(/* webpackChunkName: "editor-guest" */'./GuestNameDialog.vue'),
diff --git a/src/components/Menu/ActionInsertLink.vue b/src/components/Menu/ActionInsertLink.vue
new file mode 100644
index 00000000000..58a93b1beb7
--- /dev/null
+++ b/src/components/Menu/ActionInsertLink.vue
@@ -0,0 +1,203 @@
+
+
+
+
+
+
+
+
+
+
+ {{ t('text', 'Remove Link') }}
+
+
+
+
+
+ {{ t('text', 'Link to File or Directory') }}
+
+
+
+
+
+ {{ t('text', 'Link to Website') }}
+
+
+
+
+
+ {{ state.active ? t('text', 'Update Link') : t('text', 'Link to Website') }}
+
+
+
+
+
diff --git a/src/components/Menu/MenuBar.vue b/src/components/Menu/MenuBar.vue
index e2b66036184..d530cc5d806 100644
--- a/src/components/Menu/MenuBar.vue
+++ b/src/components/Menu/MenuBar.vue
@@ -214,7 +214,7 @@ export default {
--background-blur: blur(10px);
position: sticky;
top: 0;
- z-index: 10021; // above modal-header and menububble so menubar is always on top
+ z-index: 10021; // above modal-header so menubar is always on top
background-color: var(--color-main-background-translucent);
backdrop-filter: var(--background-blur);
max-height: 44px; // important for mobile so that the buttons are always inside the container
diff --git a/src/components/Menu/entries.js b/src/components/Menu/entries.js
index 9af3dd04a71..4fd21487392 100644
--- a/src/components/Menu/entries.js
+++ b/src/components/Menu/entries.js
@@ -46,9 +46,11 @@ import {
Emoticon,
Help,
Images,
+ Link,
} from '../icons.js'
import EmojiPickerAction from './EmojiPickerAction.vue'
import ActionImageUpload from './ActionImageUpload.vue'
+import ActionInsertLink from './ActionInsertLink.vue'
export default [
{
@@ -58,7 +60,7 @@ export default [
keyModifiers: ['ctrl'],
icon: Undo,
action: (command) => command.undo(),
- priority: 5,
+ priority: 6,
},
{
key: 'redo',
@@ -67,7 +69,7 @@ export default [
keyModifiers: ['ctrl'],
icon: Redo,
action: (command) => command.redo(),
- priority: 11,
+ priority: 12,
},
{
key: 'bold',
@@ -79,7 +81,7 @@ export default [
action: (command) => {
return command.toggleBold()
},
- priority: 6,
+ priority: 7,
},
{
key: 'italic',
@@ -91,7 +93,7 @@ export default [
action: (command) => {
return command.toggleItalic()
},
- priority: 7,
+ priority: 8,
},
{
key: 'underline',
@@ -103,7 +105,7 @@ export default [
action: (command) => {
return command.toggleUnderline()
},
- priority: 14,
+ priority: 15,
},
{
key: 'strikethrough',
@@ -115,7 +117,7 @@ export default [
action: (command) => {
return command.toggleStrike()
},
- priority: 15,
+ priority: 16,
},
{
key: 'headings',
@@ -193,7 +195,7 @@ export default [
action: (command) => {
return command.toggleBulletList()
},
- priority: 8,
+ priority: 9,
},
{
key: 'ordered-list',
@@ -205,7 +207,7 @@ export default [
action: (command) => {
return command.toggleOrderedList()
},
- priority: 9,
+ priority: 10,
},
{
key: 'task-list',
@@ -213,7 +215,15 @@ export default [
isActive: 'taskList',
icon: FormatListCheckbox,
action: (command) => command.toggleTaskList(),
- priority: 10,
+ priority: 11,
+ },
+ {
+ key: 'insert-link',
+ label: t('text', 'Insert link'),
+ isActive: 'link',
+ icon: Link,
+ component: ActionInsertLink,
+ priority: 2,
},
{
key: 'blockquote',
@@ -225,7 +235,7 @@ export default [
action: (command) => {
return command.toggleBlockquote()
},
- priority: 12,
+ priority: 13,
},
{
key: 'callouts',
@@ -281,7 +291,7 @@ export default [
action: (command) => {
return command.toggleCodeBlock()
},
- priority: 13,
+ priority: 14,
},
{
key: 'table',
@@ -291,7 +301,7 @@ export default [
action: (command) => {
return command.insertTable()
},
- priority: 16,
+ priority: 17,
},
{
key: 'emoji-picker',
@@ -301,20 +311,20 @@ export default [
action: (command, emojiObject = {}) => {
return command.emoji(emojiObject)
},
- priority: 4,
+ priority: 5,
},
{
key: 'insert-image',
label: t('text', 'Insert image'),
icon: Images,
component: ActionImageUpload,
- priority: 2,
+ priority: 4,
},
{
key: 'formatting-help',
label: t('text', 'Formatting help'),
icon: Help,
click: (view) => view.$emit('call:help'),
- priority: 17,
+ priority: 18,
},
]
diff --git a/src/components/MenuBubble.vue b/src/components/MenuBubble.vue
deleted file mode 100644
index 706de84adaf..00000000000
--- a/src/components/MenuBubble.vue
+++ /dev/null
@@ -1,235 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/src/components/icons.js b/src/components/icons.js
index 926a4d477d8..3aa0572f4a3 100644
--- a/src/components/icons.js
+++ b/src/components/icons.js
@@ -28,6 +28,7 @@ import MDI_Delete from 'vue-material-design-icons/Delete.vue'
import MDI_Document from 'vue-material-design-icons/FileDocument.vue'
import MDI_DotsHorizontal from 'vue-material-design-icons/DotsHorizontal.vue'
import MDI_Emoticon from 'vue-material-design-icons/EmoticonOutline.vue'
+import MDI_FileLink from 'vue-material-design-icons/FileLink.vue'
import MDI_Folder from 'vue-material-design-icons/Folder.vue'
import MDI_FormatBold from 'vue-material-design-icons/FormatBold.vue'
import MDI_FormatHeader1 from 'vue-material-design-icons/FormatHeader1.vue'
@@ -48,6 +49,7 @@ import MDI_Image from 'vue-material-design-icons/ImageOutline.vue'
import MDI_Images from 'vue-material-design-icons/ImageMultipleOutline.vue'
import MDI_Info from 'vue-material-design-icons/Information.vue'
import MDI_Link from 'vue-material-design-icons/Link.vue'
+import MDI_LinkOff from 'vue-material-design-icons/LinkOff.vue'
import MDI_Loading from 'vue-material-design-icons/Loading.vue'
import MDI_Lock from 'vue-material-design-icons/Lock.vue'
import MDI_Positive from 'vue-material-design-icons/CheckboxMarkedCircle.vue'
@@ -62,6 +64,7 @@ import MDI_TrashCan from 'vue-material-design-icons/TrashCan.vue'
import MDI_Undo from 'vue-material-design-icons/ArrowULeftTop.vue'
import MDI_Upload from 'vue-material-design-icons/Upload.vue'
import MDI_Warn from 'vue-material-design-icons/Alert.vue'
+import MDI_Web from 'vue-material-design-icons/Web.vue'
const DEFAULT_ICON_SIZE = 20
@@ -95,6 +98,7 @@ export const Delete = makeIcon(MDI_Delete)
export const Document = makeIcon(MDI_Document)
export const DotsHorizontal = makeIcon(MDI_DotsHorizontal)
export const Emoticon = makeIcon(MDI_Emoticon)
+export const FileLink = makeIcon(MDI_FileLink)
export const Folder = makeIcon(MDI_Folder)
export const FormatBold = makeIcon(MDI_FormatBold)
export const FormatHeader1 = makeIcon(MDI_FormatHeader1)
@@ -115,6 +119,7 @@ export const Image = makeIcon(MDI_Image)
export const Images = makeIcon(MDI_Images)
export const Info = makeIcon(MDI_Info)
export const Link = makeIcon(MDI_Link)
+export const LinkOff = makeIcon(MDI_LinkOff)
export const Lock = makeIcon(MDI_Lock)
export const Positive = makeIcon(MDI_Positive)
export const Redo = makeIcon(MDI_Redo)
@@ -128,3 +133,4 @@ export const TrashCan = makeIcon(MDI_TrashCan)
export const Undo = makeIcon(MDI_Undo)
export const Upload = makeIcon(MDI_Upload)
export const Warn = makeIcon(MDI_Warn)
+export const Web = makeIcon(MDI_Web)
diff --git a/src/helpers/files.js b/src/helpers/files.js
index f4b5625d07e..286f09a7302 100644
--- a/src/helpers/files.js
+++ b/src/helpers/files.js
@@ -34,6 +34,10 @@ const optimalPath = function(from, to) {
while (current[0] === target[0]) {
current.shift()
target.shift()
+ // Handle case where target is the current directory
+ if (current.length === 0 && target.length === 0) {
+ return '.'
+ }
}
const relativePath = current.fill('..').concat(target)
const absolutePath = to.split('/')
diff --git a/src/helpers/links.js b/src/helpers/links.js
index 007c9f791d1..226dabbd72c 100644
--- a/src/helpers/links.js
+++ b/src/helpers/links.js
@@ -61,8 +61,14 @@ const domHref = function(node) {
const [, relPath, id] = match
const currentDir = basedir(OCA.Viewer.file)
const dir = absolutePath(currentDir, basedir(relPath))
- return generateUrl(`/apps/files/?dir=${dir}&openfile=${id}#relPath=${relPath}`)
+ if (relPath.length > 1 && relPath.endsWith('/')) {
+ // is directory
+ return generateUrl(`/apps/files/?dir=${dir}&fileId=${id}`)
+ } else {
+ return generateUrl(`/apps/files/?dir=${dir}&openfile=${id}#relPath=${relPath}`)
+ }
}
+ return ref
}
const parseHref = function(dom) {
@@ -97,7 +103,7 @@ const openLink = function(event, _attrs) {
}
if (query.fileId) {
// open the direct file link
- window.open(generateUrl(`/f/${query.fileId}`))
+ window.open(generateUrl(`/f/${query.fileId}`), '_self')
return
}
if (!markdownit.validateLink(htmlHref)) {
diff --git a/src/views/RichWorkspace.vue b/src/views/RichWorkspace.vue
index 75afe2e2d03..308557dc61d 100644
--- a/src/views/RichWorkspace.vue
+++ b/src/views/RichWorkspace.vue
@@ -186,7 +186,7 @@ export default {
overflow: scroll !important;
max-height: calc(40vh - 50px);
padding-left: 10px;
- padding-bottom: 60px; /* ensure menububble fits below */
+ padding-bottom: 10px;
}
#rich-workspace::v-deep .text-editor__wrapper .ProseMirror {