mirror of
https://github.com/purocean/yn.git
synced 2026-10-12 23:31:39 +08:00
refactor: 移除 bus 事件总线,使用 hook 代替
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, nextTick, onBeforeMount, onMounted, ref, toRefs, watch } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useBus } from '@fe/core/bus'
|
||||
import { registerHook, removeHook } from '@fe/core/hook'
|
||||
import { isEncrypted, saveDoc, toUri } from '@fe/services/document'
|
||||
import { whenEditorReady } from '@fe/services/editor'
|
||||
import type { Doc } from '@fe/types'
|
||||
@@ -18,7 +18,6 @@ export default defineComponent({
|
||||
components: { MonacoEditor },
|
||||
setup () {
|
||||
let editorIsReady = false
|
||||
const bus = useBus()
|
||||
const store = useStore()
|
||||
|
||||
let timer: number | null = null
|
||||
@@ -96,14 +95,14 @@ export default defineComponent({
|
||||
watch(currentContent, restartTimer)
|
||||
|
||||
onMounted(() => {
|
||||
bus.on('global.resize', resize)
|
||||
bus.on('editor.change', setCurrentValue as any)
|
||||
registerHook('GLOBAL_RESIZE', resize)
|
||||
registerHook('EDITOR_CHANGE', setCurrentValue)
|
||||
restartTimer()
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
bus.off('global.resize', resize)
|
||||
bus.off('editor.change', setCurrentValue as any)
|
||||
removeHook('GLOBAL_RESIZE', resize)
|
||||
removeHook('EDITOR_CHANGE', setCurrentValue)
|
||||
})
|
||||
|
||||
whenEditorReady().then(({ editor, monaco }) => {
|
||||
|
||||
@@ -154,7 +154,7 @@ export default defineComponent({
|
||||
return
|
||||
}
|
||||
|
||||
triggerHook('ON_DOC_BEFORE_EXPORT')
|
||||
triggerHook('DOC_BEFORE_EXPORT')
|
||||
|
||||
if (convert.toType === 'pdf') {
|
||||
exportPdf(fileName.value)
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useStore } from 'vuex'
|
||||
import { computed, defineComponent, onBeforeMount, onBeforeUnmount, ref, toRefs, watch } from 'vue'
|
||||
import { Alt, Ctrl } from '@fe/core/command'
|
||||
import type { Components, Doc } from '@fe/types'
|
||||
import { useBus } from '@fe/core/bus'
|
||||
import { registerHook, removeHook } from '@fe/core/hook'
|
||||
import { registerAction, removeAction } from '@fe/core/action'
|
||||
import { ensureCurrentFileSaved, isEncrypted, isSubOrSameFile, switchDoc, toUri } from '@fe/services/document'
|
||||
import type { AppState } from '@fe/support/store'
|
||||
@@ -20,7 +20,6 @@ export default defineComponent({
|
||||
components: { Tabs },
|
||||
setup () {
|
||||
const store = useStore()
|
||||
const bus = useBus()
|
||||
|
||||
const { currentFile, tabs } = toRefs<AppState>(store.state)
|
||||
const { isSaved } = toRefs(store.getters)
|
||||
@@ -103,11 +102,19 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
function handleDocCreated ({ doc }: { doc: Doc | null }) {
|
||||
switchFile(doc)
|
||||
}
|
||||
|
||||
function handleDocDeleted ({ doc }: { doc: Doc | null }) {
|
||||
removeFile(doc)
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
bus.on('doc.created', switchFile)
|
||||
bus.on('doc.deleted', removeFile)
|
||||
bus.on('doc.switch-failed', handleSwitchFailed)
|
||||
bus.on('doc.moved', handleMoved)
|
||||
registerHook('DOC_MOVED', handleMoved)
|
||||
registerHook('DOC_CREATED', handleDocCreated)
|
||||
registerHook('DOC_DELETED', handleDocDeleted)
|
||||
registerHook('DOC_SWITCH_FAILED', handleSwitchFailed)
|
||||
|
||||
registerAction({
|
||||
name: 'file-tabs.switch-left',
|
||||
@@ -129,10 +136,10 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
bus.off('doc.created', switchFile)
|
||||
bus.off('doc.deleted', removeFile)
|
||||
bus.off('doc.switch-failed', handleSwitchFailed)
|
||||
bus.off('doc.moved', handleMoved)
|
||||
removeHook('DOC_MOVED', handleMoved)
|
||||
removeHook('DOC_CREATED', handleDocCreated)
|
||||
removeHook('DOC_DELETED', handleDocDeleted)
|
||||
removeHook('DOC_SWITCH_FAILED', handleSwitchFailed)
|
||||
removeAction('file-tabs.switch-left')
|
||||
removeAction('file-tabs.switch-next')
|
||||
})
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, onBeforeUnmount, onMounted, ref, toRefs } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useBus } from '@fe/core/bus'
|
||||
import { triggerHook } from '@fe/core/hook'
|
||||
import { $args, FLAG_DISABLE_XTERM } from '@fe/support/args'
|
||||
import { emitResize } from '@fe/services/layout'
|
||||
import { isElectron } from '@fe/support/env'
|
||||
@@ -43,7 +43,6 @@ let resizeOrigin: any = null
|
||||
export default defineComponent({
|
||||
name: 'layout',
|
||||
setup () {
|
||||
const bus = useBus()
|
||||
const store = useStore()
|
||||
|
||||
const { showView, showXterm, showSide, showEditor, presentation } = toRefs(store.state)
|
||||
@@ -74,7 +73,7 @@ export default defineComponent({
|
||||
const height = (resizeOrigin.targetHeight + offsetY)
|
||||
ref.style.height = Math.min(resizeOrigin.max, Math.max(resizeOrigin.min, height)) + 'px'
|
||||
}
|
||||
bus.emit('global.resize')
|
||||
triggerHook('GLOBAL_RESIZE')
|
||||
}
|
||||
|
||||
function initResize (type: any, ref: any, min: any, max: any, e: any) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import type * as monaco from 'monaco-editor'
|
||||
import { defineComponent, onMounted, ref } from 'vue'
|
||||
import { defaultOptions } from '@fe/services/editor'
|
||||
import { toUri } from '@fe/services/document'
|
||||
import { useBus } from '@fe/core/bus'
|
||||
import { triggerHook } from '@fe/core/hook'
|
||||
|
||||
const models: {[key: string]: monaco.editor.ITextModel} = {}
|
||||
|
||||
@@ -19,7 +19,6 @@ export default defineComponent({
|
||||
setup () {
|
||||
let editor: monaco.editor.IStandaloneCodeEditor | null = null
|
||||
const refEditor = ref<HTMLElement | null>(null)
|
||||
const bus = useBus()
|
||||
|
||||
const getMonaco = () => window.monaco
|
||||
const getEditor = () => editor!
|
||||
@@ -32,7 +31,7 @@ export default defineComponent({
|
||||
model = getMonaco().editor.createModel(value, undefined, getMonaco().Uri.parse(uri))
|
||||
model.onDidChangeContent(() => {
|
||||
const value = model.getValue()
|
||||
bus.emit('monaco.change-value', { uri, value })
|
||||
triggerHook('MONACO_CHANGE_VALUE', { uri, value })
|
||||
})
|
||||
}
|
||||
|
||||
@@ -51,13 +50,13 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
function initMonaco () {
|
||||
bus.emit('monaco.before-init', { monaco: getMonaco() })
|
||||
triggerHook('MONACO_BEFORE_INIT', { monaco: getMonaco() })
|
||||
|
||||
editor = getMonaco().editor.create(refEditor.value, defaultOptions)
|
||||
setModel(toUri(null), '')
|
||||
|
||||
setTimeout(() => {
|
||||
bus.emit('monaco.ready', { editor: getEditor(), monaco: getMonaco() })
|
||||
triggerHook('MONACO_READY', { editor: getEditor(), monaco: getMonaco() })
|
||||
}, 500)
|
||||
}
|
||||
|
||||
|
||||
@@ -45,8 +45,7 @@ import { computed, defineComponent, nextTick, onBeforeUnmount, onMounted, ref, t
|
||||
import { extname } from '@fe/utils/path'
|
||||
import { isElectron } from '@fe/support/env'
|
||||
import { markdown } from '@fe/services/markdown'
|
||||
import { triggerHook } from '@fe/core/hook'
|
||||
import { useBus } from '@fe/core/bus'
|
||||
import { registerHook, removeHook, triggerHook } from '@fe/core/hook'
|
||||
import { registerAction, removeAction } from '@fe/core/action'
|
||||
import { revealLineInCenter } from '@fe/services/editor'
|
||||
import { showExport } from '@fe/services/document'
|
||||
@@ -65,7 +64,6 @@ export default defineComponent({
|
||||
name: 'xview',
|
||||
components: { Render, SvgIcon },
|
||||
setup () {
|
||||
const bus = useBus()
|
||||
const store = useStore()
|
||||
|
||||
const pinOutline = ref(false)
|
||||
@@ -131,13 +129,13 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
function handleRender () {
|
||||
triggerHook('ON_VIEW_RENDER', { getViewDom })
|
||||
triggerHook('VIEW_RENDER', { getViewDom })
|
||||
}
|
||||
|
||||
function handleRendered () {
|
||||
updateOutline()
|
||||
updateTodoCount()
|
||||
triggerHook('ON_VIEW_RENDERED', { getViewDom })
|
||||
triggerHook('VIEW_RENDERED', { getViewDom })
|
||||
}
|
||||
|
||||
function render () {
|
||||
@@ -153,12 +151,12 @@ export default defineComponent({
|
||||
const renderDebonce = debounce(render, 100, { leading: true })
|
||||
|
||||
async function keydownHandler (e: KeyboardEvent) {
|
||||
triggerHook('ON_VIEW_KEY_DOWN', e, getViewDom()!)
|
||||
triggerHook('VIEW_KEY_DOWN', { e, view: getViewDom()! }, { breakable: true })
|
||||
}
|
||||
|
||||
function handleScroll (e: any) {
|
||||
scrollTop.value = e.target.scrollTop
|
||||
triggerHook('ON_VIEW_SCROLL', e)
|
||||
scrollTop.value = e.target.scrollTop || 0
|
||||
triggerHook('VIEW_SCROLL', { e })
|
||||
}
|
||||
|
||||
function syncScroll (line: number) {
|
||||
@@ -175,11 +173,11 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
function handleDbClick (e: MouseEvent) {
|
||||
triggerHook('ON_VIEW_ELEMENT_DBCLICK', e, getViewDom()!)
|
||||
triggerHook('VIEW_ELEMENT_DBCLICK', { e, view: getViewDom()! }, { breakable: true })
|
||||
}
|
||||
|
||||
async function handleClick (e: MouseEvent) {
|
||||
triggerHook('ON_VIEW_ELEMENT_CLICK', e, getViewDom()!)
|
||||
triggerHook('VIEW_ELEMENT_CLICK', { e, view: getViewDom()! }, { breakable: true })
|
||||
}
|
||||
|
||||
function revealLine (line: number) {
|
||||
@@ -209,18 +207,18 @@ export default defineComponent({
|
||||
function refresh () {
|
||||
logger.debug('refresh')
|
||||
renderDebonce()
|
||||
triggerHook('ON_VIEW_REFRESH', { getViewDom })
|
||||
triggerHook('VIEW_REFRESH', { getViewDom })
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(renderDebonce)
|
||||
triggerHook('ON_VIEW_MOUNTED', { getViewDom })
|
||||
triggerHook('VIEW_MOUNTED', { getViewDom })
|
||||
registerAction({ name: 'view.refresh', handler: refresh })
|
||||
registerAction({ name: 'view.reveal-line', handler: revealLine })
|
||||
registerAction({ name: 'view.scroll-top-to', handler: scrollTopTo })
|
||||
registerAction({ name: 'view.get-content-html', handler: getContentHtml })
|
||||
registerHook('GLOBAL_RESIZE', resizeHandler)
|
||||
window.addEventListener('keydown', keydownHandler, true)
|
||||
bus.on('global.resize', resizeHandler)
|
||||
resizeHandler()
|
||||
})
|
||||
|
||||
@@ -229,15 +227,15 @@ export default defineComponent({
|
||||
removeAction('view.reveal-line')
|
||||
removeAction('view.scroll-top-to')
|
||||
removeAction('view.get-content-html')
|
||||
removeHook('GLOBAL_RESIZE', resizeHandler)
|
||||
window.removeEventListener('keydown', keydownHandler)
|
||||
bus.off('global.resize', resizeHandler)
|
||||
})
|
||||
|
||||
watch(() => currentContent.value + filePath.value, () => autoPreview.value && renderDebonce())
|
||||
watch(filePath, () => {
|
||||
// 切换文件后,开启自动预览
|
||||
toggleAutoPreview(true)
|
||||
triggerHook('ON_VIEW_FILE_CHANGE', { getViewDom })
|
||||
triggerHook('VIEW_FILE_CHANGE', { getViewDom })
|
||||
})
|
||||
|
||||
return {
|
||||
|
||||
@@ -26,8 +26,9 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onBeforeUnmount, ref } from 'vue'
|
||||
import { hookAction } from '@fe/core/action'
|
||||
import { getMenus, MenuItem } from '@fe/services/status-bar'
|
||||
import { registerHook, removeHook } from '@fe/core/hook'
|
||||
import type { BuildInActionName } from '@fe/types'
|
||||
import SvgIcon from './SvgIcon.vue'
|
||||
|
||||
export default defineComponent({
|
||||
@@ -55,13 +56,16 @@ export default defineComponent({
|
||||
}, 0)
|
||||
}
|
||||
|
||||
const updateMenu = () => {
|
||||
list.value = getMenus(props.position)
|
||||
const updateMenu = ({ name }: { name: BuildInActionName }) => {
|
||||
if (name === 'status-bar.refresh-menu') {
|
||||
list.value = getMenus(props.position)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const cleanup = hookAction('before-run', 'status-bar.refresh-menu', updateMenu)
|
||||
registerHook('ACTION_BEFORE_RUN', updateMenu as any)
|
||||
onBeforeUnmount(() => {
|
||||
cleanup()
|
||||
removeHook('ACTION_BEFORE_RUN', updateMenu as any)
|
||||
})
|
||||
|
||||
return {
|
||||
|
||||
@@ -67,13 +67,13 @@ export default defineComponent({
|
||||
await createDoc({ repo: props.item.repo }, props.item)
|
||||
}
|
||||
|
||||
async function select (item: Components.Tree.Node) {
|
||||
if (item.type !== 'dir') {
|
||||
if (extensions.supported(item.name)) {
|
||||
switchDoc(item)
|
||||
async function select (node: Components.Tree.Node) {
|
||||
if (node.type !== 'dir') {
|
||||
if (extensions.supported(node.name)) {
|
||||
switchDoc(node)
|
||||
} else {
|
||||
if (!(await triggerHook('ON_TREE_NODE_SELECT', item))) {
|
||||
openInOS(item)
|
||||
if (!(await triggerHook('TREE_NODE_SELECT', { node }, { breakable: true }))) {
|
||||
openInOS(node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,11 +13,11 @@ import { defineComponent, nextTick, onBeforeMount, onBeforeUnmount, ref } from '
|
||||
import { useStore } from 'vuex'
|
||||
import { Terminal } from 'xterm'
|
||||
import { FitAddon } from 'xterm-addon-fit'
|
||||
import { useBus } from '@fe/core/bus'
|
||||
import { getLogger } from '@fe/utils'
|
||||
import { registerHook, removeHook } from '@fe/core/hook'
|
||||
import { registerAction, removeAction } from '@fe/core/action'
|
||||
import { $args, FLAG_DEMO, FLAG_DISABLE_XTERM } from '@fe/support/args'
|
||||
import { toggleXterm } from '@fe/services/layout'
|
||||
import { registerAction, removeAction } from '@fe/core/action'
|
||||
import { getLogger } from '@fe/utils'
|
||||
import { getColorScheme } from '@fe/services/theme'
|
||||
import { OneHalfLight, OneHalfDark } from 'xterm-theme'
|
||||
import SvgIcon from './SvgIcon.vue'
|
||||
@@ -30,7 +30,6 @@ export default defineComponent({
|
||||
name: 'xterm',
|
||||
components: { SvgIcon },
|
||||
setup () {
|
||||
const bus = useBus()
|
||||
const store = useStore()
|
||||
|
||||
const refXterm = ref<HTMLElement | null>(null)
|
||||
@@ -84,8 +83,8 @@ export default defineComponent({
|
||||
|
||||
xterm.open(refXterm.value!)
|
||||
fitAddon.fit()
|
||||
bus.on('theme.change', changeTheme)
|
||||
bus.on('global.resize', fitXterm)
|
||||
registerHook('THEME_CHANGE', changeTheme)
|
||||
registerHook('GLOBAL_RESIZE', fitXterm)
|
||||
|
||||
if (FLAG_DEMO) {
|
||||
const message = 'DEMO 模式终端不可用'
|
||||
@@ -182,6 +181,8 @@ export default defineComponent({
|
||||
removeAction('xterm.run-code')
|
||||
removeAction('xterm.run')
|
||||
removeAction('xterm.init')
|
||||
removeHook('THEME_CHANGE', changeTheme)
|
||||
removeHook('GLOBAL_RESIZE', fitXterm)
|
||||
})
|
||||
|
||||
return {
|
||||
|
||||
@@ -4,7 +4,6 @@ import * as plugin from '@fe/core/plugin'
|
||||
import * as hook from '@fe/core/hook'
|
||||
import * as action from '@fe/core/action'
|
||||
import * as command from '@fe/core/command'
|
||||
import { useBus } from '@fe/core/bus'
|
||||
import { useToast } from '@fe/support/ui/toast'
|
||||
import { useModal } from '@fe/support/ui/modal'
|
||||
import * as env from '@fe/support/env'
|
||||
@@ -45,7 +44,6 @@ const ctx = {
|
||||
lib,
|
||||
env,
|
||||
utils,
|
||||
bus: useBus(),
|
||||
ui: { useToast, useModal },
|
||||
registerHook: hook.registerHook,
|
||||
removeHook: hook.removeHook,
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { getLogger } from '@fe/utils'
|
||||
import { useBus } from '@fe/core/bus'
|
||||
import { BuildInActions, BuildInActionName } from '@fe/types'
|
||||
import { registerCommand, removeCommand } from './command'
|
||||
import { triggerHook } from './hook'
|
||||
|
||||
const logger = getLogger('action')
|
||||
const bus = useBus()
|
||||
|
||||
export type ActionHandler<T extends string> = T extends BuildInActionName ? BuildInActions[T] : (...args: any[]) => any
|
||||
export type HookType = 'before-run' | 'after-run'
|
||||
@@ -33,17 +32,6 @@ export interface Action<T extends string> {
|
||||
|
||||
const actions: { [id: string]: Action<string> } = {}
|
||||
|
||||
/**
|
||||
* Hook 一个 Action
|
||||
* @param type 钩子类型
|
||||
* @param name Action 名
|
||||
* @param handler 处理方法
|
||||
*/
|
||||
export function hookAction (type: HookType, name: BuildInActionName, handler: (payload: any) => void) {
|
||||
bus.on(`action.${type}.${name}` as any, handler)
|
||||
return () => bus.off(`action.${type}.${name}` as any, handler)
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册一个 Action
|
||||
* @param action Action
|
||||
@@ -72,7 +60,7 @@ export function getActionHandler <T extends string> (name: T): ActionHandler<T>
|
||||
export function getActionHandler <T extends string> (name: T): ActionHandler<T> {
|
||||
logger.debug('getActionHandler', name)
|
||||
return ((...args: any[]) => {
|
||||
bus.emit(`action.before-run.${name}` as any, args)
|
||||
triggerHook('ACTION_BEFORE_RUN', { name }, { breakable: true })
|
||||
|
||||
let result: any
|
||||
|
||||
@@ -83,7 +71,7 @@ export function getActionHandler <T extends string> (name: T): ActionHandler<T>
|
||||
}
|
||||
}
|
||||
|
||||
bus.emit(`action.after-run.${name}` as any, result)
|
||||
triggerHook('ACTION_AFTER_RUN', { name }, { breakable: true })
|
||||
return result
|
||||
}) as ActionHandler<T>
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
import type { BuildInEvents } from '@fe/types'
|
||||
import mitt, { Emitter, WildcardHandler } from 'mitt'
|
||||
|
||||
const emitter = mitt()
|
||||
|
||||
// debug
|
||||
// emitter.on('*', (type, payload) => {
|
||||
// console.log('debug bus >', type, payload)
|
||||
// })
|
||||
|
||||
export type BuildInEventType = keyof BuildInEvents
|
||||
export type Handler<T = any> = (event: T) => void;
|
||||
|
||||
export type BuildInEventTypeWithoutPayload = { [K in keyof BuildInEvents]: BuildInEvents[K] extends never ? K : never }[keyof BuildInEvents]
|
||||
export type BuildInEventTypeWithPayload = keyof Omit<BuildInEvents, BuildInEventTypeWithoutPayload>
|
||||
|
||||
export interface XEmitter extends Emitter {
|
||||
once<T extends BuildInEventType>(type: T, handler: Handler<BuildInEvents[T]>): void;
|
||||
once(type: '*', handler: WildcardHandler): void;
|
||||
on<T extends BuildInEventType>(type: T, handler: Handler<BuildInEvents[T]>): void;
|
||||
on(type: '*', handler: WildcardHandler): void;
|
||||
off<T extends BuildInEventType>(type: T, handler: Handler<BuildInEvents[T]>): void;
|
||||
off(type: '*', handler: WildcardHandler): void;
|
||||
emit<T extends BuildInEventTypeWithPayload>(type: T, event: BuildInEvents[T]): void;
|
||||
emit<T extends BuildInEventTypeWithoutPayload>(type: T): void;
|
||||
emit(type: '*', event?: any): void;
|
||||
}
|
||||
|
||||
(emitter as any).once = (type: any, handler: any) => {
|
||||
const wrappedHandler = (evt: any) => {
|
||||
handler(evt)
|
||||
emitter.off(type, wrappedHandler)
|
||||
}
|
||||
emitter.on(type, wrappedHandler)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一个事件总线
|
||||
* @returns 事件总线
|
||||
*/
|
||||
export function useBus () {
|
||||
return emitter as XEmitter
|
||||
}
|
||||
|
||||
export default function install () {
|
||||
window.globalBus = emitter
|
||||
}
|
||||
@@ -2,7 +2,10 @@ import type { BuildInHookTypes } from '@fe/types'
|
||||
import { getLogger } from '@fe/utils'
|
||||
|
||||
export type HookType = keyof BuildInHookTypes
|
||||
export type HookFun<T extends any[]> = (...args: T) => boolean | void | Promise<boolean | void>
|
||||
export type HookFun<T> = (arg: T) => boolean | void | Promise<boolean | void>
|
||||
|
||||
export type HookTypeWithoutPayload = { [K in keyof BuildInHookTypes]: BuildInHookTypes[K] extends never ? K : never }[keyof BuildInHookTypes]
|
||||
export type HookTypeWithPayload = keyof Omit<BuildInHookTypes, HookTypeWithoutPayload>
|
||||
|
||||
const logger = getLogger('hook')
|
||||
|
||||
@@ -36,17 +39,26 @@ export function removeHook<T extends HookType> (type: T, fun: HookFun<BuildInHoo
|
||||
/**
|
||||
* 触发一个钩子
|
||||
* @param type 钩子类型
|
||||
* @param args 参数
|
||||
* @param arg 参数
|
||||
* @returns 所有钩子执行结果
|
||||
*/
|
||||
export async function triggerHook<T extends HookType> (type: T, ...args: BuildInHookTypes[T]) {
|
||||
logger.debug('triggerHook', type, args)
|
||||
export async function triggerHook<T extends HookTypeWithoutPayload> (type: T): Promise<void>
|
||||
export async function triggerHook<T extends HookTypeWithPayload> (type: T, arg: BuildInHookTypes[T], options?: { breakable?: boolean }): Promise<boolean>
|
||||
export async function triggerHook<T extends HookType> (type: T, arg?: BuildInHookTypes[T], options?: { breakable?: boolean }): Promise<boolean | void> {
|
||||
logger.debug('triggerHook', type, arg)
|
||||
for (const { fun, once } of (hooks[type] || ([] as any))) {
|
||||
once && removeHook(type, fun)
|
||||
if (await fun(...args)) {
|
||||
return true
|
||||
if (options?.breakable) {
|
||||
if (await fun(arg)) {
|
||||
logger.debug('triggerHook', 'break', fun)
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
fun(arg)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
if (options?.breakable) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import { createApp } from 'vue'
|
||||
import App from '@fe/App.vue'
|
||||
import router from '@fe/router'
|
||||
|
||||
import bus from '@fe/core/bus'
|
||||
import store from '@fe/support/store'
|
||||
import toast from '@fe/support/ui/toast'
|
||||
import modal from '@fe/support/ui/modal'
|
||||
@@ -12,7 +11,6 @@ import contextmenu from '@fe/support/ui/context-menu'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(bus)
|
||||
app.use(store)
|
||||
app.use(router)
|
||||
app.use(toast)
|
||||
|
||||
@@ -6,7 +6,7 @@ import store from '@fe/support/store'
|
||||
export default {
|
||||
name: 'copy-text',
|
||||
register: (ctx) => {
|
||||
ctx.registerHook('ON_VIEW_ELEMENT_CLICK', async (e: MouseEvent) => {
|
||||
ctx.registerHook('VIEW_ELEMENT_CLICK', async ({ e }) => {
|
||||
const target = e.target as HTMLElement
|
||||
|
||||
const preventEvent = () => {
|
||||
|
||||
@@ -57,19 +57,19 @@ export default {
|
||||
updateMenu()
|
||||
}
|
||||
|
||||
ctx.bus.on('doc.switched', (file?: Doc | null) => {
|
||||
if (file) {
|
||||
if (!ctx.doc.isSameFile(stack[idx], file)) {
|
||||
ctx.registerHook('DOC_SWITCHED', ({ doc }) => {
|
||||
if (doc) {
|
||||
if (!ctx.doc.isSameFile(stack[idx], doc)) {
|
||||
stack.splice(idx + 1, stack.length)
|
||||
stack.push({ type: file.type, repo: file.repo, name: file.name, path: file.path })
|
||||
stack.push({ type: doc.type, repo: doc.repo, name: doc.name, path: doc.path })
|
||||
idx = stack.length - 1
|
||||
}
|
||||
}
|
||||
updateMenu()
|
||||
})
|
||||
|
||||
ctx.bus.on('doc.deleted', removeFromStack)
|
||||
ctx.bus.on('doc.moved', ({ oldDoc }) => removeFromStack(oldDoc))
|
||||
ctx.registerHook('DOC_DELETED', ({ doc }) => removeFromStack(doc))
|
||||
ctx.registerHook('DOC_MOVED', ({ oldDoc }) => removeFromStack(oldDoc))
|
||||
|
||||
ctx.action.registerAction({
|
||||
name: backId,
|
||||
|
||||
@@ -34,7 +34,7 @@ async function pasteImage (file: File, asBase64: boolean) {
|
||||
throw new Error('当前未打开文件')
|
||||
}
|
||||
|
||||
if (!(await triggerHook('ON_EDITOR_PASTE_IMAGE', file))) {
|
||||
if (!(await triggerHook('EDITOR_PASTE_IMAGE', { file }, { breakable: true }))) {
|
||||
const assetPath = await upload(file, store.state.currentFile)
|
||||
insert(`})\n`)
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ export default {
|
||||
}
|
||||
})
|
||||
|
||||
ctx.registerHook('ON_EDITOR_PASTE_IMAGE', async (file: File) => {
|
||||
ctx.registerHook('EDITOR_PASTE_IMAGE', async ({ file }) => {
|
||||
if (!ctx.setting.getSettings()[settingKeyPaste]) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ let viewer: any
|
||||
export default {
|
||||
name: 'image-viewer',
|
||||
register: ctx => {
|
||||
ctx.registerHook('ON_VIEW_RENDERED', debounce(({ getViewDom }) => {
|
||||
ctx.registerHook('VIEW_RENDERED', debounce(({ getViewDom }) => {
|
||||
if (!viewer) {
|
||||
viewer = new Viewer(getViewDom(), {
|
||||
zIndex: 299999,
|
||||
|
||||
@@ -3,7 +3,7 @@ import { defineComponent, h, ref, watch } from 'vue'
|
||||
import { Plugin } from '@fe/context'
|
||||
import { buildSrc, IFrame } from '@fe/support/embed'
|
||||
import * as api from '@fe/support/api'
|
||||
import { useBus } from '@fe/core/bus'
|
||||
import { triggerHook } from '@fe/core/hook'
|
||||
import { openWindow } from '@fe/support/env'
|
||||
|
||||
const Drawio = defineComponent({
|
||||
@@ -13,7 +13,6 @@ const Drawio = defineComponent({
|
||||
content: String
|
||||
},
|
||||
setup (props) {
|
||||
const bus = useBus()
|
||||
const srcdoc = ref('')
|
||||
const refIFrame = ref<any>()
|
||||
|
||||
@@ -29,7 +28,7 @@ const Drawio = defineComponent({
|
||||
iframe.height = iframe.contentDocument.documentElement.offsetHeight + 'px'
|
||||
iframe.contentDocument.body.style.height = iframe.contentDocument.body.clientHeight + 'px'
|
||||
iframe.contentDocument.documentElement.style.height = '100%'
|
||||
bus.emit('global.resize')
|
||||
triggerHook('GLOBAL_RESIZE')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,9 +176,9 @@ export default {
|
||||
register: ctx => {
|
||||
ctx.markdown.registerPlugin(MarkdownItPlugin)
|
||||
|
||||
ctx.registerHook('ON_TREE_NODE_SELECT', async (item) => {
|
||||
if (item.path.toLowerCase().endsWith('.drawio')) {
|
||||
const srcdoc = await buildSrcdoc({ content: '', ...item })
|
||||
ctx.registerHook('TREE_NODE_SELECT', async ({ node }) => {
|
||||
if (node.path.toLowerCase().endsWith('.drawio')) {
|
||||
const srcdoc = await buildSrcdoc({ content: '', ...node })
|
||||
openWindow(buildSrc(srcdoc, '查看图形'))
|
||||
|
||||
return true
|
||||
|
||||
@@ -101,14 +101,14 @@ export default {
|
||||
`)
|
||||
|
||||
ctx.markdown.registerPlugin(EChartsPlugin)
|
||||
ctx.registerHook('ON_VIEW_RENDERED', () => {
|
||||
ctx.registerHook('VIEW_RENDERED', () => {
|
||||
update()
|
||||
})
|
||||
ctx.registerHook('ON_DOC_BEFORE_EXPORT', () => {
|
||||
ctx.registerHook('DOC_BEFORE_EXPORT', () => {
|
||||
preparePrint() // 转换成图片形式,设置主题
|
||||
setTimeout(() => update(), 0) // 恢复
|
||||
})
|
||||
|
||||
ctx.bus.on('theme.change', () => update())
|
||||
ctx.registerHook('THEME_CHANGE', () => update())
|
||||
}
|
||||
} as Plugin
|
||||
|
||||
@@ -153,7 +153,7 @@ function convertLink (state: StateCore) {
|
||||
export default {
|
||||
name: 'markdown-link',
|
||||
register: (ctx) => {
|
||||
ctx.registerHook('ON_VIEW_ELEMENT_CLICK', async (e, view) => {
|
||||
ctx.registerHook('VIEW_ELEMENT_CLICK', async ({ e, view }) => {
|
||||
const target = e.target as HTMLElement
|
||||
|
||||
const preventEvent = () => {
|
||||
|
||||
@@ -428,9 +428,9 @@ export default {
|
||||
name: 'markdown-luckysheet',
|
||||
register: ctx => {
|
||||
ctx.markdown.registerPlugin(MarkdownItPlugin)
|
||||
ctx.registerHook('ON_TREE_NODE_SELECT', async (item: Doc) => {
|
||||
if (item.path.toLowerCase().endsWith(fileExt)) {
|
||||
const srcdoc = buildSrcdoc(item.repo, item.path, true)
|
||||
ctx.registerHook('TREE_NODE_SELECT', async ({ node }) => {
|
||||
if (node.path.toLowerCase().endsWith(fileExt)) {
|
||||
const srcdoc = buildSrcdoc(node.repo, node.path, true)
|
||||
openWindow(buildSrc(srcdoc, '编辑表格', false), '_blank', { alwaysOnTop: false })
|
||||
|
||||
return true
|
||||
|
||||
@@ -38,6 +38,6 @@ export default {
|
||||
}
|
||||
`)
|
||||
ctx.markdown.registerPlugin(MermaidPlugin)
|
||||
ctx.registerHook('ON_VIEW_RENDERED', () => mermaid.init('.mermaid'))
|
||||
ctx.registerHook('VIEW_RENDERED', () => mermaid.init('.mermaid'))
|
||||
}
|
||||
} as Plugin
|
||||
|
||||
@@ -30,7 +30,7 @@ export default {
|
||||
}
|
||||
})
|
||||
|
||||
ctx.registerHook('ON_VIEW_ELEMENT_CLICK', async (e: MouseEvent) => {
|
||||
ctx.registerHook('VIEW_ELEMENT_CLICK', async ({ e }) => {
|
||||
const target = e.target as HTMLElement
|
||||
|
||||
const preventEvent = () => {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { debounce } from 'lodash-es'
|
||||
import type { Plugin } from '@fe/context'
|
||||
import type { Doc } from '@fe/types'
|
||||
import { sleep } from '@fe/utils'
|
||||
|
||||
export default {
|
||||
@@ -29,8 +28,8 @@ export default {
|
||||
}
|
||||
|
||||
// 切换文件后恢复滚动位置
|
||||
ctx.bus.on('doc.switched', async (file?: Doc | null) => {
|
||||
if (file) {
|
||||
ctx.registerHook('DOC_SWITCHED', async ({ doc }) => {
|
||||
if (doc) {
|
||||
await sleep(0)
|
||||
|
||||
const key = ctx.doc.toUri(ctx.store.state.currentFile)
|
||||
@@ -62,14 +61,14 @@ export default {
|
||||
})
|
||||
|
||||
const savePosition = debounce(saveScrollPosition, 500)
|
||||
ctx.registerHook('ON_VIEW_SCROLL', (e: WheelEvent) => {
|
||||
ctx.registerHook('VIEW_SCROLL', ({ e }) => {
|
||||
if (ctx.store.state.currentFile?.status) {
|
||||
const { scrollTop } = e.target as HTMLElement
|
||||
savePosition({ view: scrollTop })
|
||||
}
|
||||
})
|
||||
|
||||
ctx.registerHook('ON_VIEW_ELEMENT_CLICK', async (e: MouseEvent) => {
|
||||
ctx.registerHook('VIEW_ELEMENT_CLICK', async ({ e }) => {
|
||||
const target = e.target as HTMLElement
|
||||
|
||||
if (
|
||||
|
||||
@@ -184,9 +184,9 @@ export default {
|
||||
return false
|
||||
}
|
||||
|
||||
ctx.registerHook('ON_VIEW_ELEMENT_DBCLICK', e => handleClick(e, false))
|
||||
ctx.registerHook('ON_VIEW_ELEMENT_CLICK', e => handleClick(e, true))
|
||||
ctx.registerHook('ON_VIEW_RENDERED', ({ getViewDom }) => {
|
||||
ctx.registerHook('VIEW_ELEMENT_DBCLICK', ({ e }) => handleClick(e, false))
|
||||
ctx.registerHook('VIEW_ELEMENT_CLICK', ({ e }) => handleClick(e, true))
|
||||
ctx.registerHook('VIEW_RENDERED', ({ getViewDom }) => {
|
||||
const view: HTMLElement = getViewDom()!
|
||||
view.querySelectorAll('.yank-table-cell').forEach(td => {
|
||||
(td as HTMLElement).title = '双击编辑'
|
||||
|
||||
@@ -80,7 +80,7 @@ async function transformAll () {
|
||||
refreshTree()
|
||||
}
|
||||
|
||||
async function handleClick (e: MouseEvent) {
|
||||
async function handleClick ({ e }: { e: MouseEvent }) {
|
||||
const target = e.target as HTMLElement
|
||||
if (target.tagName !== 'IMG') {
|
||||
return false
|
||||
@@ -118,8 +118,8 @@ export default {
|
||||
handler: null
|
||||
})
|
||||
|
||||
ctx.registerHook('ON_VIEW_ELEMENT_CLICK', handleClick)
|
||||
ctx.registerHook('ON_VIEW_RENDERED', ({ getViewDom }) => {
|
||||
ctx.registerHook('VIEW_ELEMENT_CLICK', handleClick)
|
||||
ctx.registerHook('VIEW_RENDERED', ({ getViewDom }) => {
|
||||
refView = getViewDom()!
|
||||
})
|
||||
|
||||
|
||||
@@ -5,13 +5,12 @@ import { useToast } from '@fe/support/ui/toast'
|
||||
import store from '@fe/support/store'
|
||||
import type { Doc } from '@fe/types'
|
||||
import { basename, dirname, isBelongTo, join } from '@fe/utils/path'
|
||||
import { useBus } from '@fe/core/bus'
|
||||
import { triggerHook } from '@fe/core/hook'
|
||||
import * as api from '@fe/support/api'
|
||||
import { getLogger } from '@fe/utils'
|
||||
import { inputPassword } from './base'
|
||||
|
||||
const logger = getLogger('document')
|
||||
const bus = useBus()
|
||||
|
||||
function decrypt (content: any, password: string) {
|
||||
if (!password) {
|
||||
@@ -139,7 +138,7 @@ export async function createDoc (doc: Optional<Pick<Doc, 'repo' | 'path' | 'cont
|
||||
|
||||
await api.writeFile(file, file.content)
|
||||
|
||||
bus.emit('doc.created', file)
|
||||
triggerHook('DOC_CREATED', { doc: file })
|
||||
} catch (error: any) {
|
||||
useToast().show('warning', error.message)
|
||||
console.error(error)
|
||||
@@ -192,7 +191,7 @@ export async function deleteDoc (doc: Doc) {
|
||||
if (confirm) {
|
||||
await api.deleteFile(doc)
|
||||
|
||||
bus.emit('doc.deleted', doc)
|
||||
triggerHook('DOC_DELETED', { doc })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,7 +243,7 @@ export async function moveDoc (doc: Doc, newPath?: string) {
|
||||
|
||||
await api.moveFile(doc, newPath)
|
||||
|
||||
bus.emit('doc.moved', { oldDoc: doc, newDoc })
|
||||
triggerHook('DOC_MOVED', { oldDoc: doc, newDoc })
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -283,7 +282,7 @@ export async function saveDoc (doc: Doc, content: string) {
|
||||
contentHash: hash,
|
||||
status: 'saved'
|
||||
})
|
||||
bus.emit('doc.saved', store.state.currentFile!)
|
||||
triggerHook('DOC_SAVED', { doc: store.state.currentFile! })
|
||||
} catch (error: any) {
|
||||
store.commit('setCurrentFile', { ...doc, status: 'save-failed' })
|
||||
useToast().show('warning', error.message)
|
||||
@@ -335,7 +334,7 @@ export async function switchDoc (doc: Doc | null) {
|
||||
try {
|
||||
if (!doc) {
|
||||
store.commit('setCurrentFile', null)
|
||||
bus.emit('doc.switched', null)
|
||||
triggerHook('DOC_SWITCHED', { doc: null })
|
||||
return
|
||||
}
|
||||
|
||||
@@ -363,9 +362,9 @@ export async function switchDoc (doc: Doc | null) {
|
||||
status: 'loaded'
|
||||
})
|
||||
|
||||
bus.emit('doc.switched', store.state.currentFile)
|
||||
triggerHook('DOC_SWITCHED', { doc: store.state.currentFile })
|
||||
} catch (error: any) {
|
||||
bus.emit('doc.switch-failed', { doc, message: error.message })
|
||||
triggerHook('DOC_SWITCH_FAILED', { doc, message: error.message })
|
||||
useToast().show('warning', error.message.includes('Malformed') ? '密码错误' : error.message)
|
||||
throw error
|
||||
}
|
||||
@@ -377,7 +376,7 @@ export async function switchDoc (doc: Doc | null) {
|
||||
*/
|
||||
export async function markDoc (doc: Doc) {
|
||||
await api.markFile(doc)
|
||||
bus.emit('doc.changed', doc)
|
||||
triggerHook('DOC_CHANGED', { doc })
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -386,7 +385,7 @@ export async function markDoc (doc: Doc) {
|
||||
*/
|
||||
export async function unmarkDoc (doc: Doc) {
|
||||
await api.unmarkFile(doc)
|
||||
bus.emit('doc.changed', doc)
|
||||
triggerHook('DOC_CHANGED', { doc })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import * as Monaco from 'monaco-editor'
|
||||
import { FLAG_READONLY } from '@fe/support/args'
|
||||
import { isElectron } from '@fe/support/env'
|
||||
import { useBus } from '@fe/core/bus'
|
||||
import { registerHook, triggerHook } from '@fe/core/hook'
|
||||
import { registerAction } from '@fe/core/action'
|
||||
import { Alt } from '@fe/core/command'
|
||||
import { getColorScheme } from './theme'
|
||||
import { registerAction } from '../core/action'
|
||||
import { Alt } from '../core/command'
|
||||
|
||||
const bus = useBus()
|
||||
|
||||
let monaco: typeof Monaco
|
||||
let editor: Monaco.editor.IStandaloneCodeEditor
|
||||
@@ -61,9 +59,7 @@ export function whenEditorReady (): Promise<{ editor: typeof editor, monaco: typ
|
||||
}
|
||||
|
||||
return new Promise(resolve => {
|
||||
bus.once('editor.ready', payload => {
|
||||
resolve(payload)
|
||||
})
|
||||
registerHook('EDITOR_READY', resolve)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -171,9 +167,7 @@ export function toggleWrap () {
|
||||
|
||||
registerAction({ name: 'editor.toggle-wrap', handler: toggleWrap, keys: [Alt, 'w'] })
|
||||
|
||||
bus.on('monaco.before-init', (payload: any) => {
|
||||
monaco = payload.monaco
|
||||
|
||||
registerHook('MONACO_BEFORE_INIT', ({ monaco }) => {
|
||||
monaco.editor.defineTheme('vs', {
|
||||
base: 'vs',
|
||||
inherit: true,
|
||||
@@ -195,17 +189,17 @@ bus.on('monaco.before-init', (payload: any) => {
|
||||
})
|
||||
})
|
||||
|
||||
bus.on('monaco.ready', (payload) => {
|
||||
registerHook('MONACO_READY', (payload) => {
|
||||
monaco = payload.monaco
|
||||
editor = payload.editor
|
||||
|
||||
bus.emit('editor.ready', payload)
|
||||
triggerHook('EDITOR_READY', payload)
|
||||
})
|
||||
|
||||
bus.on('monaco.change-value', payload => {
|
||||
bus.emit('editor.change', payload)
|
||||
registerHook('MONACO_CHANGE_VALUE', payload => {
|
||||
triggerHook('EDITOR_CHANGE', payload)
|
||||
})
|
||||
|
||||
bus.on('theme.change', () => {
|
||||
registerHook('THEME_CHANGE', () => {
|
||||
monaco?.editor.setTheme(getColorScheme() === 'dark' ? 'vs-dark' : 'vs')
|
||||
})
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
import { nextTick } from 'vue'
|
||||
import store from '@fe/support/store'
|
||||
import { useBus } from '@fe/core/bus'
|
||||
import { getActionHandler, registerAction } from '../core/action'
|
||||
import { Alt } from '../core/command'
|
||||
import { triggerHook } from '@fe/core/hook'
|
||||
import { getActionHandler, registerAction } from '@fe/core/action'
|
||||
import { Alt } from '@fe/core/command'
|
||||
import * as view from './view'
|
||||
|
||||
const bus = useBus()
|
||||
|
||||
/**
|
||||
* 下一个 tick 抛出 resize 事件
|
||||
*/
|
||||
export function emitResize () {
|
||||
nextTick(() => bus.emit('global.resize'))
|
||||
nextTick(() => triggerHook('GLOBAL_RESIZE'))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { useBus } from '@fe/core/bus'
|
||||
import { triggerHook } from '@fe/core/hook'
|
||||
import type { ThemeName } from '@fe/types'
|
||||
import * as storage from '@fe/utils/storage'
|
||||
|
||||
const bus = useBus()
|
||||
|
||||
/**
|
||||
* 获取当前主题设置
|
||||
* @returns 主题名
|
||||
@@ -38,7 +36,7 @@ export function getColorScheme () {
|
||||
*/
|
||||
export function setTheme (name: ThemeName) {
|
||||
document.documentElement.setAttribute('app-theme', name)
|
||||
bus.emit('theme.change', name)
|
||||
triggerHook('THEME_CHANGE', { name })
|
||||
storage.set('app.theme', name)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useBus } from '@fe/core/bus'
|
||||
import { Escape } from '@fe/core/command'
|
||||
import { triggerHook } from '@fe/core/hook'
|
||||
import { getActionHandler, registerAction } from '@fe/core/action'
|
||||
import { useToast } from '@fe/support/ui/toast'
|
||||
import store from '@fe/support/store'
|
||||
@@ -10,7 +10,7 @@ function present (flag: boolean) {
|
||||
}
|
||||
store.commit('setPresentation', flag)
|
||||
setTimeout(() => {
|
||||
useBus().emit('global.resize')
|
||||
triggerHook('GLOBAL_RESIZE')
|
||||
}, 0)
|
||||
}
|
||||
|
||||
|
||||
+8
-12
@@ -1,7 +1,6 @@
|
||||
import { useBus } from '@fe/core/bus'
|
||||
import { isElectron, nodeRequire } from '@fe/support/env'
|
||||
import { init } from '@fe/core/plugin'
|
||||
import { triggerHook } from '@fe/core/hook'
|
||||
import { registerHook, triggerHook } from '@fe/core/hook'
|
||||
import store from '@fe/support/store'
|
||||
import * as storage from '@fe/utils/storage'
|
||||
import { basename } from '@fe/utils/path'
|
||||
@@ -16,8 +15,6 @@ import ctx from '@fe/context'
|
||||
|
||||
init(plugins, ctx)
|
||||
|
||||
const bus = useBus()
|
||||
|
||||
function getLastOpenFile (repoName?: string): Doc | null {
|
||||
const currentFile = storage.get<Doc>('currentFile')
|
||||
const recentOpenTime = storage.get('recentOpenTime', {}) as {[key: string]: number}
|
||||
@@ -49,7 +46,7 @@ function getLastOpenFile (repoName?: string): Doc | null {
|
||||
}
|
||||
|
||||
export default function startup () {
|
||||
triggerHook('ON_STARTUP')
|
||||
triggerHook('STARTUP')
|
||||
|
||||
// 在 Electron 环境中开启缩放页面功能
|
||||
if (isElectron) {
|
||||
@@ -89,13 +86,12 @@ export default function startup () {
|
||||
const doc = getLastOpenFile()
|
||||
switchDoc(doc)
|
||||
|
||||
bus.on('doc.created', refreshTree)
|
||||
bus.on('doc.deleted', refreshTree)
|
||||
bus.on('doc.moved', refreshTree)
|
||||
bus.on('doc.changed', refreshTree)
|
||||
bus.on('doc.switch-failed', refreshTree)
|
||||
|
||||
bus.on('doc.switch-failed', (payload?: { doc?: Doc | null, message: string }) => {
|
||||
registerHook('DOC_CREATED', refreshTree)
|
||||
registerHook('DOC_DELETED', refreshTree)
|
||||
registerHook('DOC_MOVED', refreshTree)
|
||||
registerHook('DOC_CHANGED', refreshTree)
|
||||
registerHook('DOC_SWITCH_FAILED', refreshTree)
|
||||
registerHook('DOC_SWITCH_FAILED', (payload?: { doc?: Doc | null, message: string }) => {
|
||||
if (payload && payload.doc && payload?.message?.indexOf('NOENT')) {
|
||||
unmarkDoc(payload.doc)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { debounce } from 'lodash-es'
|
||||
import { defineComponent, h, IframeHTMLAttributes, nextTick, onBeforeMount, onBeforeUnmount, PropType, ref, watch } from 'vue'
|
||||
import { useBus } from '@fe/core/bus'
|
||||
import { md5 } from '@fe/utils'
|
||||
import { registerHook, removeHook } from '@fe/core/hook'
|
||||
import { registerHook, removeHook, triggerHook } from '@fe/core/hook'
|
||||
import type { ThemeName } from '@fe/types'
|
||||
|
||||
/**
|
||||
* 构建一个嵌入页面的 src 路径
|
||||
@@ -46,7 +46,7 @@ export const IFrame = defineComponent({
|
||||
onBeforeMount(update)
|
||||
watch(props, debounce(update, props.debounce))
|
||||
|
||||
const changeTheme = (name?: string) => {
|
||||
const changeTheme = ({ name }: { name: ThemeName }) => {
|
||||
if (name) {
|
||||
iframe.value?.contentDocument?.documentElement.setAttribute('app-theme', name)
|
||||
}
|
||||
@@ -57,23 +57,21 @@ export const IFrame = defineComponent({
|
||||
nextTick(update)
|
||||
}
|
||||
|
||||
const bus = useBus()
|
||||
bus.on('theme.change', changeTheme)
|
||||
|
||||
registerHook('ON_VIEW_REFRESH', refresh)
|
||||
registerHook('ON_VIEW_FILE_CHANGE', refresh)
|
||||
registerHook('THEME_CHANGE', changeTheme)
|
||||
registerHook('VIEW_REFRESH', refresh)
|
||||
registerHook('VIEW_FILE_CHANGE', refresh)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
bus.off('theme.change', changeTheme)
|
||||
removeHook('ON_VIEW_REFRESH', refresh)
|
||||
removeHook('ON_VIEW_FILE_CHANGE', refresh)
|
||||
removeHook('THEME_CHANGE', changeTheme)
|
||||
removeHook('VIEW_REFRESH', refresh)
|
||||
removeHook('VIEW_FILE_CHANGE', refresh)
|
||||
})
|
||||
|
||||
const onLoad = function () {
|
||||
const frame = iframe.value!
|
||||
const resize = () => {
|
||||
frame.height = frame.contentDocument!.documentElement.scrollHeight + 'px'
|
||||
bus.emit('global.resize')
|
||||
triggerHook('GLOBAL_RESIZE')
|
||||
}
|
||||
|
||||
const win = frame.contentWindow as any
|
||||
|
||||
+32
-33
@@ -84,23 +84,6 @@ export namespace Components {
|
||||
|
||||
export type ThemeName = 'system' | 'dark' | 'light'
|
||||
|
||||
export type BuildInEvents = {
|
||||
'global.resize': never,
|
||||
'theme.change': ThemeName,
|
||||
'monaco.change-value': { uri: string, value: string },
|
||||
'monaco.before-init': { monaco: typeof Monaco },
|
||||
'monaco.ready': { editor: Monaco.editor.IStandaloneCodeEditor, monaco: typeof Monaco },
|
||||
'editor.ready': { editor: Monaco.editor.IStandaloneCodeEditor, monaco: typeof Monaco },
|
||||
'editor.change': { uri: string, value: string },
|
||||
'doc.created': Doc,
|
||||
'doc.deleted': Doc,
|
||||
'doc.moved': { oldDoc: Doc, newDoc: Doc },
|
||||
'doc.saved': Doc,
|
||||
'doc.switched': Doc | null,
|
||||
'doc.switch-failed': { doc?: Doc | null, message: string },
|
||||
'doc.changed': Doc,
|
||||
}
|
||||
|
||||
export type BuildInSettings = {
|
||||
'repos': { name: string, path: string }[],
|
||||
'theme': ThemeName,
|
||||
@@ -110,22 +93,6 @@ export type BuildInSettings = {
|
||||
'plugin.image-hosting-picgo.enable-paste-image': boolean
|
||||
}
|
||||
|
||||
export type BuildInHookTypes = {
|
||||
ON_STARTUP: [],
|
||||
ON_EDITOR_PASTE_IMAGE: [File],
|
||||
ON_VIEW_ELEMENT_CLICK: [MouseEvent, HTMLElement],
|
||||
ON_VIEW_ELEMENT_DBCLICK: [MouseEvent, HTMLElement],
|
||||
ON_VIEW_KEY_DOWN: [KeyboardEvent, HTMLElement],
|
||||
ON_VIEW_SCROLL: [WheelEvent],
|
||||
ON_VIEW_RENDER: [{ getViewDom: ()=> HTMLElement | null }],
|
||||
ON_VIEW_RENDERED: [{ getViewDom: ()=> HTMLElement | null }],
|
||||
ON_VIEW_MOUNTED: [{ getViewDom: ()=> HTMLElement | null }],
|
||||
ON_VIEW_FILE_CHANGE: [{ getViewDom: ()=> HTMLElement | null }],
|
||||
ON_VIEW_REFRESH: [{ getViewDom: ()=> HTMLElement | null }],
|
||||
ON_TREE_NODE_SELECT: [Components.Tree.Node],
|
||||
ON_DOC_BEFORE_EXPORT: [],
|
||||
}
|
||||
|
||||
export type BuildInActions = {
|
||||
'view.refresh': () => void,
|
||||
'view.reveal-line': (line: number) => void,
|
||||
@@ -161,6 +128,38 @@ export type BuildInActions = {
|
||||
|
||||
export type BuildInActionName = keyof BuildInActions
|
||||
|
||||
export type BuildInHookTypes = {
|
||||
STARTUP: never,
|
||||
GLOBAL_RESIZE: never,
|
||||
ACTION_BEFORE_RUN: { name: string },
|
||||
ACTION_AFTER_RUN: { name: string }
|
||||
THEME_CHANGE: { name: ThemeName },
|
||||
EDITOR_PASTE_IMAGE: { file: File },
|
||||
VIEW_ELEMENT_CLICK: { e: MouseEvent, view: HTMLElement },
|
||||
VIEW_ELEMENT_DBCLICK: { e: MouseEvent, view: HTMLElement },
|
||||
VIEW_KEY_DOWN: { e: KeyboardEvent, view: HTMLElement },
|
||||
VIEW_SCROLL: { e: WheelEvent },
|
||||
VIEW_RENDER: { getViewDom: ()=> HTMLElement | null },
|
||||
VIEW_RENDERED: { getViewDom: ()=> HTMLElement | null },
|
||||
VIEW_MOUNTED: { getViewDom: ()=> HTMLElement | null },
|
||||
VIEW_FILE_CHANGE: { getViewDom: ()=> HTMLElement | null },
|
||||
VIEW_REFRESH: { getViewDom: ()=> HTMLElement | null },
|
||||
TREE_NODE_SELECT: { node: Components.Tree.Node },
|
||||
MONACO_CHANGE_VALUE : { uri: string, value: string },
|
||||
MONACO_BEFORE_INIT: { monaco: typeof Monaco },
|
||||
MONACO_READY: { editor: Monaco.editor.IStandaloneCodeEditor, monaco: typeof Monaco },
|
||||
EDITOR_READY: { editor: Monaco.editor.IStandaloneCodeEditor, monaco: typeof Monaco },
|
||||
EDITOR_CHANGE: { uri: string, value: string },
|
||||
DOC_CREATED: { doc: Doc },
|
||||
DOC_DELETED: { doc: Doc },
|
||||
DOC_MOVED: { oldDoc: Doc, newDoc: Doc },
|
||||
DOC_SAVED: { doc: Doc },
|
||||
DOC_SWITCHED: { doc: Doc | null },
|
||||
DOC_SWITCH_FAILED: { doc?: Doc | null, message: string },
|
||||
DOC_CHANGED: { doc: Doc },
|
||||
DOC_BEFORE_EXPORT: never,
|
||||
}
|
||||
|
||||
export type FrontMatterAttrs = {
|
||||
headingNumber?: boolean,
|
||||
enableMacro?: boolean,
|
||||
|
||||
Reference in New Issue
Block a user