fix(editor): use manual input prompt instead of window.prompt
Resolves https://kolaente.dev/vikunja/desktop/issues/184
This commit is contained in:
parent
8ea97f3ffc
commit
57c99a22a0
@ -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>
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
26
src/components/input/editor/setLinkInEditor.ts
Normal file
26
src/components/input/editor/setLinkInEditor.ts
Normal 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()
|
||||||
|
}
|
39
src/helpers/inputPrompt.ts
Normal file
39
src/helpers/inputPrompt.ts
Normal 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()
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user