feat(editor): add hotkeys to quickly edit and discard (#2265)
Reviewed-on: https://kolaente.dev/vikunja/vikunja/pulls/2265 Reviewed-by: konrad <k@knt.li>
This commit is contained in:
commit
fd66e6875c
@ -67,6 +67,7 @@
|
||||
class="tiptap__editor"
|
||||
:class="{'tiptap__editor-is-edit-enabled': isEditing}"
|
||||
:editor="editor"
|
||||
@dblclick="setEditIfApplicable()"
|
||||
@click="focusIfEditing()"
|
||||
/>
|
||||
|
||||
@ -171,7 +172,7 @@ import {OrderedList} from '@tiptap/extension-ordered-list'
|
||||
import {Paragraph} from '@tiptap/extension-paragraph'
|
||||
import {Strike} from '@tiptap/extension-strike'
|
||||
import {Text} from '@tiptap/extension-text'
|
||||
import {BubbleMenu, EditorContent, useEditor} from '@tiptap/vue-3'
|
||||
import {BubbleMenu, EditorContent, type Extensions, useEditor} from '@tiptap/vue-3'
|
||||
import {Node} from '@tiptap/pm/model'
|
||||
|
||||
import Commands from './commands'
|
||||
@ -189,7 +190,7 @@ import BaseButton from '@/components/base/BaseButton.vue'
|
||||
import XButton from '@/components/input/button.vue'
|
||||
import {Placeholder} from '@tiptap/extension-placeholder'
|
||||
import {eventToHotkeyString} from '@github/hotkey'
|
||||
import {mergeAttributes} from '@tiptap/core'
|
||||
import {Extension, mergeAttributes} from '@tiptap/core'
|
||||
import {isEditorContentEmpty} from '@/helpers/editorContentEmpty'
|
||||
import inputPrompt from '@/helpers/inputPrompt'
|
||||
import {setLinkInEditor} from '@/components/input/editor/setLinkInEditor'
|
||||
@ -202,6 +203,7 @@ const {
|
||||
showSave = false,
|
||||
placeholder = '',
|
||||
editShortcut = '',
|
||||
enableDiscardShortcut = false,
|
||||
} = defineProps<{
|
||||
modelValue: string,
|
||||
uploadCallback?: UploadCallback,
|
||||
@ -210,6 +212,7 @@ const {
|
||||
showSave?: boolean,
|
||||
placeholder?: string,
|
||||
editShortcut?: string,
|
||||
enableDiscardShortcut?: boolean,
|
||||
}>()
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'save'])
|
||||
@ -311,6 +314,8 @@ const internalMode = ref<Mode>('preview')
|
||||
const isEditing = computed(() => internalMode.value === 'edit' && isEditEnabled)
|
||||
const contentHasChanged = ref<boolean>(false)
|
||||
|
||||
let lastSavedState = modelValue
|
||||
|
||||
watch(
|
||||
() => internalMode.value,
|
||||
mode => {
|
||||
@ -320,10 +325,7 @@ watch(
|
||||
},
|
||||
)
|
||||
|
||||
const editor = useEditor({
|
||||
// eslint-disable-next-line vue/no-ref-object-destructure
|
||||
editable: isEditing.value,
|
||||
extensions: [
|
||||
const extensions : Extensions = [
|
||||
// Starterkit:
|
||||
Blockquote,
|
||||
Bold,
|
||||
@ -422,7 +424,28 @@ const editor = useEditor({
|
||||
suggestion: suggestionSetup(t),
|
||||
}),
|
||||
BubbleMenu,
|
||||
],
|
||||
]
|
||||
|
||||
// Add a custom extension for the Escape key
|
||||
if (enableDiscardShortcut) {
|
||||
extensions.push(Extension.create({
|
||||
name: 'escapeKey',
|
||||
|
||||
addKeyboardShortcuts() {
|
||||
return {
|
||||
'Escape': () => {
|
||||
exitEditMode()
|
||||
return true
|
||||
},
|
||||
}
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
const editor = useEditor({
|
||||
// eslint-disable-next-line vue/no-ref-object-destructure
|
||||
editable: isEditing.value,
|
||||
extensions: extensions,
|
||||
onUpdate: () => {
|
||||
bubbleNow()
|
||||
},
|
||||
@ -461,12 +484,27 @@ function bubbleNow() {
|
||||
|
||||
function bubbleSave() {
|
||||
bubbleNow()
|
||||
emit('save', editor.value?.getHTML())
|
||||
lastSavedState = editor.value?.getHTML() ?? ''
|
||||
emit('save', lastSavedState)
|
||||
if (isEditing.value) {
|
||||
internalMode.value = 'preview'
|
||||
}
|
||||
}
|
||||
|
||||
function exitEditMode() {
|
||||
editor.value?.commands.setContent(lastSavedState, false)
|
||||
if (isEditing.value) {
|
||||
internalMode.value = 'preview'
|
||||
}
|
||||
}
|
||||
|
||||
function setEditIfApplicable() {
|
||||
if (!isEditEnabled) return
|
||||
if (isEditing.value) return
|
||||
|
||||
setEdit()
|
||||
}
|
||||
|
||||
function setEdit(focus: boolean = true) {
|
||||
internalMode.value = 'edit'
|
||||
if (focus) {
|
||||
|
@ -85,6 +85,7 @@
|
||||
:upload-enabled="true"
|
||||
:bottom-actions="actions[c.id]"
|
||||
:show-save="true"
|
||||
:enable-discard-shortcut="true"
|
||||
initial-mode="preview"
|
||||
@update:modelValue="
|
||||
() => {
|
||||
|
@ -30,6 +30,7 @@
|
||||
:placeholder="$t('task.description.placeholder')"
|
||||
:show-save="true"
|
||||
edit-shortcut="e"
|
||||
:enable-discard-shortcut="true"
|
||||
@update:modelValue="saveWithDelay"
|
||||
@save="save"
|
||||
/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user