Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cypress/e2e/Links.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ describe('test link marks', function () {
cy.insertLine(link)
clickLink(link)

cy.get('.link-view-bubble button[title="Remove link"]').click()
cy.get('.link-view-bubble .link-options').click()
cy.get('button').contains('Remove').click()

cy.getContent().find(`a[href*="${link}"]`).should('not.exist')
})
Expand Down
4 changes: 3 additions & 1 deletion cypress/e2e/nodes/PreviewOptions.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ describe('Preview Options', function () {
'nextcloud.com',
)
cy.get('[data-text-action-entry="insert-link-input"] button').click()
cy.get('.preview-options').click()

cy.getContent().find(`a[href*="https://nextcloud.com"]`).click()
cy.get('.link-options').click()
})

it('should render previewOptions correctly', function () {
Expand Down
130 changes: 73 additions & 57 deletions src/components/Editor/PreviewOptions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,60 @@
- SPDX-License-Identifier: AGPL-3.0-or-later
-->
<template>
<div contenteditable="false" class="preview-options-container">
<NcActions
data-text-preview-options="select"
class="preview-options"
:open.sync="open"
@open="onOpen">
<NcActions
data-text-link-options="select"
class="link-options"
:open.sync="open"
@open="onOpen">
<template #icon>
<DotsVerticalIcon :size="20" />
</template>
<NcActionCaption :name="t('text', 'Preview options')" />
<NcActionRadio
data-text-preview-option="text-only"
name="preview-option"
value="text-only"
:model-value="type"
@change="(e) => toggle(e.currentTarget.value)">
{{ t('text', 'Text only') }}
</NcActionRadio>
<NcActionRadio
data-text-preview-option="link-preview"
name="preview-option"
value="link-preview"
:model-value="type"
@change="(e) => toggle(e.currentTarget.value)">
{{ t('text', 'Show link preview') }}
</NcActionRadio>

<NcActionSeparator />

<!-- Open link -->
<NcActionButton v-if="href" close-after-click @click="openLink">
<template #icon>
<OpenIcon :size="20" />
</template>
{{ t('text', 'Open in new tab') }}
</NcActionButton>

<!-- Copy link -->
<NcActionButton v-if="href" close-after-click @click="copyLink">
<template #icon>
<CheckIcon v-if="copySuccess" :size="20" />
<NcLoadingIcon v-else-if="copyLoading" :size="20" />
<ContentCopyIcon v-else :size="20" />
</template>
{{ t('text', 'Copy link') }}
</NcActionButton>

<!-- Remove link -->
<NcActionButton close-after-click @click="deleteNode">
<template #icon>
<DotsVerticalIcon :size="20" />
<DeleteOutlineIcon :size="20" />
</template>
<NcActionCaption :name="t('text', 'Preview options')" />
<NcActionRadio
data-text-preview-option="text-only"
name="preview-option"
value="text-only"
:model-value="type"
@change="(e) => toggle(e.currentTarget.value)">
{{ t('text', 'Text only') }}
</NcActionRadio>
<NcActionRadio
data-text-preview-option="link-preview"
name="preview-option"
value="link-preview"
:model-value="type"
@change="(e) => toggle(e.currentTarget.value)">
{{ t('text', 'Show link preview') }}
</NcActionRadio>
<NcActionSeparator />
<NcActionButton v-if="href" close-after-click @click="openLink">
<template #icon>
<OpenIcon :size="20" />
</template>
{{ t('text', 'Open in new tab') }}
</NcActionButton>
<NcActionButton close-after-click @click="deleteNode">
<template #icon>
<DeleteOutlineIcon :size="20" />
</template>
{{ t('text', 'Remove link') }}
</NcActionButton>
</NcActions>
</div>
{{ t('text', 'Remove link') }}
</NcActionButton>
</NcActions>
</template>

<script>
Expand All @@ -53,24 +66,33 @@ import NcActionCaption from '@nextcloud/vue/components/NcActionCaption'
import NcActionRadio from '@nextcloud/vue/components/NcActionRadio'
import NcActions from '@nextcloud/vue/components/NcActions'
import NcActionSeparator from '@nextcloud/vue/components/NcActionSeparator'
import NcLoadingIcon from '@nextcloud/vue/components/NcLoadingIcon'
import CheckIcon from 'vue-material-design-icons/Check.vue'
import ContentCopyIcon from 'vue-material-design-icons/ContentCopy.vue'
import DotsVerticalIcon from 'vue-material-design-icons/DotsVertical.vue'
import OpenIcon from 'vue-material-design-icons/OpenInNew.vue'
import DeleteOutlineIcon from 'vue-material-design-icons/TrashCanOutline.vue'
import CopyToClipboardMixin from '../../mixins/CopyToClipboardMixin.js'

export default {
name: 'PreviewOptions',

components: {
CheckIcon,
ContentCopyIcon,
DotsVerticalIcon,
NcActions,
NcActionButton,
NcActionCaption,
NcActionRadio,
NcActionSeparator,
NcLoadingIcon,
DeleteOutlineIcon,
OpenIcon,
},

mixins: [CopyToClipboardMixin],

props: {
type: {
type: String,
Expand All @@ -88,6 +110,12 @@ export default {
}
},

computed: {
isPreview() {
return this.type === 'link-preview'
},
},

methods: {
onOpen() {
this.$emit('open')
Expand All @@ -96,13 +124,16 @@ export default {
this.open = false
this.$emit('toggle', type)
},
deleteNode() {
this.$emit('delete')
},
openLink() {
if (!this.href) return
window.open(this.href, '_blank').focus()
},
async copyLink() {
await this.copyToClipboard(this.href)
},
deleteNode() {
this.$emit('delete')
},
t,
},
}
Expand All @@ -113,19 +144,4 @@ div[contenteditable='false'] {
padding: 0;
margin: 0;
}

.preview-options-container {
position: absolute;
width: 0 !important;
left: -44px;
top: 50%;
transform: translate(0, -50%);
// Required to overlay the drag handler padding
z-index: 10000;
}

// Inside details, button needs to be shifted further
.details-content .preview-options-container {
left: calc(-44px - 24px);
}
</style>
81 changes: 25 additions & 56 deletions src/components/Link/LinkBubbleView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,6 @@
<OpenInNewIcon :size="20" />
</template>
</NcButton>
<!-- copy link -->
<NcButton
:title="copyLinkTooltip"
:aria-label="copyLinkTooltip"
type="tertiary"
@click="copyLink">
<template #icon>
<CheckIcon v-if="copySuccess" :size="20" />
<NcLoadingIcon v-else-if="copyLoading" :size="20" />
<ContentCopyIcon v-else :size="20" />
</template>
</NcButton>

<!-- edit/save -->
<div v-if="isEditable" class="edit-buttons">
Expand All @@ -55,29 +43,25 @@
<CheckIcon :size="20" />
</template>
</NcButton>

<!-- remove link / dismiss changes -->
<NcButton
v-if="!edit"
:title="t('text', 'Remove link')"
:aria-label="t('text', 'Remove link')"
type="tertiary"
@click="removeLink">
<template #icon>
<LinkOffIcon :size="20" />
</template>
</NcButton>
<NcButton
v-else
:title="t('text', 'Cancel')"
:aria-label="t('text', 'Cancel')"
type="tertiary"
@click="stopEdit">
<template #icon>
<CloseIcon :size="20" />
</template>
</NcButton>
</div>

<!-- preview options / dismiss changes -->
<PreviewOptions
v-if="isEditable && !edit"
:href="href"
type="text-only"
@toggle="setPreview"
@delete="removeLink" />
<NcButton
v-else
:title="t('text', 'Cancel')"
:aria-label="t('text', 'Cancel')"
type="tertiary"
@click="stopEdit">
<template #icon>
<CloseIcon :size="20" />
</template>
</NcButton>
</div>

<!-- link edit form -->
Expand Down Expand Up @@ -106,38 +90,33 @@
<script>
import { t } from '@nextcloud/l10n'
import NcButton from '@nextcloud/vue/components/NcButton'
import NcLoadingIcon from '@nextcloud/vue/components/NcLoadingIcon'
import NcTextField from '@nextcloud/vue/components/NcTextField'
import { NcReferenceList } from '@nextcloud/vue/dist/Components/NcRichText.js'
import CheckIcon from 'vue-material-design-icons/Check.vue'
import CloseIcon from 'vue-material-design-icons/Close.vue'
import ContentCopyIcon from 'vue-material-design-icons/ContentCopy.vue'
import LinkOffIcon from 'vue-material-design-icons/LinkOff.vue'
import OpenInNewIcon from 'vue-material-design-icons/OpenInNew.vue'
import PencilOutlineIcon from 'vue-material-design-icons/PencilOutline.vue'

import CopyToClipboardMixin from '../../mixins/CopyToClipboardMixin.js'
import { useOpenLinkHandler } from '../Editor.provider.ts'
import PreviewOptions from '../Editor/PreviewOptions.vue'

const PROTOCOLS_WITH_PREVIEW = ['http:', 'https:']

export default {
name: 'LinkBubbleView',

components: {
PreviewOptions,
CheckIcon,
CloseIcon,
ContentCopyIcon,
NcButton,
NcLoadingIcon,
NcReferenceList,
NcTextField,
LinkOffIcon,
OpenInNewIcon,
PencilOutlineIcon,
},

mixins: [CopyToClipboardMixin, useOpenLinkHandler],
mixins: [useOpenLinkHandler],

props: {
editor: {
Expand All @@ -164,16 +143,6 @@ export default {
return this.href || 'no-href'
},

copyLinkTooltip() {
if (this.copied) {
if (this.copySuccess) {
return ''
}
return t('text', 'Cannot copy, please copy the link manually')
}
return t('text', 'Copy link to clipboard')
},

/**
* NcReferenceList only accepts full URLs with origin.
*/
Expand Down Expand Up @@ -217,16 +186,16 @@ export default {
this.$openLinkHandler.openLink(href)
},

async copyLink() {
await this.copyToClipboard(this.href)
},

onReferenceListLoaded() {
this.referenceTitle =
this.$refs.referencelist.firstReference?.openGraphObject?.name
?? null
},

setPreview() {
this.editor.chain().hideLinkBubble().setPreview().run()
},

startEdit() {
this.edit = true
this.newHref = this.href
Expand Down
6 changes: 1 addition & 5 deletions src/nodes/Paragraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import TiptapParagraph from '@tiptap/extension-paragraph'
import currentLineMenu from '../plugins/currentLineMenu.js'
import previewOptions from '../plugins/previewOptions.js'

const Paragraph = TiptapParagraph.extend({
parseHTML() {
Expand Down Expand Up @@ -45,10 +44,7 @@ const Paragraph = TiptapParagraph.extend({
},

addProseMirrorPlugins() {
return [
currentLineMenu({ editor: this.editor }),
previewOptions({ editor: this.editor }),
]
return [currentLineMenu({ editor: this.editor })]
},
})

Expand Down
Loading
Loading