fix(editor): use manual input prompt instead of window.prompt
continuous-integration/drone/push Build is passing Details

Resolves vikunja/desktop#184
This commit is contained in:
kolaente 2024-01-21 20:08:10 +01:00
parent 8ea97f3ffc
commit 57c99a22a0
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
4 changed files with 76 additions and 54 deletions

View File

@ -336,6 +336,7 @@ import {ref} from 'vue'
import {Editor} from '@tiptap/vue-3' import {Editor} from '@tiptap/vue-3'
import BaseButton from '@/components/base/BaseButton.vue' import BaseButton from '@/components/base/BaseButton.vue'
import {setLinkInEditor} from '@/components/input/editor/setLinkInEditor'
const { const {
editor = null, editor = null,
@ -353,29 +354,8 @@ function openImagePicker() {
document.getElementById('tiptap__image-upload').click() document.getElementById('tiptap__image-upload').click()
} }
function setLink() { function setLink(event) {
const previousUrl = editor.getAttributes('link').href setLinkInEditor(event.target.getBoundingClientRect(), editor)
const url = window.prompt('URL', previousUrl)
// cancelled
if (url === null) {
return
}
// empty
if (url === '') {
editor.chain().focus().extendMarkRange('link').unsetLink().run()
return
}
// update link
editor
.chain()
.focus()
.extendMarkRange('link')
.setLink({href: url, target: '_blank'})
.run()
} }
</script> </script>

View File

@ -174,6 +174,8 @@ import {Placeholder} from '@tiptap/extension-placeholder'
import {eventToHotkeyString} from '@github/hotkey' import {eventToHotkeyString} from '@github/hotkey'
import {mergeAttributes} from '@tiptap/core' import {mergeAttributes} from '@tiptap/core'
import {isEditorContentEmpty} from '@/helpers/editorContentEmpty' import {isEditorContentEmpty} from '@/helpers/editorContentEmpty'
import inputPrompt from '@/helpers/inputPrompt'
import {setLinkInEditor} from '@/components/input/editor/setLinkInEditor'
const tiptapInstanceRef = ref<HTMLInputElement | null>(null) const tiptapInstanceRef = ref<HTMLInputElement | null>(null)
@ -320,7 +322,7 @@ const editor = useEditor({
addKeyboardShortcuts() { addKeyboardShortcuts() {
return { return {
'Mod-Enter': () => { 'Mod-Enter': () => {
if(contentHasChanged.value) { if (contentHasChanged.value) {
bubbleSave() bubbleSave()
} }
}, },
@ -470,7 +472,7 @@ function uploadAndInsertFiles(files: File[] | FileList) {
}) })
} }
function addImage() { async function addImage(event) {
if (typeof uploadCallback !== 'undefined') { if (typeof uploadCallback !== 'undefined') {
const files = uploadInputRef.value?.files const files = uploadInputRef.value?.files
@ -484,7 +486,7 @@ function addImage() {
return return
} }
const url = window.prompt('URL') const url = await inputPrompt(event.target.getBoundingClientRect())
if (url) { if (url) {
editor.value?.chain().focus().setImage({src: url}).run() editor.value?.chain().focus().setImage({src: url}).run()
@ -492,34 +494,8 @@ function addImage() {
} }
} }
function setLink() { function setLink(event) {
const previousUrl = editor.value?.getAttributes('link').href setLinkInEditor(event.target.getBoundingClientRect(), editor.value)
const url = window.prompt('URL', previousUrl)
// cancelled
if (url === null) {
return
}
// empty
if (url === '') {
editor.value
?.chain()
.focus()
.extendMarkRange('link')
.unsetLink()
.run()
return
}
// update link
editor.value
?.chain()
.focus()
.extendMarkRange('link')
.setLink({href: url, target: '_blank'})
.run()
} }
onMounted(async () => { onMounted(async () => {
@ -573,6 +549,7 @@ function setFocusToEditor(event) {
event.target.contentEditable === 'true') { event.target.contentEditable === 'true') {
return return
} }
event.preventDefault() event.preventDefault()
if (!isEditing.value && isEditEnabled) { if (!isEditing.value && isEditEnabled) {

View File

@ -0,0 +1,26 @@
import inputPrompt from '@/helpers/inputPrompt'
export async function setLinkInEditor(pos, editor) {
const previousUrl = editor?.getAttributes('link').href || ''
const url = await inputPrompt(pos, previousUrl)
// empty
if (url === '') {
editor
?.chain()
.focus()
.extendMarkRange('link')
.unsetLink()
.run()
return
}
// update link
editor
?.chain()
.focus()
.extendMarkRange('link')
.setLink({href: url, target: '_blank'})
.run()
}

View File

@ -0,0 +1,39 @@
import {createRandomID} from '@/helpers/randomId'
import tippy from 'tippy.js'
import {nextTick} from 'vue'
import {eventToHotkeyString} from '@github/hotkey'
export default function inputPrompt(pos: ClientRect, oldValue: string = ''): Promise<string> {
return new Promise((resolve) => {
const id = 'link-input-' + createRandomID()
const linkPopup = tippy('body', {
getReferenceClientRect: () => pos,
appendTo: () => document.body,
content: `<div><input class="input" placeholder="URL" id="${id}" value="${oldValue}"/></div>`,
showOnCreate: true,
interactive: true,
trigger: 'manual',
placement: 'top-start',
allowHTML: true,
})
linkPopup[0].show()
nextTick(() => document.getElementById(id)?.focus())
document.getElementById(id)?.addEventListener('keydown', event => {
const hotkeyString = eventToHotkeyString(event)
if (hotkeyString !== 'Enter') {
return
}
const url = event.target.value
resolve(url)
linkPopup[0].hide()
})
})
}