diff --git a/src/muya/lib/assets/pngicon/imageOpen/1.png b/src/muya/lib/assets/pngicon/imageOpen/1.png new file mode 100644 index 00000000..e0f762bb Binary files /dev/null and b/src/muya/lib/assets/pngicon/imageOpen/1.png differ diff --git a/src/muya/lib/assets/pngicon/imageOpen/2.png b/src/muya/lib/assets/pngicon/imageOpen/2.png new file mode 100644 index 00000000..e00849c0 Binary files /dev/null and b/src/muya/lib/assets/pngicon/imageOpen/2.png differ diff --git a/src/muya/lib/assets/pngicon/imageOpen/3.png b/src/muya/lib/assets/pngicon/imageOpen/3.png new file mode 100644 index 00000000..dcb7592c Binary files /dev/null and b/src/muya/lib/assets/pngicon/imageOpen/3.png differ diff --git a/src/muya/lib/config/index.js b/src/muya/lib/config/index.js index 815f5bcf..8536b6e8 100644 --- a/src/muya/lib/config/index.js +++ b/src/muya/lib/config/index.js @@ -280,6 +280,8 @@ export const MUYA_DEFAULT_OPTION = Object.freeze({ imageAction: null, // Call Electron open dialog or input element type is file. imagePathPicker: null, + // Call Electron openPath to open image file with external tool. + openImageWithExternalTool: null, clipboardFilePath: () => {}, // image path auto completed when you input in image selector. imagePathAutoComplete: () => [], diff --git a/src/muya/lib/contentState/imageCtrl.js b/src/muya/lib/contentState/imageCtrl.js index 25af86cb..f72727a1 100644 --- a/src/muya/lib/contentState/imageCtrl.js +++ b/src/muya/lib/contentState/imageCtrl.js @@ -1,5 +1,6 @@ import { URL_REG, DATA_URL_REG } from '../config' import { correctImageSrc } from '../utils/getImageInfo' +import { fileURLToPath } from 'url' const imageCtrl = ContentState => { /** @@ -204,6 +205,19 @@ const imageCtrl = ContentState => { return this.singleRender(outMostBlock, true) } + + ContentState.prototype.openImage = function ({ key, absoluteImagePath }) { + const block = this.getBlock(key) + const { eventCenter } = this.muya + if (this.muya.options.openImageWithExternalTool) { + const path = fileURLToPath(absoluteImagePath) + this.muya.options.openImageWithExternalTool(path) + this.singleRender(block) + eventCenter.dispatch('muya-transformer', { reference: null }) + eventCenter.dispatch('muya-image-toolbar', { reference: null }) + this.muya.dispatchChange() + } + } } export default imageCtrl diff --git a/src/muya/lib/ui/imageToolbar/config.js b/src/muya/lib/ui/imageToolbar/config.js index 3c06fbdb..b61afa30 100644 --- a/src/muya/lib/ui/imageToolbar/config.js +++ b/src/muya/lib/ui/imageToolbar/config.js @@ -1,4 +1,5 @@ import editIcon from '../../assets/pngicon/imageEdit/2.png' +import openIcon from '../../assets/pngicon/imageOpen/2.png' import inlineIcon from '../../assets/pngicon/inline_image/2.png' import leftIcon from '../../assets/pngicon/algin_left/2.png' import middleIcon from '../../assets/pngicon/algin_center/2.png' @@ -11,6 +12,11 @@ const icons = [ tooltip: 'Edit Image', icon: editIcon }, + { + type: 'open', + tooltip: 'Open Image', + icon: openIcon + }, { type: 'inline', tooltip: 'Inline Image', diff --git a/src/muya/lib/ui/imageToolbar/index.css b/src/muya/lib/ui/imageToolbar/index.css index 76a717b5..740c5a2a 100644 --- a/src/muya/lib/ui/imageToolbar/index.css +++ b/src/muya/lib/ui/imageToolbar/index.css @@ -66,15 +66,25 @@ } .ag-image-toolbar li.item.edit { + margin-right: 8px; +} + +.ag-image-toolbar li.item.open.enable { margin-right: 21px; - margin-left: 10px; + margin-left: 0px; +} + +.ag-image-toolbar li.item.open.disable { + margin-right: 21px; + margin-left: 0px; + opacity: 0.4; } .ag-image-toolbar li.item.inline { margin-right: 8px; } -.ag-image-toolbar li.item:first-of-type:before { +.ag-image-toolbar li.item:nth-of-type(2):before { content: ''; width: 1px; position: absolute; diff --git a/src/muya/lib/ui/imageToolbar/index.js b/src/muya/lib/ui/imageToolbar/index.js index 4e1ab9a5..3159806d 100644 --- a/src/muya/lib/ui/imageToolbar/index.js +++ b/src/muya/lib/ui/imageToolbar/index.js @@ -1,6 +1,7 @@ import BaseFloat from '../baseFloat' import { patch, h } from '../../parser/render/snabbdom' import icons from './config' +import { URL_REG } from '../../config' import './index.css' @@ -53,6 +54,10 @@ class ImageToolbar extends BaseFloat { const { icons, oldVnode, toolbarContainer, imageInfo } = this const { attrs } = imageInfo.token const dataAlign = attrs['data-align'] + let isLocalImage = false + if (this.isLocalFile(imageInfo)) { + isLocalImage = true + } const children = icons.map(i => { let icon let iconWrapperSelector @@ -69,6 +74,13 @@ class ImageToolbar extends BaseFloat { const iconWrapper = h(iconWrapperSelector, icon) let itemSelector = `li.item.${i.type}` + if (i.type === 'open') { + if (isLocalImage) { + itemSelector += '.enable' + } else { + itemSelector += '.disable' + } + } if (i.type === dataAlign || !dataAlign && i.type === 'inline') { itemSelector += '.active' } @@ -99,6 +111,10 @@ class ImageToolbar extends BaseFloat { event.stopPropagation() const { imageInfo } = this + let isLocalImage = false + if (this.isLocalFile(imageInfo)) { + isLocalImage = true + } switch (item.type) { // Delete image. case 'delete': @@ -135,8 +151,22 @@ class ImageToolbar extends BaseFloat { this.muya.contentState.updateImage(this.imageInfo, 'data-align', item.type) return this.hide() } + case 'open': { + if (isLocalImage) { + this.muya.contentState.openImage(this.imageInfo) + this.hide() + } + } } } + + isLocalFile (imageInfo) { + const { attrs } = imageInfo.token + if (URL_REG.test(imageInfo.token.src) || URL_REG.test(attrs.src)) { + return false + } + return true + } } export default ImageToolbar diff --git a/src/muya/lib/utils/getImageInfo.js b/src/muya/lib/utils/getImageInfo.js index 22d54795..968a1806 100644 --- a/src/muya/lib/utils/getImageInfo.js +++ b/src/muya/lib/utils/getImageInfo.js @@ -12,10 +12,13 @@ export const getImageInfo = image => { start: offset, end: offset + raw.length } + const imageContainer = image.querySelector('.ag-image-container') + const absoluteImagePath = imageContainer.firstChild.currentSrc return { key: paragraph.id, token, - imageId: image.id + imageId: image.id, + absoluteImagePath: absoluteImagePath } } diff --git a/src/renderer/components/editorWithTabs/editor.vue b/src/renderer/components/editorWithTabs/editor.vue index 0b407039..811e7aa7 100644 --- a/src/renderer/components/editorWithTabs/editor.vue +++ b/src/renderer/components/editorWithTabs/editor.vue @@ -533,6 +533,7 @@ export default { spellcheckEnabled: spellcheckerEnabled, imageAction: this.imageAction.bind(this), imagePathPicker: this.imagePathPicker.bind(this), + openImageWithExternalTool: this.openImageWithExternalTool.bind(this), clipboardFilePath: guessClipboardFilePath, imagePathAutoComplete: this.imagePathAutoComplete.bind(this) } @@ -775,6 +776,10 @@ export default { return this.$store.dispatch('ASK_FOR_IMAGE_PATH') }, + openImageWithExternalTool (absoluteImagePath) { + return shell.openPath(absoluteImagePath) + }, + keyup (event) { if (event.key === 'Escape') { this.setImageViewerVisible(false)