This commit is contained in:
Kiyoka Nishiyama 2024-06-14 09:39:29 +00:00 committed by GitHub
commit d60f6eb93b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 73 additions and 3 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -280,6 +280,8 @@ export const MUYA_DEFAULT_OPTION = Object.freeze({
imageAction: null, imageAction: null,
// Call Electron open dialog or input element type is file. // Call Electron open dialog or input element type is file.
imagePathPicker: null, imagePathPicker: null,
// Call Electron openPath to open image file with external tool.
openImageWithExternalTool: null,
clipboardFilePath: () => {}, clipboardFilePath: () => {},
// image path auto completed when you input in image selector. // image path auto completed when you input in image selector.
imagePathAutoComplete: () => [], imagePathAutoComplete: () => [],

View File

@ -1,5 +1,6 @@
import { URL_REG, DATA_URL_REG } from '../config' import { URL_REG, DATA_URL_REG } from '../config'
import { correctImageSrc } from '../utils/getImageInfo' import { correctImageSrc } from '../utils/getImageInfo'
import { fileURLToPath } from 'url'
const imageCtrl = ContentState => { const imageCtrl = ContentState => {
/** /**
@ -204,6 +205,19 @@ const imageCtrl = ContentState => {
return this.singleRender(outMostBlock, true) 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 export default imageCtrl

View File

@ -1,4 +1,5 @@
import editIcon from '../../assets/pngicon/imageEdit/2.png' 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 inlineIcon from '../../assets/pngicon/inline_image/2.png'
import leftIcon from '../../assets/pngicon/algin_left/2.png' import leftIcon from '../../assets/pngicon/algin_left/2.png'
import middleIcon from '../../assets/pngicon/algin_center/2.png' import middleIcon from '../../assets/pngicon/algin_center/2.png'
@ -11,6 +12,11 @@ const icons = [
tooltip: 'Edit Image', tooltip: 'Edit Image',
icon: editIcon icon: editIcon
}, },
{
type: 'open',
tooltip: 'Open Image',
icon: openIcon
},
{ {
type: 'inline', type: 'inline',
tooltip: 'Inline Image', tooltip: 'Inline Image',

View File

@ -66,15 +66,25 @@
} }
.ag-image-toolbar li.item.edit { .ag-image-toolbar li.item.edit {
margin-right: 8px;
}
.ag-image-toolbar li.item.open.enable {
margin-right: 21px; 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 { .ag-image-toolbar li.item.inline {
margin-right: 8px; margin-right: 8px;
} }
.ag-image-toolbar li.item:first-of-type:before { .ag-image-toolbar li.item:nth-of-type(2):before {
content: ''; content: '';
width: 1px; width: 1px;
position: absolute; position: absolute;

View File

@ -1,6 +1,7 @@
import BaseFloat from '../baseFloat' import BaseFloat from '../baseFloat'
import { patch, h } from '../../parser/render/snabbdom' import { patch, h } from '../../parser/render/snabbdom'
import icons from './config' import icons from './config'
import { URL_REG } from '../../config'
import './index.css' import './index.css'
@ -53,6 +54,10 @@ class ImageToolbar extends BaseFloat {
const { icons, oldVnode, toolbarContainer, imageInfo } = this const { icons, oldVnode, toolbarContainer, imageInfo } = this
const { attrs } = imageInfo.token const { attrs } = imageInfo.token
const dataAlign = attrs['data-align'] const dataAlign = attrs['data-align']
let isLocalImage = false
if (this.isLocalFile(imageInfo)) {
isLocalImage = true
}
const children = icons.map(i => { const children = icons.map(i => {
let icon let icon
let iconWrapperSelector let iconWrapperSelector
@ -69,6 +74,13 @@ class ImageToolbar extends BaseFloat {
const iconWrapper = h(iconWrapperSelector, icon) const iconWrapper = h(iconWrapperSelector, icon)
let itemSelector = `li.item.${i.type}` 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') { if (i.type === dataAlign || !dataAlign && i.type === 'inline') {
itemSelector += '.active' itemSelector += '.active'
} }
@ -99,6 +111,10 @@ class ImageToolbar extends BaseFloat {
event.stopPropagation() event.stopPropagation()
const { imageInfo } = this const { imageInfo } = this
let isLocalImage = false
if (this.isLocalFile(imageInfo)) {
isLocalImage = true
}
switch (item.type) { switch (item.type) {
// Delete image. // Delete image.
case 'delete': case 'delete':
@ -135,8 +151,22 @@ class ImageToolbar extends BaseFloat {
this.muya.contentState.updateImage(this.imageInfo, 'data-align', item.type) this.muya.contentState.updateImage(this.imageInfo, 'data-align', item.type)
return this.hide() 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 export default ImageToolbar

View File

@ -12,10 +12,13 @@ export const getImageInfo = image => {
start: offset, start: offset,
end: offset + raw.length end: offset + raw.length
} }
const imageContainer = image.querySelector('.ag-image-container')
const absoluteImagePath = imageContainer.firstChild.currentSrc
return { return {
key: paragraph.id, key: paragraph.id,
token, token,
imageId: image.id imageId: image.id,
absoluteImagePath: absoluteImagePath
} }
} }

View File

@ -533,6 +533,7 @@ export default {
spellcheckEnabled: spellcheckerEnabled, spellcheckEnabled: spellcheckerEnabled,
imageAction: this.imageAction.bind(this), imageAction: this.imageAction.bind(this),
imagePathPicker: this.imagePathPicker.bind(this), imagePathPicker: this.imagePathPicker.bind(this),
openImageWithExternalTool: this.openImageWithExternalTool.bind(this),
clipboardFilePath: guessClipboardFilePath, clipboardFilePath: guessClipboardFilePath,
imagePathAutoComplete: this.imagePathAutoComplete.bind(this) imagePathAutoComplete: this.imagePathAutoComplete.bind(this)
} }
@ -775,6 +776,10 @@ export default {
return this.$store.dispatch('ASK_FOR_IMAGE_PATH') return this.$store.dispatch('ASK_FOR_IMAGE_PATH')
}, },
openImageWithExternalTool (absoluteImagePath) {
return shell.openPath(absoluteImagePath)
},
keyup (event) { keyup (event) {
if (event.key === 'Escape') { if (event.key === 'Escape') {
this.setImageViewerVisible(false) this.setImageViewerVisible(false)