diff --git a/docs/changelog.md b/docs/changelog.md index 4402d20f..e3cfb777 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -6,6 +6,8 @@ Here are the most notable changes in each release. For a more detailed list of c ## 2.1.0 (not yet released) - Added support for moving the current block to another (or new) buffer. Pressing `Ctrl/Cmd+S` will now pop up a dialog where you can search for and select another buffer to which the block will be moved. It's also possible to select to create a brand new buffer to which the block will be moved. +- Add right click context menu with undo/redo/cut/copy/paste/select all as well as Delete Block and Move block to another buffer. +- Add File menu item for switching buffer - When deleting a block, the cursor will now end up at the beginning of the next block, instead of at the end of the previous block. - Added support for the following languages: * Elixir diff --git a/electron/main/index.ts b/electron/main/index.ts index a2fefbc1..32effaa2 100644 --- a/electron/main/index.ts +++ b/electron/main/index.ts @@ -5,7 +5,7 @@ import fs from "fs" import { WINDOW_CLOSE_EVENT, SETTINGS_CHANGE_EVENT } from '@/src/common/constants' -import { menu, getTrayMenu } from './menu' +import { menu, getTrayMenu, getEditorContextMenu } from './menu' import CONFIG from "../config" import { isDev, isLinux, isMac, isWindows } from '../detect-platform'; import { initializeAutoUpdate, checkForUpdates } from './auto-update'; @@ -376,6 +376,10 @@ ipcMain.handle("setWindowTitle", (event, title) => { win?.setTitle(title) }) +ipcMain.handle("showEditorContextMenu", () => { + getEditorContextMenu(win).popup({window:win}); +}) + // Initialize note/file library async function initFileLibrary(win) { await migrateBufferFileToLibrary(app) diff --git a/electron/main/menu.js b/electron/main/menu.js index 2e8a54b8..353c2fee 100644 --- a/electron/main/menu.js +++ b/electron/main/menu.js @@ -1,10 +1,51 @@ const { app, Menu } = require("electron") -import { OPEN_SETTINGS_EVENT, REDO_EVENT, MOVE_BLOCK_EVENT } from '@/src/common/constants' +import { OPEN_SETTINGS_EVENT, UNDO_EVENT, REDO_EVENT, MOVE_BLOCK_EVENT, DELETE_BLOCK_EVENT, CHANGE_BUFFER_EVENT } from '@/src/common/constants' import { openAboutWindow } from "./about"; import { quit } from "./index" const isMac = process.platform === "darwin" + +const undoMenuItem = { + label: 'Undo', + accelerator: 'CommandOrControl+z', + click: (menuItem, window, event) => { + window?.webContents.send(UNDO_EVENT) + }, +} + +const redoMenuItem = { + label: 'Redo', + accelerator: 'CommandOrControl+Shift+z', + click: (menuItem, window, event) => { + window?.webContents.send(REDO_EVENT) + }, +} + +const deleteBlockMenuItem = { + label: 'Delete block', + accelerator: 'CommandOrControl+Shift+D', + click: (menuItem, window, event) => { + window?.webContents.send(DELETE_BLOCK_EVENT) + }, +} + +const moveBlockMenuItem = { + label: 'Move block to another buffer…', + accelerator: 'CommandOrControl+S', + click: (menuItem, window, event) => { + window?.webContents.send(MOVE_BLOCK_EVENT) + }, +} + +const changeBufferMenuItem = { + label: 'Switch buffer…', + accelerator: 'CommandOrControl+P', + click: (menuItem, window, event) => { + window?.webContents.send(CHANGE_BUFFER_EVENT) + }, +} + const template = [ // { role: 'appMenu' } ...(isMac ? [{ @@ -18,6 +59,7 @@ const template = [ }, }, { type: 'separator' }, + changeBufferMenuItem, { label: 'Settings', click: (menuItem, window, event) => { @@ -37,6 +79,7 @@ const template = [ }] : [{ role: 'fileMenu', submenu: [ + changeBufferMenuItem, { label: 'Settings', click: (menuItem, window, event) => { @@ -62,22 +105,11 @@ const template = [ { label: 'Edit', submenu: [ - { role: 'undo' }, - { - label: 'Redo', - accelerator: 'CommandOrControl+Shift+z', - click: (menuItem, window, event) => { - window?.webContents.send(REDO_EVENT) - }, - }, + undoMenuItem, + redoMenuItem, { type: 'separator' }, - { - label: 'Move block to another buffer...', - accelerator: 'CommandOrControl+S', - click: (menuItem, window, event) => { - window?.webContents.send(MOVE_BLOCK_EVENT) - }, - }, + deleteBlockMenuItem, + moveBlockMenuItem, { type: 'separator' }, { role: 'cut' }, { role: 'copy' }, @@ -185,3 +217,18 @@ export function getTrayMenu(win) { ]) } +export function getEditorContextMenu(win) { + return Menu.buildFromTemplate([ + undoMenuItem, + redoMenuItem, + {type: 'separator'}, + {role: 'cut'}, + {role: 'copy'}, + {role: 'paste'}, + {type: 'separator'}, + {role: 'selectAll'}, + {type: 'separator'}, + deleteBlockMenuItem, + moveBlockMenuItem, + ]) +} diff --git a/electron/preload/index.js b/electron/preload/index.js index 31e2a1e8..ce2aae80 100644 --- a/electron/preload/index.js +++ b/electron/preload/index.js @@ -48,6 +48,10 @@ contextBridge.exposeInMainWorld("heynote", { off(event, callback) { ipcRenderer.off(event, callback) }, + + invoke(event, ...args) { + return ipcRenderer.invoke(event, ...args) + } }, buffer: { diff --git a/src/common/constants.js b/src/common/constants.js index 7d8e3f99..90d9ac03 100644 --- a/src/common/constants.js +++ b/src/common/constants.js @@ -5,7 +5,10 @@ export const WINDOW_CLOSE_EVENT = "window-close" export const OPEN_SETTINGS_EVENT = "open-settings" export const SETTINGS_CHANGE_EVENT = "settings-change" export const REDO_EVENT = "redo" +export const UNDO_EVENT = "undo" export const MOVE_BLOCK_EVENT = "move-block" +export const DELETE_BLOCK_EVENT = "delete-block" +export const CHANGE_BUFFER_EVENT = "change-buffer" export const UPDATE_AVAILABLE_EVENT = "update-available" export const UPDATE_NOT_AVAILABLE_EVENT = "update-not-available" diff --git a/src/components/App.vue b/src/components/App.vue index 8bb24370..fa208140 100644 --- a/src/components/App.vue +++ b/src/components/App.vue @@ -7,7 +7,7 @@ import { useSettingsStore } from "../stores/settings-store" import { useEditorCacheStore } from '../stores/editor-cache' - import { OPEN_SETTINGS_EVENT, MOVE_BLOCK_EVENT } from '@/src/common/constants' + import { OPEN_SETTINGS_EVENT, MOVE_BLOCK_EVENT, CHANGE_BUFFER_EVENT } from '@/src/common/constants' import StatusBar from './StatusBar.vue' import Editor from './Editor.vue' @@ -48,6 +48,10 @@ window.heynote.mainProcess.on(MOVE_BLOCK_EVENT, (path) => { this.openMoveToBufferSelector() }) + + window.heynote.mainProcess.on(CHANGE_BUFFER_EVENT, () => { + this.openBufferSelector() + }) }, beforeUnmount() { diff --git a/src/components/Editor.vue b/src/components/Editor.vue index d661a0dd..9dfde363 100644 --- a/src/components/Editor.vue +++ b/src/components/Editor.vue @@ -5,7 +5,7 @@ import { useErrorStore } from "../stores/error-store" import { useHeynoteStore } from "../stores/heynote-store.js" import { useEditorCacheStore } from "../stores/editor-cache" - import { REDO_EVENT, WINDOW_CLOSE_EVENT } from '@/src/common/constants'; + import { REDO_EVENT, WINDOW_CLOSE_EVENT, DELETE_BLOCK_EVENT, UNDO_EVENT } from '@/src/common/constants'; const NUM_EDITOR_INSTANCES = 5 @@ -22,7 +22,6 @@ syntaxTreeDebugContent: null, editor: null, onWindowClose: null, - onRedo: null, } }, @@ -38,15 +37,25 @@ [this.editor.path, this.editor.getContent()], ]) } + window.heynote.mainProcess.on(WINDOW_CLOSE_EVENT, this.onWindowClose) - this.onRedo = () => { + window.heynote.mainProcess.on(UNDO_EVENT, () => { + if (this.editor) { + toRaw(this.editor).undo() + } + }) + + window.heynote.mainProcess.on(REDO_EVENT, () => { if (this.editor) { toRaw(this.editor).redo() } - } + }) - window.heynote.mainProcess.on(WINDOW_CLOSE_EVENT, this.onWindowClose) - window.heynote.mainProcess.on(REDO_EVENT, this.onRedo) + window.heynote.mainProcess.on(DELETE_BLOCK_EVENT, () => { + if (this.editor) { + toRaw(this.editor).deleteActiveBlock() + } + }) // if debugSyntaxTree prop is set, display syntax tree for debugging if (this.debugSyntaxTree) { @@ -70,7 +79,9 @@ beforeUnmount() { window.heynote.mainProcess.off(WINDOW_CLOSE_EVENT, this.onWindowClose) - window.heynote.mainProcess.off(REDO_EVENT, this.onRedo) + window.heynote.mainProcess.off(UNDO_EVENT) + window.heynote.mainProcess.off(REDO_EVENT) + window.heynote.mainProcess.off(DELETE_BLOCK_EVENT) this.editorCacheStore.tearDown(); }, @@ -138,13 +149,18 @@ focus() { toRaw(this.editor).focus() }, + + onContextMenu(event) { + event.preventDefault() + window.heynote.mainProcess.invoke("showEditorContextMenu") + }, }, }