From afc90bf61a2ce8c246e6f4176fb40f9011db6fe2 Mon Sep 17 00:00:00 2001 From: erseco Date: Sat, 26 Sep 2026 07:02:26 +0100 Subject: [PATCH] fix(editor): make Ctrl/Cmd+S save from inside the embedded editor The injected bridge swallows the shortcut and posts REQUEST_SAVE to the parent, but nothing in the view page listened, so the keystroke was a no-op. EditorEmbed now re-emits it as save-requested and ElpxViewPage runs the same save as the button, guarded by writability and an in-flight save. --- src/view/EditorEmbed.vue | 7 ++++++- src/view/ElpxViewPage.vue | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/view/EditorEmbed.vue b/src/view/EditorEmbed.vue index b3733a9..011a99b 100644 --- a/src/view/EditorEmbed.vue +++ b/src/view/EditorEmbed.vue @@ -37,7 +37,7 @@ export default defineComponent({ file: { type: Object as () => FileMeta, required: true }, editorIframeUrl: { type: String, required: true }, }, - emits: ['file-renamed'], + emits: ['file-renamed', 'save-requested'], data() { return { state: 'loading' as State, @@ -52,6 +52,11 @@ export default defineComponent({ try { const slot = this.$refs.frameSlot as HTMLElement this.frame = new EditorFrame(slot, { editorIframeUrl: this.editorIframeUrl }) + // Ctrl/Cmd+S inside the editor: the injected bridge swallows the + // keystroke and posts REQUEST_SAVE up for the page to handle. + this.frame.onMessage((message) => { + if (message.type === 'REQUEST_SAVE') this.$emit('save-requested') + }) this.status = t('exelearning', 'Loading editor…') await this.frame.load() diff --git a/src/view/ElpxViewPage.vue b/src/view/ElpxViewPage.vue index 0301b2c..c725474 100644 --- a/src/view/ElpxViewPage.vue +++ b/src/view/ElpxViewPage.vue @@ -53,7 +53,8 @@ :key="'editor-' + file.id" :file="file" :editor-iframe-url="editorIframeUrl" - @file-renamed="onFileRenamed" /> + @file-renamed="onFileRenamed" + @save-requested="canShowSaveButton && !saving && save()" />

{{ t('exelearning', 'No file selected.') }}

{{ t('exelearning', 'Back to Files') }}